简体   繁体   English

将typename关键字与typedef和new一起使用

[英]Use of typename keyword with typedef and new

Consider this code, 考虑一下这段代码

template<class T>
struct Sample
{ 
     typename T::X *x; //declare pointer to T's X
};

In the above code, the keyword typename is required by the compiler, so that it can disambiguate between nested types and nested values in templates. 在上面的代码中,编译器需要关键字typename ,以便它可以在嵌套类型和模板中的嵌套值之间消除歧义。 That means, in the absence of typename keyword, compiler would interpret this as multiplication of T::X with x, 这意味着,在没有typename关键字的情况下,编译器会将此解释为T :: X与x的乘法,

T::X *x; //multiply T::X with x

So in such situations where ambiguity can arise, the keyword typename becomes necessity so as to remove ambiguities. 因此,在可能出现歧义的情况下,关键字typename变为必要 ,以便消除歧义。 But there are few situations when the context itself removes ambiguities. 但是,上下文本身消除歧义的情况很少。 The other topic discusses contexts of base-class and function-parameters (the latter doesn't remove ambiguity though). 另一个主题讨论了基类和函数参数的上下文(后者虽然没有消除歧义)。 In this topic, I particularly want to discuss other two contexts which seem to be unambiguous , but we're still required to write typename , 在本主题中,我特别想讨论其他两个似乎明确无误的上下文,但我们仍然需要编写typename

typedef typename T::X xtype;
pX = new typename T::X;  

In these two situations, the keywords typedef and new make it clear enough to the compiler that whatever follows is type , not value . 在这两种情况下,关键字typedefnew使编译器清楚地知道后面的内容是类型而不是

So my question is, why do compilers still need the typename keyword, even in unambiguous situations such as when we use typedef and new ? 所以我的问题是,为什么编译器仍然需要typename关键字,即使在明确的情况下,例如当我们使用typedefnew


EDIT (after reading this response from Johannes Schaub ) : 编辑(阅读Johannes Schaub的回复后):

//typedef NOT followed by a type!
int typedef A;

This syntax asks me to modify my question a little bit, so that the point which I'm trying to make, may be seen by others. 这种语法要求我稍微修改一下我的问题,以便我试图做出的观点可能会被其他人看到。

Consider this, 想想这个,

T::X typedef *x;

So from the context, it's still clear enough to the compiler that T::X is a type, no matter whether it appears before typedef ,or after typedef . 所以,从上下文,它仍然不够清楚,编译器T :: X是一种类型,无论它出现之前 typedef ,或之后 typedef Unless C++ allows us to write typedef 5 five or typedef T::value t_value (where T::value is value ), the presence of typedef itself removes all ambiguities and so, typename seems to be an unnecessary requirement by the Standard (in such situations) . 除非C ++允许我们编写typedef 5 fivetypedef T::value t_value (其中T :: value是value ), typedef本身的存在会消除所有歧义,因此, typename似乎是标准的一个不必要的要求(在此类情况) Same argument holds true for new as well. 同样的论点也适用于new


Also, I've written a class template which is using this struct as template argument: 另外,我编写了一个使用此结构作为模板参数的类模板:

struct A 
{
        struct X { string name; };
        static const int X = 100;
};

I particularly want to know if the following code (from the constructor) is correct (portable) or not, 我特别想知道以下代码(来自构造函数)是否正确(可移植),

//two interesting statements
 pX = new typename T::X; //T::X means struct X
 product = T::X * p; //but here, T::X means int X

The complete code is here at ideone. 完整的代码在这里是ideone。 Please have a look at it before replying. 请在回复之前先看一下。 :-) :-)

C++ syntax is more crazy than that. C ++语法比这更疯狂。

// typedef NOT followed by a type!
int typedef A;

// new NOT followed by a type!
new (0) int;

Others have commented about your example. 其他人评论了你的例子。 The typename specifier does not yield to lookup ignoring non-type names. typename说明符不会导致查找忽略非类型名称。 So if you say new typename T::X , and there is an object name X in T , it will still be found instead of the type name X (GCC however ignores non-type names in looking up a name after a typename . But that's not Standards compliant). 所以,如果你说的new typename T::X ,并且有一个对象名称XT ,它仍然会被发现,而不是类型名称X (GCC但是在照顾一个名字忽略非类型名称typename 。但是,这不符合标准)。


Answers to edits: 编辑答案:

Consider this, 想想这个,

 T::X typedef *x; 

So from the context, it's still clear enough to the compiler that T::X is a type, no matter whether it appears before typedef,or after typedef. 因此,从上下文来看,编译器仍然清楚T :: X是一种类型,无论它是出现在typedef之前还是出现在typedef之后。

The compiler has to know when the declaration specifiers and (ie the "type section" and when the declarator section start (ie the "names" section). There are declarations where the type section is empty: 编译器必须知道声明说明符的时间和(即“类型部分”以及声明者部分何时开始(即“名称”部分)。有声明类型部分为空的声明:

// constructor definitions don't need a type section
MyClass::MyClass() { }

// conversion function definitions don't need a type section
MyClass::operator int() { }

If the first name you specify is not a type, the type section ends, and the name section starts. 如果您指定的名字不是类型,则类型部分结束,名称部分开始。 Saying T::X tells the compiler: T::X告诉编译器:

Now I want to define T::X . 现在我想定义T::X

It reads from left to right, so it will think you forgot a semicolon when it then encounters the typedef . 它从左到右读取,因此当它遇到typedef时会认为你忘记了分号。 Inside classes the interpretation is slightly different but much like this too. 内部课程的解释略有不同,但也很像这样。 That's a simple and effective parse. 这是一个简单而有效的解析。

Same argument holds true for new as well. 同样的论点也适用于新的。

I tend to agree with you here. 我倾向于同意你的意见。 Syntactically it should be unambiguous if you leave off parentheses. 从语法上讲, 如果你不加括号,它应该是明确的。 As I've never written a C++ parser, there may be hidden pitfalls I'm not seeing, though. 由于我从未编写过C ++解析器,因此可能存在隐藏的陷阱,但我没有看到。

Every addition of typename in corner cases of the language like in new will potentially require substantial amount of design for both compilers and standards writers, while still requiring typename for the vast majority of other cases where it's needed. new的语言的typename情况下,每次添加typename都可能需要为编译器和标准编写者进行大量设计,同时仍然需要在绝大多数其他需要的情况下使用typename I don't think that this pays off. 我认为这不会带来回报。

Then why do compilers still need the typename keyword? 那为什么编译器仍然需要typename关键字?

Because the rules of the language are formulated in that way: every dependant name which is used in a type context must be preceeded by typename ( mutatis mutandis , the same thing holds for template name and template keyword). 因为语言的规则是以这种方式表达的:在类型上下文中使用的每个依赖名称必须以typename比照mutatis ,同样适用于模板名称和template关键字)。 Now, why the rules of the language don't make the difference between the cases where the typename is needed to remove the ambiguity and those where the context provides enough information? 现在,为什么语言规则不会在需要typename来消除歧义的情况和上下文提供足够信息的情况之间产生差异? Probably -- I wasn't there when the decision was made -- to keep the language description to be even more complex (consider the consequences of missing cases, one way or the other). 可能 - 在作出决定时我并不在场 - 保持语言描述更加复杂(考虑失踪案件的后果,不管是哪种方式)。

In your example, X isn't a type name (that possibility if for compatibility with C where tag name aren't automatically type name), so you need to yuse struct : 在您的示例中,X不是类型名称(如果与C兼容,那么标记名称不是自动类型名称的可能性),因此您需要使用struct

pX = new struct T::X;

Your code seems to go into a very gray area. 您的代码似乎进入了一个非常灰色的区域。

This paragraph on name hiding 名称隐藏的这一段

A class name (9.1) or enumeration name (7.2) can be hidden by the name of a variable, data member, function, or enumerator declared in the same scope. 类名(9.1)或枚举名(7.2)可以通过在同一范围内声明的变量,数据成员,函数或枚举器的名称隐藏。 If a class or enumeration name and a variable, data member, function, or enumerator are declared in the same scope (in any order) with the same name, the class or enumeration name is hidden wherever the variable, data member, function, or enumerator name is visible. 如果类或枚举名称和变量,数据成员,函数或枚举器在同一作用域(按任何顺序)中声明具有相同名称,则类或枚举名称将隐藏在变量,数据成员,函数或枚举器名称可见。

seems to indicate that the compiler is right to complain that A::X is not a type name. 似乎表明编译器抱怨A::X不是类型名称是正确的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM