[英]Three-way operator <=> return struct with implicit conversion function
考慮以下無用的代碼:
struct S{
constexpr operator int() const { return 0; }
constexpr auto operator<=>(S) const { return *this; }
};
static_assert(S{} <= S{});
Clang 和 MSVC 接受此代碼,但 GCC拒絕它並顯示錯誤消息:
error: no match for 'operator<=' (operand types are 'S' and 'int')
哪個編譯器是對的? operator<=
如何從operator<=>
合成?
從 [over.match.oper] ( 3.4.1和8 ):
對於關系 ([expr.rel]) 運算符,重寫的候選包括表達式 x <=> y 的所有未重寫的候選。
和
如果通過重載決策為
operator @
選擇了重寫的operator<=>
候選者,則x @ y
被解釋為 [...](x <=> y) @ 0
[...],使用所選的重寫operator<=>
候選人。 在結果表達式的上下文中不考慮operator @
的重寫候選。
因此,對於表達式S{} <= S{}
,選定的運算符將是S::operator<=>(S) const
並且表達式將被重寫為(S{} <=> S{}) <= 0
。 在重寫的表達式中,操作數的類型是S
和int
,將選擇內置的operator<=(int, int)
。 所以最終表達式(在將S
轉換為int
之后)將導致0 <= 0
,這是true
。
總之 Clang 和 MSVC 在這種情況下是正確的,並且 GCC 似乎無法將(S{} <=> S{}) <= 0
解釋為對內置運算符的調用(請注意讀取operand types are 'S' and 'int'
)。 如果您將static_assert
中的條件更改為重寫后的表達式(S{} <=> S{}) <= 0
,則所有三個編譯器都接受它。
GCC 中的 C++20 支持仍處於實驗階段,因此雖然它支持三向運算符,但您的static_assert
失敗,因為其他編譯器自動從<=>
運算符推斷<=
運算符,而 GCC 似乎更多對標准的解釋很迂腐,並且由於您沒有直接使用<=
運算符,因此編譯器會發出編譯時錯誤,因為它找不到<=
運算符。
如果添加<=
運算符,則代碼有效,例如:
struct S{
constexpr operator int() const { return 0; }
constexpr auto operator<=>(S) const { return *this; }
constexpr bool operator<=(S) { return true; }
};
static_assert(S{} <= S{});
此外,如果您將斷言更改為三向運算符,則測試在所有編譯器上都會失敗,例如:
struct S{
constexpr operator int() const { return 0; }
constexpr auto operator<=>(S) const { return *this; }
};
static_assert(S{} <=> S{});
此外,由於預計三路運算符基本上返回負值、零或正值(實際上返回一個排序),返回*this
可能會將值轉換為 Clang 和 MSVC 解釋為斷言的true
值的值,而 GCC 可能會將其轉換為false
值,因此斷言失敗。
如果您將返回類型更改為任何負值(甚至-0
)或零值,則斷言將傳遞給所有編譯器,此外,如果您將值更改為任何高於 0 的正值,則斷言在所有編譯器上都會失敗。
您可以將三向運算符更改為將*this
強制轉換為int
,該 int 將調用operator int
並返回 0,這將導致斷言通過,例如:
constexpr auto operator<=>(S) const { return static_cast<int>(*this); }
所以直接回答:
哪個編譯器是對的?
根據我對 GCC 的經驗,當涉及到面對奇怪的代碼片段(如您的代碼片段)可能模棱兩可的語言規范時,它往往會非常迂腐地解釋語言,並且會謹慎行事。
為此,其他編譯器對語言的解釋可能過於松散,或者 GCC 在這種特殊情況下可能過於嚴格。
無論哪種方式,即使這段代碼是“無用的”,任何遇到這樣的事情並針對所有 3 個編譯器的人都應該盡可能地嘗試使用這種類型的代碼,盡管這可能必然會違背不幸的是,這種情況下的代碼。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.