#include <string>
template <class StringType>
class mytype
{
struct mybase
{
using Type = StringType;
};
class mychild : public mybase
{
typename Type somevalue;
};
};
int main()
{
mytype<std::string> mt;
}
It produces this error:
error C3646: 'somevalue': unknown override specifier
message : see reference to class template instantiation 'mytype::mychild' being compiled
message : see reference to class template instantiation 'mytype' being compiled
error C4430: missing type specifier - int assumed. Note: C does not support default-int
Why is this not allowed?
CodePudding user response:
mybase
is a dependent base class, because you could add arbitrary specializations of mytype<T>::mybase
for some type T
, so that it has different members.
Therefore the compiler cannot know at the point of definition of mychild
that Type
is a member of the base class. You could specialize it later to not have a Type
member for some specializations. But the compiler needs to know whether Type
is a type or not to parse the declaration. Names are not looked in dependent base classes for this reason.
You need to tell the compiler that you are sure that Type
is a member of the base class and that it is a type, not something else:
class mychild : public mybase
{
typename mybase::Type somevalue;
};
The typename
here indicates to the compiler that the nested Type
is really a type, since it can't look this up in the dependent base class at the point of definition for the reasons stated above.
If you then do specialize mytype<T>::mybase
in such a way that it doesn't contain Type
or Type
is not a type, then instantiation of the corresponding mytype<T>::myclass
will fail.
typename
only makes sense before a nested name. If the name is not nested, then either it is not dependent and so can simply be looked up immediately (as the case in your example) or it is a member of the current instantiation, in which case the compiler also can be sure whether it is a type or not with a lookup in the template definition. typename
before an unqualified name is a syntax error. (Aside from its other meaning in a template parameter.)