check this out:
template <class T>
class Test: public T
{
public:
void TestFunc()
{
T::SubClass bob;
}
};
this fails when compiling for iPhone (expected ';' before 'bob'). works on other platforms
this is a simplified example of what we are actually trying to do, which is inherit from an std::map<> and inside that class, create an iterator.
Very often encountered issue. Put typename
:
template <class T>
class Test: public T
{
public:
void TestFunc()
{
typename T::SubClass bob;
}
};
T::SubClass
is a dependent name. While parsing the template, the compiler doesn't know yet whether it will be a type. For still being able to parse it (and collect information won thereby), it assumes it is not a type. But then, the line must be an expression, and misses an operator between the two names. typename
will tell it the name is a type, and the line then becomes a declaration.
It may not be apparent why it fails above because the whole line cannot be an expression. But there are other situation where this isn't possible to decide on the form of the whole statement:
T::SubClass * bob;
Is that a multiplication, or a pointer declaration? The compiler will assume it is a multiplication. If later when instantiating the template it figures out that T::SubClass
names a type, it will rise an error message. typename
will also here tell the compiler to parse this as a declaration instead of an expression (by taking T::SubClass
as a type).
Notice some compilers may still work without typename
(if i remember right, the MSVC compiler is one of them). I think this should come with the restriction that those compilers won't do two-phase name lookup: They will parse the complete template at instantiation time, and all names, even those that were not visible in the definition of the template, will be found (as opposed to what the Standard says, that treats name lookup at definition/instantiation differently).
Visit the Template FAQ for further assistance: C++ Templates FAQ