c++c++11templatesportability

Is it C++ standard-compliant to define a variable using `A<int>::template B<int> x;`?


The following code is accepted by gcc, vc++, and clang.

template<class T>
struct A
{
    template<class U>
    struct B
    {};
};

int main()
{
    A<int>::B<int> y; // OK as expected
    A<int>::template B<int> x; // Also OK! Is this standard-compliant?
};

Is it C++ standard-compliant to define a variable using A<int>::template B<int> x;?


Solution

  • Even though it is a non-normative note, I think an answer can be given by n3797[temp.names]/6

    As is the case with the typename prefix, the template 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.

    In the OP's example, the prefix template is used outside the scope of a template, and the preceding nested-name-specifier is not dependent. Therefore, the prefix template is not required, but allowed here.


    [expr.prim.general]/8

    qualified-id:
         nested-name-specifier templateopt   unqualified-id

    Plus [temp.names]/5

    A name prefixed by the keyword template shall be a template-id or the name shall refer to a class template.

    [temp.names]/1 says that B<int> is indeed a (simple-)template-id.