Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 与typedef和new一起使用typename关键字_C++_Templates_Typedef_Language Lawyer_Typename - Fatal编程技术网

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

C++ 与typedef和new一起使用typename关键字,c++,templates,typedef,language-lawyer,typename,C++,Templates,Typedef,Language Lawyer,Typename,考虑一下这个代码 template<class T> struct Sample { typename T::X *x; //declare pointer to T's X }; 因此,在可能出现歧义的情况下,关键字typename会变成必要性,以消除歧义。但很少有情况下上下文本身会消除歧义。本文讨论了基类和函数参数的上下文(尽管后者并没有消除歧义)。在本主题中,我特别想讨论另外两个上下文,这两个上下文似乎是明确的,但我们仍然需要编写typename typedef

考虑一下这个代码

template<class T>
struct Sample
{ 
     typename T::X *x; //declare pointer to T's X
};
因此,在可能出现歧义的情况下,关键字
typename
会变成必要性,以消除歧义。但很少有情况下上下文本身会消除歧义。本文讨论了基类和函数参数的上下文(尽管后者并没有消除歧义)。在本主题中,我特别想讨论另外两个上下文,这两个上下文似乎是明确的,但我们仍然需要编写
typename

typedef typename T::X xtype;
pX = new typename T::X;  
在这两种情况下,关键字
typedef
new
向编译器清楚地表明,后面的内容都是type,而不是

所以我的问题是,为什么编译器仍然需要
typename
关键字,即使在明确的情况下,例如当我们使用
typedef
new


编辑(从中读取此响应后): 这个语法要求我稍微修改一下我的问题,以便其他人可以看到我试图表达的观点

想想这个,

T::X typedef *x;
T::X typedef *x;
因此,从上下文来看,编译器仍然很清楚,T::X是一个类型,无论它出现在
typedef
之前还是
typedef
之后<强> >除非C++允许我们编写TyBuffF 5五或<代码> TyPufT::值TyValue (其中t::value是value),存在“代码> TyPulf< /COD>本身消除了所有的模糊性,因此, Type NeNe/COD>似乎是标准(在这种情况下)不必要的要求。同样的参数也适用于
new


此外,我还编写了一个类模板,它使用此结构作为模板参数:

struct A 
{
        struct X { string name; };
        static const int X = 100;
};
我特别想知道以下代码(来自构造函数)是否正确(可移植)

完整的代码位于ideone。回复前请先看一看。:-)

那么为什么编译器仍然需要typename关键字呢

因为语言的规则是这样制定的:在类型上下文中使用的每个从属名称都必须在
typename
之前(经过必要的修改,模板名称和
template
关键字也是如此)。现在,为什么语言的规则不能区分需要类型名来消除歧义的情况和上下文提供足够信息的情况?可能——当做出决定时,我不在场——让语言描述变得更加复杂(考虑一下遗漏案例的后果,不管怎样)

在您的示例中,X不是类型名(如果为了与C兼容,标记名不会自动成为类型名,则可能会出现这种情况),因此您需要使用
struct

pX = new struct T::X;

您的代码似乎进入了一个非常灰色的区域

这一段是关于姓名隐藏的

类名(9.1)或枚举名 (7.2)可通过 变量、数据成员、函数或 在同一作用域中声明的枚举数。 如果类或枚举名称和 变量、数据成员、函数或 枚举数是在同一个 范围(以任何顺序)相同 名称,则类或枚举名称为 隐藏在变量、数据 成员、函数或枚举器名称 是可见的


似乎表明编译器抱怨
A::X
不是类型名是正确的。

C++语法比这更疯狂

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

// new NOT followed by a type!
new (0) int;
其他人对你的例子发表了评论。
typename
说明符不允许忽略非类型名称的查找。因此,如果您说
newtypename T::X
,并且在
T
中有一个对象名
X
,它仍然会被找到,而不是类型名
X
(GCC在
typename
后查找名称时忽略非类型名。但这不符合标准)


编辑答案:

想想这个,

T::X typedef *x;
T::X typedef *x;
因此,从上下文来看,编译器仍然很清楚T::X是一个类型,无论它出现在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++解析器,但是可能有隐藏的陷阱,我看不到。
在该语言的角落案例中,如在
new
中,每次添加
typename
,都可能需要编译器和标准编写器进行大量的设计,而在其他绝大多数需要的案例中,仍然需要
typename
。我认为这是没有回报的。

他的问题是为什么编译器在
typedef
之后需要一个
typename
关键字。因为在
typedef
之后,它总是知道一个typeString是Commin。但是我认为这就是语法分析器的编写方式。@Pawel:问题是:为什么编译器在明确的情况下仍然需要typename关键字?这是编写语法分析器的规则syntax.it真的需要让它有意义吗?即使在typedef之后出现的内容也应该是一个类型。所以你必须给它命名。编译器永远不知道typedef之后会有什么问题
// constructor definitions don't need a type section
MyClass::MyClass() { }

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