虽然discussing Type(identifier);
语法及其声明如何,但我发现Type(::x);
没有与Clang合作。我希望给定一个全局变量x
,它会将::x
视为表达式(::x + 2
起作用)并将::x
强制转换为Type
。但是,它会产生编译错误。
以下是a short example:
int x;
int main() {
int(::x); //does not compile
int(::x + 2); //compiles
}
Clang 3.5给出的编译器错误是:
然而,GCC 4.9.0编译就好了。这段代码有效吗?错误:'x'的定义或重新声明无法命名全局范围
答案 0 :(得分:19)
据我所知,draft C++ standard部分8.3
声明者的含义段 6 表示(强调)我的前进):
在声明T D中,D的格式为
(D1)
包含的declarator-id的类型与包含的declarator-id的类型相同 宣言
T D1
括号不会改变嵌入式声明符id的类型,但它们可以改变复杂的绑定 说明符。
这样:
int(::x);
相当于:
int ::x ;
显然无效,这也会产生相同的错误。所以gcc 4.9
在这里不正确,但由于这在后来发布的gcc 4.8.3
中看起来已修复,我希望在4.9
的后续版本中也可以修复此问题。虽然我在gcc 4.8.3 bugs fixed list中没有看到与此问题有任何明显匹配,但他们并未声称这是完整列表。
第二种情况是功能显式类型转换,在5.2.3
显式类型转换(功能表示法)一节中有所描述:
简单类型说明符(7.1.6.2)或typename-specifier(14.6) 后面跟一个带括号的表达式列表构造一个值 给定表达式列表的指定类型。如果表达式列表是a 单表达式,类型转换表达式是等价的(in 定义,如果在意义上定义)到相应的演员 表达式(5.4)。[...]
这是明确的,因为::x + 2
是表达式。
当声明被视为声明或表达时,涵盖的部分是6.8
歧义解决,其中包含:
涉及表达式语句的语法含糊不清 和声明:具有函数样式的表达式语句 显式类型转换(5.2.3),因为它最左边的子表达式可以 与第一个声明者开始的声明无法区分 a(。在这些情况下,声明是声明。 [注意:To 消除歧义,整个声明可能需要进行审查 确定它是表达式语句还是声明。这个 消除许多例子的歧义。
并提供以下示例:
T(a)->m = 7; // expression-statement T(a)++; // expression-statement T(a,5)<<c; // expression-statement T(*d)(int); // declaration T(e)[5]; // declaration T(f) = { 1, 2 }; // declaration T(*g)(double(3)); // declaration
注意:如果()
不是T ::D
,那么T
是 qualified-id ,如果5.1
是类,这是clang
主要表达式的语法所涵盖的。
更新
gcc的回应是:
当前G ++和EDG都将其视为有效表达式(int):: x
由于此回复意味着gcc
不正确(我不同意),我提交的clang bug report和older bug report看似相似似乎不同意clang bug report
回复。
更新2
回应gcc
理查德史密斯的同意,这应该被视为声明并说:
这并不意味着铿锵不正确;事实上,Clang是正确的 在这里,据我所见。 (我还向EDG发送了一份错误报告。)
那就是说,我们应该给你一个正确的解决方案,这里有一个令人烦恼的解析,这里是怎样的 消除歧义&#39;在这种情况下出错。
更新3
{{1}} confirms这是一个错误。
答案 1 :(得分:11)
对我来说,这看起来是最令人烦恼的解析。如果可以将其解析为声明。第一个可以解析为int变量(int ::x;
)的声明,但::
在该上下文中是非法的。第二个有是一个表达式,因此编译器会进行数学运算,将其强制转换为int,并抛弃结果。
这是一个迂腐的问题,还是还有其他问题?如果您遇到了一个特定的问题,那么其他信息将为您的用例提供一种解决方法。