Reputation: 1437
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:
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
.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
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