6

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;?

xmllmx
  • 39,765
  • 26
  • 162
  • 323
  • B is a template-dependent type template, so the second syntax is perfectly correct. – Quentin Jul 04 '14 at 14:59
  • Could you refer me to the page of the standard that specifies this usage? Thanks. – xmllmx Jul 04 '14 at 15:00
  • 3
    @peppe Not a duplicate, because you do not need to use `template` here. – juanchopanza Jul 04 '14 at 15:04
  • @MikeSeymour oh. So it would only be the case with, say, `A::template B` within a scope with a template parameter `W` ? – Quentin Jul 04 '14 at 15:04
  • 1
    @Quentin: Indeed; it's needed in a dependent context, when the interpretation of the name depends on unknown template parameters. Here, it's not needed, since the template has been specialised and we know exactly what `B` is in that specialiation. (Sorry, I had brief second thoughts and removed my comment saying that it's not dependent here). – Mike Seymour Jul 04 '14 at 15:07
  • @MikeSeymour Thank you very much ! I'll sleep wiser tonight :) – Quentin Jul 04 '14 at 15:09

1 Answers1

12

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.

dyp
  • 38,334
  • 13
  • 112
  • 177
  • It all is valid for C++11+, not for C++98/03. Am I right? – Constructor Jul 04 '14 at 19:29
  • 2
    @Constructor In C++03, you could use the keyword `template` even if the *nested-type-name* is not dependent; but you were not allowed to use it outside the scope of templates. – dyp Jul 04 '14 at 20:33