将相关名称显式标记为类型名和模板的奇怪之处

Oddity of explicitly marking dependent names as typename and template

请看一下这段代码:

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

这正在编译,但只是由于在 s::type_alias type-alias.[=27 处的从属名称的显式 typenametemplate 'markers' =]

我想知道以下两件事:

  1. 为什么我需要将 T 明确标记为 typename?它毕竟 不是 依赖名称,而是 s.
  2. 的模板参数列表中指定的 typename
  3. 为什么我只能(可选)将 type 标记为 template(即 s<typename T::template identifier<Index>::template type>)而不是 typename?最终,它 用作 stypename 模板参数,因此它 确实 必须是 typename.
如果相关,则使用

MSVC 19.25.28614 for x64/std:c++latest


PS: 标题和问题在其原始版本中非常专业,因此如果您找到一种以某种方式概括它的方法,请不要犹豫对其进行编辑。

在语法中:

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

typename 关键字并不是说 T 是一种类型 - 它是说整个 T::template identifier<Index>::type 是一种类型。当它不引入模板参数时,typename 总是出现在 qualified-id 之前,其中至少包含一个 :: 标记,例如 A::B::C,并且表示该名称链中的姓氏和 :: 标记命名了一个类型。

另一方面,使用 template 关键字来指定成员名称命名模板总是在 ::.-> 之后标记和紧接在名称之前的模板。

所以在这个例子中,T::template identifier<Index>::template type 是有效的语法,但是与前面的 typenames 期望类型的事实一起没有意义,不是模板,作为它的模板参数。