在这个问题之前,我从未在详细类型说明符中看到过嵌套名称说明符,乍一看,我认为语法甚至没有涵盖它。现在我看到,从 C++98 到现在,它被翻译为没有 typename-specifier 构造的特殊情况。 C++11 7.1.6.3/2(C++98 中的 7.1.5.3/2):
3.4.4 描述了如何在详细类型说明符中对标识符进行名称查找。如果 identifier 解析为 class-name 或 enum-name,则 elaborated-type-specifier 将其引入声明中,就像 simple-type-specifier 引入其 type-name 一样.
因此,虽然您可以形成合格的详细类型说明符,但您需要注意它永远不依赖于类型。在模板定义时按照 3.4.4 进行的名称解析永远不会找到类名,因为从属名称被假定为对象,除非以
typename
关键字为前缀,这在本上下文中在语法上是不允许的。
这是对标准含义和语言设计意图的准确评估吗?
从评论中扩展:
以这个程序为例:
template <typename T>
struct S1 { struct I { }; };
template <typename T>
struct S2 { typedef struct S1<T>::I I; }; // okay
template <typename T>
struct S3 { typedef struct S2<T>::I I; }; // okay at definition time
// usually error at instantiation time
template <>
struct S2<short> : S1<short> { };
int main() {
S1<int>::I a;
S2<int>::I &b = a; // okay
S3<int>::I &c = b; // error
S1<short>::I d;
S2<short>::I &e = d; // okay
S3<short>::I &f = e; // okay
}
在模板定义时,
S2
和S3
都可以:14.6p5列出了不需要typename
的例外情况。本质上:如果使用明确,因为名称只能是类型,则不需要 typename
。这包括语法上不允许使用 typename
的几种情况,因此需要 typename
就意味着无法编写程序。 typename struct S<T>::I
和 struct typename S<T>::I
都是硬错误,并且 struct S<T>::I
是明确的。
在模板实例化时,3.4.4的规则更加清晰:
struct S1<int>::I
和struct S2<int>::I
都可以找到,其中S2<int>::I
显然是一个typedef,因此struct S2<int>::I
是一个错误。同时,此时, S2<short>::I
被视为不是 typedef,而是一个结构体,因此 struct S2<short>::I
是允许的。