Reputation: 317
The following code
template <typename MemberType>
struct Holder {
static MemberType member;
};
template <typename MemberType>
auto Holder<MemberType>::member;
produces error C2371 in MSVS 2013 if we try to access Holder::member:
error C2371: 'member' : redefinition; different basic types
However, if in initialization we use template parameter name instead of 'auto' keyword
template <typename MemberType>
MemberType Holder<MemberType>::member;
it compiles as expected. So, what is the reason why compiler is unable to infer static member type in this case?
Upvotes: 1
Views: 703
Reputation: 96800
The declaration of a variable with a placeholder auto
/decltype(auto)
must have an initializer for the type of the variable to be deduced:
The type of a variable declared using
auto
ordecltype(auto)
is deduced from its initializer. This use is allowed when declaring variables in a block (6.3), in namespace scope (3.3.6), and in a for-init-statement (6.5.3).auto
ordecltype(auto)
shall appear as one of the decl-specifiers in the decl-specifier-seq and the decl-specifier-seq shall be followed by one or more init-declarators, each of which shall have a non-empty initializer.
Your example doesn't have an initializer for the definition, so your code is ill-formed.
The definition of a static member may have a placeholder, but the problem in your example has to do with the fact that you're using templates and the declaration of the static member is dependent on the template argument. For example, this definition won't compile:
template <typename MemberType>
auto Holder<MemberType>::member = 42; // error: redefinition of 'member' with
// a different type: 'int' vs 'MemberType'
Holder<MemberType>
causes an implicit instantiation where the compiler will look at the declaration of Holder<MemberType>::member
. The compiler doesn't know at the time of this instantiation whether the type deduced from the initializer (int
) matches MemberType
, which is why you get the strange error "int
vs MemberType
".
The above code works if you create an explicit specialization of the data member because MemberType
is known at the time of the instantiation:
template <>
auto Holder<int>::member = 42; // OK, decltype(42) matches int (MemberType)
Upvotes: 0