g ++ rejects,clang ++ accepted:foo(x)(“bar”)(“baz”); [英] g++ rejects, clang++ accepts: foo(x)("bar")("baz");

查看:203
本文介绍了g ++ rejects,clang ++ accepted:foo(x)(“bar”)(“baz”);的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有人曾经要求另一天某些东西编译clang,但不是与gcc。我直观地了解发生了什么,并能够帮助的人,但它让我想知道 - 根据标准,哪个编译器是正确的?下面是一个代码的缩写版本:

Somebody had asked the other day why something compiles with clang, but not with gcc. I intuitively understood what was happening and was able to help the person, but it got me wondering -- according to the standard, which compiler was correct? Here is a boiled down version of the code:

#include <iostream>
#include <string>

class foo
{
public:
    foo(const std::string& x):
        name(x)
    { }
    foo& operator()(const std::string& x)
    {
        std::cout << name << ": " << x << std::endl;
        return (*this);
    }
    std::string name;
};

int main()
{
    std::string x = "foo";
    foo(x)("bar")("baz");
    return 0;
}

这与clang ++编译良好,但g ++给出以下错误:

This compiles fine with clang++, but g++ gives the following error:

runme.cpp: In function ‘int main()’:
runme.cpp:21:11: error: conflicting declaration ‘foo x’
    foo(x)("bar")("baz");
        ^
runme.cpp:20:17: error: ‘x’ has a previous declaration as ‘std::string x’
    std::string x = "foo";

如果我在第21行中添加一对括号,g ++很高兴:

If I add a pair of parentheses in line 21, g++ is happy:

(foo(x))("bar")("baz");

换句话说,g ++将此行解释为:

In other words, g++ interprets this line as:

foo x ("bar")("baz");

在g ++中嗅探它的错误,但是我想问一下标准专家,错误?

Methinks itsa bug in g++, but again, I wanted to ask the standard experts, which compiler got it wrong?

PS:gcc-4.8.3,clang-3.5.1

PS: gcc-4.8.3, clang-3.5.1

推荐答案

就我可以告诉这是草案C + +标准部分 6.8 歧义解析,它说,可以有一个表达式语句和声明之间的模糊性,并说:

As far as I can tell this is covered in the draft C++ standard section 6.8 Ambiguity resolution which says that there can be an ambiguity between expression statements and declarations and says:


语法中涉及表达式语句
和声明时存在歧义:带有函数式
的表达式语句作为其最左边的子表达式的
显式类型转换(5.2.3)可以是
与第一个声明符从
开始的声明不可区分的(在这些情况下语句是一个声明[注:要
消歧,整个语句可能需要检查
确定它是一个表达式语句还是一个声明这个
消除了很多例子。 [示例:假设T是一个
简单类型说明符(7.1.6),

There is an ambiguity in the grammar involving expression-statements and declarations: An expression statement with a function-style explicit type conversion (5.2.3) as its leftmost subexpression can be indistinguishable from a declaration where the first declarator starts with a (. In those cases the statement is a declaration. [ Note: To disambiguate, the whole statement might have to be examined to determine if it is an expression-statement or a declaration. This disambiguates many examples. [ Example: assuming T is a simple-type-specifier (7.1.6),

并给出以下示例:

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

,然后说:


其余的情况是声明。 [示例:

The remaining cases are declarations. [ Example:

class T {
    // ...
   public:
    T();
    T(int);
    T(int, int);
};
T(a); // declaration
T(*b)(); // declaration
T(c)=7; // declaration
T(d),e,f=3; // declaration
extern int h;
T(g)(h,2); // declaration

-end example] -end note]

—end example ] —end note ]

看起来这种情况属于声明示例,特别是最后一个示例似乎是在OP中创建的情况,因此 gcc 将是正确的。

It seems like this case falls into the declaration examples in particular the last example seems to make the case in the OP, so gcc would be correct then.

上述相关部分 5.2.3 显示类型转换

Relevant section mentioned above 5.2.3 Explicit type conversion (functional notation) says:


[...]如果指定的类型是类类型,类类型应完整。如果表达式
list指定多于单个值,则该类型将是具有适当声明的构造函数(8.5,12.1),
并且表达式T(x1,x2,...)的类等效于声明T t(x1,x2,...);对于某些
发明的临时变量t,结果是t的值作为prvalue。

[...] If the type specified is a class type, the class type shall be complete. If the expression list specifies more than a single value, the type shall be a class with a suitably declared constructor (8.5, 12.1), and the expression T(x1, x2, ...) is equivalent in effect to the declaration T t(x1, x2, ...); for some invented temporary variable t, with the result being the value of t as a prvalue.

8.3 含义:


其中D具有形式

In a declaration T D where D has the form

( D1 ) 

所包含的declarator-id的类型与在声明中包含declarator-id的
的类型相同

the type of the contained declarator-id is the same as that of the contained declarator-id in the declaration

T D1

括号不会更改嵌入的声明器ID,但
他们可以改变复杂声明器的绑定。

Parentheses do not alter the type of the embedded declarator-id, but they can alter the binding of complex declarators.

更新

我最初使用 N337 ,但如果我们查看 N4296 部分 6.8 已更新,现在包括以下注释:

I was originally using N337 but if we look at N4296 section 6.8 was updated an it now includes the following note:


如果语句在语法上不能是声明,没有歧义,所以这个规则不会
适用。

If the statement cannot syntactically be a declaration, there is no ambiguity, so this rule does not apply.

这意味着 gcc 不正确,因为:

which means that gcc is incorrect since:

foo x ("bar")("baz");

不能是有效的声明,我最初解释段落 2 如果你的case开始下面的任何一个,那么它是声明,这也许是如何 gcc 实现也解释。

can not be a valid declaration, I originally interpreted paragraph 2 as saying if you case begins with any of the following then it is declaration, which is perhaps how the gcc implementor interpreted as well.

由于 2 的唯一规范部分,我应该更加怀疑 2 c>对于 1 真的没有说什么,似乎对一个不规范的例子提出了要求。我们可以看到, 2 的语句形式现在实际上是一个更有意义的注释。

I should have been more suspicious of paragraph 2 since the only normative part of paragraph 2 really said nothing with respect to paragraph 1 and seems to place a requirement on an example which is not normative. We can see that that statement form paragraph 2 is now actually a note which makes much more sense.

如下所述, 2 实际上从来没有规范,它只是出现了,他链接到修改的修改

As T.C. noted below, paragraph 2 was actually never normative, it just appeared that way and he linked to the change that fixed it.

这篇关于g ++ rejects,clang ++ accepted:foo(x)(“bar”)(“baz”);的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆