我在this question之前从未在详细说明类型说明符中看到嵌套名称说明符,乍一看我以为它甚至没有被语法覆盖。现在我看到,从C ++ 98到现在,它被翻译为没有 typename-specifier 构造的特殊情况。 C ++ 11 7.1.6.3/2(C ++ 98中的7.1.5.3/2):
3.4.4描述了如何在 elaborated-type-specifier 中对标识符进行名称查找。如果标识符解析为类名或枚举名, elaborated-type-specifier 会引入它进入声明的方式与 simple-type-specifier 引入其类型名称的方式相同。
因此,虽然你可以形成一个合格的详细类型说明符,但你需要注意它从不依赖于类型。模板定义时每3.4.4的名称解析将永远不会找到类名,因为除非前缀为typename
关键字,否则依赖名称将被假定为对象,在此上下文中不允许使用语法。
这是对标准含义和语言设计意图的准确评估吗?
答案 0 :(得分:3)
从评论中扩展:
以此程序为例:
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,所以{ {1}}是一个错误。同时,在此时,struct S2<int>::I
被视为不是typedef,而是结构,因此允许S2<short>::I
。