【问题标题】:Is "int (x), 1;" an ambiguous statement?是“int (x), 1;”一个模棱两可的陈述?
【发布时间】:2017-11-08 22:10:51
【问题描述】:
void f(int x) {
    int (x), 1;
}

Clang 编译它,GCC 没有。哪个编译器是正确的?

【问题讨论】:

  • 看起来正确。但是有什么意义呢?
  • 我看不出这不应该编译的原因。 gcc 会产生什么错误?编辑:似乎抱怨本地x 掩盖了论点x。据我所知,虽然这是个坏主意,但这是允许的。
  • @FrançoisAndrieux 这看起来很像int x, <other declarations> 的声明。并且您可以在声明中使用多余的括号
  • @Stephen 拥有void f() { ... } 编译没有问题。如果任何地方都没有 main 函数,那将是 linker 错误。但是编译不包含main函数的代码其实是常见的情况
  • @RegisPortalez:这是一个精简的例子,所以它可能看起来毫无意义,但事实并非如此。

标签: c++ syntax expression language-lawyer variable-declaration


【解决方案1】:

IMO,[stmt.ambig] 中的措辞在这一点上已经足够清楚了:

以函数样式显式类型转换作为其最左边的子表达式的表达式语句与第一个声明符以 @ 开头的声明无法区分987654323@。 在这些情况下该声明是一个声明。

[注意如果语句在语法上不能是声明,则不存在歧义,因此该规则不适用。可能需要检查整个语句以确定是否是这种情况。

该措辞涉及整个(表达式)语句。 您的语句不能被解析为声明,因为词位 1 在语法上不是声明符。没有歧义:如果我们只看int(x),它可能看起来模棱两可,但标准非常明确地否认,如果语句的某些前缀被解析为声明,则整个语句都被视为潜在声明。

事实上,早在 2002 年,核心专家就 core issue 340 进行过非常相似的讨论——我强调了重要的部分。在这里,我们再次假设声明包含一个不兼容的子结构。

考虑以下程序:

struct Point   {
  Point(int){}   
};
struct Lattice    {
  Lattice(Point, Point, int){}   
};
int main(void)   {
  int a, b;
  Lattice latt(Point(a), Point(b), 3);   /* Line X */   
} 

问题与标记为/* Line X */ 的行有关,这是一个模棱两可的 对象或函数的声明。该条款 管理这种歧义的是 8.2 [dcl.ambig.res] 第 1 段,内容如下:

由函数样式之间的相似性引起的歧义 cast 和 6.8 [stmt.ambig] [..] 中提到的声明

基于这个条款有两个 X 行中声明的可能解释:

  • latt 的声明声明了一个函数,其返回值为 输入 Lattice 并接受三个参数。前两种的类型 参数是 Point 并且每个参数后面都跟一个 冗余括号中的参数名称。第三种类型 参数无法确定,因为它是文字。 这将 导致语法错误。
  • latt 的声明声明了一个对象, 因为另一个选项(函数声明)会导致 语法错误。请注意,“[注:”之前的最后一句不是 很有帮助,因为这两个选项都是声明。

Steve Adamczyk:很多人在 comp.std.c++ 说他们没有发现问题。

原版 发帖人回复:

除了同意你的论点,我什么也做不了。所以有 只有对第 8.2 条的一种正确解释 [dcl.ambig.res] 第 1 段,但我不得不说,经过一些改写,该条款 可以做得更清楚,比如明确说明整个 必须考虑声明,并且函数声明 优先于对象声明。

我想建议以下内容作为当前的替代品 第 8.2 条 [dcl.ambig.res] 第 1 段:

由函数样式转换之间的相似性引起的歧义 以及 6.8 [stmt.ambig] […]

中提到的声明

工作组认为目前的措辞已经足够清晰了。

【讨论】:

  • 感谢您的回答!现在很明显,clang 是对的。但是,在我看来,目前的措辞应该改进。因为,它在 1 的末尾声明:“在这些情况下,声明是声明。”然后,注释说,这个陈述并不总是真的,但只有在陈述可以在语法上是一个声明的情况下。这可能有点令人困惑。 End of 1 应该读为“在那些情况下,当整个语句可以是语法正确的声明时,它就是一个声明”
猜你喜欢
  • 2012-08-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-07
  • 2018-05-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多