Reizo
Reizo

Reputation: 1437

Oddity of explicitly marking dependent names as typename and template

Please have a look at this code snippet:

template<typename T>
struct s {
    template<int Index>
    using type_alias = s<typename T::template identifier<Index>::type>;
};

This is compiling but only due to the explicit typename and template 'markers' for the dependent names at the s::type_alias type-alias.

I wonder about the following two things:

  1. Why do I need to explicitly mark T as typename? It is after all not a dependent name, but instead exactly a typename as specified in the template parameter list of s.
  2. Why can I only (optionally) mark type as template (i. e. s<typename T::template identifier<Index>::template type>) but not as typename? Ultimately, it is used as a typename template argument for s, so it does have to be a typename.

MSVC 19.25.28614 for x64 with /std:c++latest was used if that is relevant.


PS: Title and question are very specialized in its original version so don't hesitate to edit it if you find a way to generalize it somehow.

Upvotes: 0

Views: 62

Answers (1)

aschepler
aschepler

Reputation: 72291

In the syntax:

typename T::template identifier<Index>::type

the typename keyword isn't saying that T is a type - it's saying that the whole thing T::template identifier<Index>::type is a type. When it's not introducing a template parameter, typename always comes before a qualified-id, something containing at least one :: token like A::B::C, and says that the last name in that chain of names and :: tokens names a type.

On the other hand, the use of the template keyword to specify that a member name names a template always comes after a :: or . or -> token and immediately before the name which is a template.

So in this example, it's valid grammar to have T::template identifier<Index>::template type, but that doesn't make sense together with the preceding typename and the fact that s expects a type, not a template, as its template argument.

Upvotes: 1

Related Questions