This question covers when and why the typename
and template
disambiguators are needed in C++ template code.
Is it valid to use these disambiguators in cases where they are not needed in C++03? How about in C++11?
It's valid in conforming C++03/C++11 compilers, for some definition of "valid."
C++03 ISO/IEC 14882:2003 §14.2.5:
[ Note: just as is the case with the
typename
prefix, thetemplate
prefix is allowed in cases where it is not strictly necessary; i.e., when the expression on the left of the->
or.
, or the nested-name-specifier is not dependent on a template-parameter. ]
C++11 ISO/IEC 14882:2011 §14.2.5:
[ Note: As is the case with the
typename
prefix, thetemplate
prefix is allowed in cases where it is not strictly necessary; i.e., when the nested-name-specifier or the expression on the left of the->
or.
is not dependent on a template-parameter, or the use does not appear in the scope of a template. —end note ]
Note that you can't use template
when the member in question isn't actually a template—you aren't allow to lie with it. Also note that for typename
, the type has to be a qualified type (e.g. X::Y
, not just X
). C++11 also changed it so that you don't have to be in the scope of a template, whereas C++03 required you to be in a template. Also note that compilers are likely to differ on whether they actually let you do this. Under Clang, for instance, this warns under the flag -Wc++11-extensions
.
Here are some examples, assuming 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 produces 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.
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With