考虑这段代码,
template<class T>
struct Sample
{
typename T::X *x; //declare pointer to T's X
};
在上面的代码中,编译器需要关键字typename
,以便它可以消除模板中嵌套类型和嵌套值之间的歧义。这意味着,在没有typename
关键字的情况下,编译器会将此解释为T :: X与x的乘法,
T::X *x; //multiply T::X with x
因此,在可能出现歧义的情况下,关键字typename
变为必需,以消除歧义。但是,上下文本身消除歧义的情况很少。 other topic讨论了基类和函数参数的上下文(后者虽然没有消除歧义)。在本主题中,我特别想讨论其他两个似乎明确的上下文,但我们仍然需要编写typename
,
typedef typename T::X xtype;
pX = new typename T::X;
在这两种情况下,关键字typedef
和new
使编制者清楚地知道后面的内容是 type ,不是 < EM>值。
所以我的问题是,为什么编译器仍需要typename
关键字,即使在明确的情况下,例如我们使用typedef
和new
时?
//typedef NOT followed by a type!
int typedef A;
这种语法要求我稍微修改一下我的问题,以便我可以看到其他人看到的问题。
考虑一下,
T::X typedef *x;
所以从上下文来看,编译器仍然清楚T :: X是一个类型,无论它出现在 typedef
之前,还是之后> em> typedef
。 除非C ++允许我们编写typedef 5 five
或typedef T::value t_value
(其中T :: value是 value ),typedef
本身的存在会消除所有歧义,所以,typename
似乎是标准的必要条件(在这种情况下)。同样的论点也适用于new
。
另外,我编写了一个使用此结构作为模板参数的类模板:
struct A
{
struct X { string name; };
static const int X = 100;
};
我特别想知道以下代码(来自构造函数)是否正确(可移植),
//two interesting statements
pX = new typename T::X; //T::X means struct X
product = T::X * p; //but here, T::X means int X
完整代码在ideone处为here。请在回复之前先看一下。 : - )
答案 0 :(得分:14)
C ++语法比这更疯狂。
// typedef NOT followed by a type!
int typedef A;
// new NOT followed by a type!
new (0) int;
其他人评论了你的例子。 typename
说明符不会导致查找忽略非类型名称。因此,如果您说new typename T::X
,并且X
中有一个对象名称T
,则仍会找到它而不是类型名称X
(但GCC会忽略非类型在typename
之后查找名称的名称。但这不符合标准)。
编辑答案:
考虑一下,
T::X typedef *x;
所以从上下文来看,编译器仍然清楚T :: X是一个类型,无论它是出现在typedef之前还是出现在typedef之后。
编译器必须知道声明说明符的时间和(即“类型部分”以及声明者部分何时开始(即“名称”部分)。有声明类型部分为空的声明:
// constructor definitions don't need a type section
MyClass::MyClass() { }
// conversion function definitions don't need a type section
MyClass::operator int() { }
如果您指定的名字不是类型,则类型部分结束,名称部分开始。说T::X
告诉编译器:
现在我要定义
T::X
。
它从左到右读取,因此当它遇到typedef
时会认为你忘记了分号。内部课程的解释略有不同,但也很像这样。这是一个简单而有效的解析。
同样的论点也适用于新的。
我倾向于同意你的意见。从语法上来说,它应该是明确的如果你不用括号。由于我从未编写过C ++解析器,因此可能存在隐藏的陷阱,但我没有看到。
typename
语言的每一个new
的添加都可能需要为编译器和标准编写者设计大量的设计,而绝大多数仍然需要typename
其他需要的情况。我认为这不会带来回报。
答案 1 :(得分:0)
那为什么编译器仍然需要typename关键字?
因为语言的规则是以这种方式表达的:在类型上下文中使用的每个从属名称必须在typename
之前( mutatis mutandis ,同样适用于模板名称和template
关键字)。现在,为什么语言规则不会在需要typename来消除歧义的情况和上下文提供足够信息的情况之间产生差异?可能 - 在作出决定时我不在场 - 保持语言描述更加复杂(考虑失踪案件的后果,不管是哪种方式)。
在您的示例中,X不是类型名称(如果与C兼容,则标签名称不是自动类型名称的可能性),因此您需要使用struct
:
pX = new struct T::X;
答案 2 :(得分:0)
您的代码似乎进入了一个非常灰暗的区域。
关于名字隐藏的这一段
类名(9.1)或枚举名称 (7.2)可以隐藏一个名字 变量,数据成员,函数或 枚举器在同一范围内声明。 如果是类或枚举名称和 变量,数据成员,函数或 枚举器声明在同一个 范围(以任何顺序)与相同 name,类或枚举名称是 隐藏在变量,数据的任何地方 成员,函数或枚举器名称 是可见的。
似乎表明编译器抱怨A::X
不是类型名称是正确的。