簡體   English   中英

三路運算符 <=> 隱式轉換返回結構 function

[英]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.18 ):

對於關系 ([expr.rel]) 運算符,重寫的候選包括表達式 x <=> y 的所有未重寫的候選。

如果通過重載決策為operator @選擇了重寫的operator<=>候選者,則x @ y被解釋為 [...] (x <=> y) @ 0 [...],使用所選的重寫operator<=>候選人。 在結果表達式的上下文中不考慮operator @的重寫候選。

因此,對於表達式S{} <= S{} ,選定的運算符將是S::operator<=>(S) const並且表達式將被重寫為(S{} <=> S{}) <= 0 在重寫的表達式中,操作數的類型是Sint ,將選擇內置的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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM