新表达式中的详细类型说明符出现条件表达式分析错误 考虑下面的C++代码: struct A {}; struct A* b = (1 == 1) ? new struct A : new struct A;

新表达式中的详细类型说明符出现条件表达式分析错误 考虑下面的C++代码: struct A {}; struct A* b = (1 == 1) ? new struct A : new struct A;,c++,parsing,gcc,visual-c++,clang,C++,Parsing,Gcc,Visual C++,Clang,MSVC接受这一点,但GCC和Clang不接受我想了解根据标准,哪个是正确的,以及为什么。 Clang给出的错误是: test.cpp:2:37: error: redefinition of 'A' struct A* b = (1 == 1) ? new struct A : new struct A; ^ test.cpp:1:8: note: previous definition is here struct A

MSVC接受这一点,但GCC和Clang不接受我想了解根据标准,哪个是正确的,以及为什么。

Clang给出的错误是:

test.cpp:2:37: error: redefinition of 'A'
struct A* b = (1 == 1) ? new struct A : new struct A;
                                    ^
test.cpp:1:8: note: previous definition is here
struct A {};
       ^
test.cpp:2:37: error: '(anonymous struct at test.cpp:2:37)' cannot be defined in a type specifier
struct A* b = (1 == 1) ? new struct A : new struct A;
                                    ^
test.cpp:2:41: error: expected class name
struct A* b = (1 == 1) ? new struct A : new struct A;
                                        ^
test.cpp:2:53: error: expected '{' after base class list
struct A* b = (1 == 1) ? new struct A : new struct A;
                                                    ^
test.cpp:2:53: error: expected ':'
struct A* b = (1 == 1) ? new struct A : new struct A;
                                                    ^
                                                    :
test.cpp:2:24: note: to match this '?'
struct A* b = (1 == 1) ? new struct A : new struct A;
                       ^
test.cpp:2:53: error: expected expression
struct A* b = (1 == 1) ? new struct A : new struct A;
                                                    ^
这向我表明,clang试图将令牌
struct A:
解析为类说明符,冒号引入一个base子句,然后在解析失败时退出


然而,我不明白为什么它会试图解析一个类说明符。查看中新表达式的语法,它使用一个新的类型id语法产品,它使用类型说明符seq,它使用类型说明符。但是,类说明符不是类型说明符的备选方案之一,它仅作为定义类型说明符的备选方案出现。另一方面,详细阐述了类型说明符<强>是类型说明符的替代之一,并给出了我们的解析。

< > > C++ >结构> <代码>与类< /C> >相同,只是初始范围假设为代码>公用:而不是<代码>私下:。因此,一旦您声明
struct A{}引用类型的表达式应仅使用类型标识符
A
,而不使用
struct
关键字:

A* b = (1 == 1) ? new A : new A;
编辑

正如OP在注释中所指出的,
struct A
是一个有效的类型名称,因此它可以作为
new
的参数出现。然而,
new
表达式中的类型id被认为是贪婪的。以下是一个例子:

因此,当编译器在
类a
之后发现冒号时,它可能假定完整的声明语法(
类a:公共基\u类
),该语法看起来不完整,在这里是不允许的–因此出现
错误:重新定义“a”
消息

解决方案:通过将类型括在括号中显式分隔:

1 ? new (struct A) : new struct A;

请注意,第二个
结构A
不会引起任何问题,因为它后面跟的是分号,而不是冒号,因此它不需要插入括号。

虽然我没有权威性的答案,但我有一个有根据的猜测

定义类型说明符是最近才添加到标准中的:如果你看一个,它不在那里,在引入它之前,类型说明符确实有类说明符作为它的替代品之一

引入定义类型说明符产品的第一个原因是解决了,它涉及到一个包含精心设计的类型说明符的新表达式(尽管它没有特别提到条件表达式)的歧义性

DR 2141的叮当声目前被列为“未知”

因此,我的猜测是:

  • Clang和GCC尚未执行DR 2141的决议
    • 更新:我在主题上找到了一个,并提交了一个
  • 因此,他们试图基于旧的类型说明符产品解析一个新的类型id,该产品包括一个类说明符作为其备选方案之一

有一件事我仍然有点困惑:即使尝试解析一个类说明符失败了,为什么不回溯并尝试解析一个复杂的类型说明符呢?大概在允许使用类说明符和详细类型说明符的上下文中,这类事情对于消除类说明符和详细类型说明符的歧义是必要的。

C++不使用C的标记名称空间。出于好奇,当您删除
结构时,是否会得到与在
新结构A中一样的结果?也就是说,一个新的
是否触发了它?@jww如果触发了,它将是一个糟糕的编译器@jww:
新的A
很好用(很容易理解为什么:
A
现在只是一个命名类型说明符,不可能是一个精心设计的类型说明符或类说明符的开始)。在我看来,这看起来像一个bug。这个措辞实际上令人困惑。上面说。但据我所知,语法中没有描述它。那么它可能会出现在表达式中?我迷路了。如果你所说的“应该”是指你推荐的风格,那么我同意你的观点,但这与我的问题无关。如果您的意思是将类型引用为
struct A
是无效的,那么这是不正确的;C++允许将类型引用为“代码>结构”< /COD>,并且在大多数上下文中,它等同于只使用<代码> < <代码>。
1 ? new (struct A) : new struct A;