Это допустимо в соответствующих компиляторах C ++ 03 / C ++ 11 для некоторого определения «действительный».
C ++ 03 ISO / IEC 14882: 2003 §14.2.5:
[ Примечание: Как и в случае с префиксом typename
, префикс template
допускается в тех случаях, когда это не является строго обязательным;то есть, когда выражение слева от ->
или .
или спецификатор вложенного имени не зависит от шаблона-параметра .]
C ++ 11 ИСО / МЭК 14882: 2011 §14.2.5:
[ Примечание: Как и в случае с *Префикс 1024 *, префикс template
разрешен в случаях, когда это не является строго обязательным;то есть когда спецификатор вложенного имени или выражение слева от ->
или .
не зависит от шаблона-параметра , или использование непоявляются в объеме шаблона.- конец примечания ]
Обратите внимание, что вы не можете использовать template
, когда рассматриваемый элемент на самом деле не является шаблоном - вы не можете лгать с ним,Также обратите внимание, что для typename
тип должен быть квалифицированным типом (например, X::Y
, а не просто X
).C ++ 11 также изменил его, чтобы вам не нужно было находиться в области действия шаблона, тогда как C ++ 03 требовал, чтобы вы были в шаблоне.Также обратите внимание, что компиляторы могут различаться в зависимости от того, позволяют ли они делать это.Например, под Clang это предупреждает под флагом -Wc++11-extensions
.
Вот несколько примеров, предполагающих следующее определение:
struct X {
typedef int Y;
template <typename T> static void foo();
static void bar();
template <typename T> static void baz(T);
};
Недопустимо в обоих C ++ 03и 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.
}
Недопустимо в C ++ 03, допустимо в C ++ 11 (но выдает предупреждение для моей копии 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.
}
Действителени в C ++ 03, и в 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.
}