![](/img/trans.png)
[英]Elaborated-type-specifier for a scoped enum must not use the ‘class’ keyword
[英]Conditional expression parse error on an elaborated-type-specifier inside a new-expression
考慮以下C ++代碼:
struct A {};
struct A* b = (1 == 1) ? new struct A : new 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-clause ,然后在該解析失敗時保釋。
但是,我不明白為什么它會嘗試解析一個類說明符 。 在最新草案標准中查看new-expression的語法,它使用了一個new-type-id語法生成,它使用了type-specifier-seq ,它使用了type-specifier 。 但是, 類說明符 不是 類型說明符的替代方法之一 - 它只作為定義類型說明符的替代方法出現。 在另一方面, 闡述類型說明符 是 類型說明符的選擇之一,並會在這里給我們預期的解析。
雖然我沒有權威的答案,但我有一個有根據的猜測。
最近, 定義類型說明符生成被添加到標准中:如果從2015年末開始查看草案 ,它就不存在了,在引入之前, 類型說明符 確實有類別說明符作為其替代方案之一。
引入定義類型說明符生成的更改是DR 2141的解決方案,它涉及 - 等待它 - 涉及帶有詳細類型說明符的新表達式的歧義(盡管它沒有提到條件表達式 s特別)。
Clang的DR 2141 實施狀態目前列為“未知”。
所以,我受過教育的猜測是:
我仍然有點困惑的一件事是:即使嘗試解析類說明符失敗,為什么不回溯並嘗試解析一個精心設計的類型說明符呢? 據推測,有必要消除類別說明符和詳細類型說明符的歧義,以便在允許其中任何一個的上下文中開始。
在C ++中, struct
與class
相同,只是初始范圍假定為public:
而不是private:
. 所以,一旦你聲明了struct A {};
引用該類型的表達式應僅使用類型標識符A
,而不使用struct
關鍵字:
A* b = (1 == 1) ? new A : new A;
編輯
正如OP在注釋中指出的那樣, struct A
是一個有效的類型名稱,因此它可以作為new
的參數出現。 但是, new
表達式中的type-id被認為是貪婪的。 以下是cppreference.com的示例:
new int + 1 // syntactically okay, '+1' offsets the pointer returned by 'new int'
new int * 1 // error, type (int *) is assumed and 1 doesn't make sense in '(new (int *)) 1'
因此,當編譯器在class A
之后創建一個冒號時,它可能會假設完整的聲明語法( class A : public base_class
)看起來不完整並且在這里不允許 - 因此error: redefinition of 'A'
消息。
解決方案:通過將其括在括號中來明確界定類型:
1 ? new (struct A) : new struct A;
注意第二個struct A
不會引起任何問題,因為它后跟分號,而不是冒號,因此不需要括號。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.