It is valid according to the C ++ 03 / C ++ 11 compilers, for some definition of "valid."
C ++ 03 ISO / IEC 14882: 2003 §14.2.5:
[Note: as with the typename prefix, the template prefix is allowed in cases where this is not strictly necessary; that is, when the expression to the left of -> or . or the naming specifier is independent of the template parameter. ]
C ++ 11 ISO / IEC 14882: 2011 §14.2.5:
[Note. As with the typename prefix, the template prefix is allowed in cases where this is not strictly necessary; that is, when the nested name specifier or expression to the left of -> or . independent of the template parameter, or usage is not displayed in the template area. -end note]
Please note that you cannot use template when this element is not actually a template - you cannot lie with it. Also note that for typename type must be a qualified type (for example, X::Y , not just X ). C ++ 11 also changed it so that you do not need to be within the framework of the template, while C ++ 03 required you to be in the template. Also note that compilers are likely to differ in whether they really allow you to do this. For example, under Clang, this warns under the flag -Wc++11-extensions .
Here are a few examples with the following definition:
struct X { typedef int Y; template <typename T> static void foo(); static void bar(); template <typename T> static void baz(T); };
Invalid in both C ++ 03 and C ++ 11:
template <typename T> void foo() { typename int z = 0;
Invalid in C ++ 03, valid in C ++ 11 (but throws a warning on my copy of Clang):
void bar() { typename X::Y z = 0;
Valid in both C ++ 03 and C ++ 11:
template <typename T> void baz() { typename X::Y z = 0;