The short version that you need to do typename X::Y
whenever X is or depends on a template parameter. Until X is known, the compiler can't tell if Y is a type or a value. So you have to add typename
to specify that it is a type.
For example:
template <typename T>
struct Foo {
typename T::some_type x; // T is a template parameter. `some_type` may or may not exist depending on what type T is.
};
template <typename T>
struct Foo {
typename some_template<T>::some_type x; // `some_template` may or may not have a `some_type` member, depending on which specialization is used when it is instantiated for type `T`
};
As sbi points out in the comments, the cause of the ambiguity is that Y
might be a static member, an enum or a function. Without knowing the type of X
, we can't tell.
The standard specifies that the compiler should assume it is a value unless it is explicitly labelled a type by using the typename
keyword.
And it sounds like the commenters really want me to mention another related case as well: ;)
If the dependant name is a function member template, and you call it with an explicit template argument (foo.bar<int>()
, for example), you have to add the template
keyword before the function name, as in foo.template bar<int>()
.
The reason for this is that without the template keyword, the compiler assumes that bar
is a value, and you wish to invoke the less than operator (operator<
) on it.