[英]Nested generation of comparison operator with three-way operator?
考慮S
的以下兩個重載operator<=>
:
#include <compare>
struct S {};
int operator<=>(S, int) { return 0; } #1
S operator<=>(S, S) { return {}; } #2
如果我將object S
與int
進行比較, #1
將為我生成正確的運算符,因此像S{} <= 0
、 0 < S{}
或0 <=> S{}
這樣的表達式就可以了。
但是,如果我將 object S
與其他 object S
進行比較:
S{} < S{};
然后這將被重寫為(S{} <=> S{}) < 0
。 由於(S{} <=> S{})
將返回另一個S
,我們回到原點問題: S
與int
進行比較。 目前,我們沒有operator<(S, int)
,所以#1
會為我生成正確的運算符。
但令人驚訝的是,三個編譯器都沒有對我這樣做。 GCC、Clang 和 MSVC都拒絕S{} < S{}
並顯示相同的錯誤消息:
no match for 'operator<' (operand types are 'S' and 'int')
這讓我很沮喪。 因為#1
確實存在。 為什么這里沒有發生操作符的嵌套生成? 標准是怎么說的? 是否存在 static 約束違規?
這是格式錯誤的,盡管錯誤消息確實令人困惑。
來自[over.match.oper]/8的規則是(強調我的):
如果通過重載決策為運算符
@
選擇了重寫的operator<=>
候選者,如果所選候選者是具有相反參數順序的合成候選者,則x @ y
被解釋為0 @ (y <=> x)
,或者(x <=> y) @ 0
否則,使用選定的重寫operator<=>
候選。 在結果表達式的上下文中不考慮運算符@
的重寫候選。
表達式S{} < S{}
將解析為重寫后的候選(S{} <=> S{}) < 0
。 生成的表達式在其查找中不會考慮重寫的候選者。 因此,當我們執行S{} < 0
時,將只查找operator<
,而不是operator<=>
。 它找不到這樣的東西,所以表達式是不正確的。
<source>:8:14: error: no match for 'operator<' (operand types are 'S' and 'int')
8 | auto x = S{} < S{};
| ~~~~^~~~~
從這個意義上說,錯誤是真的:沒有匹配,特別是operator<
與這些操作數。 雖然如果錯誤消息有更多的上下文來解釋它為什么要尋找它(並且我在99629中提交了一個請求),這會有所幫助。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.