The following code compiles successfully with clang 3.5.0 and g++ 4.9.0 (with -Wall -Wextra -pedantic-errors
flags) under C++03 (flag -std=C++03
), C++11 (flag -std=C++11
), and C++14 (flag -std=C++14
):
namespace N
{
typedef int T;
enum E{};
}
template <typename N::T>
struct ST{};
template <typename N::E>
struct SE{};
int main()
{
}
Is it valid to add extra typename
keyword before a non-type template parameter declaration?
Note that the following code doesn't compile (as C++03, C++11, and C++14 code):
typedef int T;
enum E{};
template <typename T t>
struct ST{};
template <typename E e>
struct SE{};
int main()
{
}
But the following one compiles fine again (C++03, C++11, and C++14):
typedef int T;
enum E{};
template <typename ::T>
struct ST{};
template <typename ::E>
struct SE{};
int main()
{
}
It is allowed, but only with qualified names:
typename-specifier:
typename
nested-name-specifier identifier
typename
nested-name-specifiertemplate
opt simple-template-id
So typename E
is wrong according to the grammar. typename N::E
is not since the name is qualified. The third case, typename ::E
, is fine since ::
is a valid nested-name-specifier.
The C++03 standard specifies in [temp.res]/5 that
The keyword
typename
shall be applied only to qualified names, but those names need not be dependent.
The C++11 standard states this nowhere explicitly but inside a note in [temp.names]/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 ]
The same note exists in the exact same place in the C++14 standard.
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