Using the double-digit characters "pattern" and "type-name" when they are not needed

This question describes when and why the C ++ template template needs typename and template .

Is it possible to use these ambiguities in cases when they are not needed in C ++ 03? How about in C ++ 11?

+7
source share
1 answer

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; // int is not a qualified name. X::template bar(); // X::bar is not a template. X::template baz(z); // no template argument list. } 

Invalid in C ++ 03, valid in C ++ 11 (but throws a warning on my copy of Clang):

 void bar() { typename X::Y z = 0; // not in the body of a template, so X::template foo<int>(); // no possibility of dependent names. } 

Valid in both C ++ 03 and C ++ 11:

 template <typename T> void baz() { typename X::Y z = 0; // not a dependent name, so 'typename' X::template foo<int>(); // isn't strictly necessary. } 
+11
source

All Articles