康桓瑋*_*康桓瑋 7 c++ language-lawyer implicit-conversion spaceship-operator c++20
考虑以下无用的代码:
struct S{
constexpr operator int() const { return 0; }
constexpr auto operator<=>(S) const { return *this; }
};
static_assert(S{} <= S{});
Run Code Online (Sandbox Code Playgroud)
Clang 和 MSVC 接受此代码,但 GCC拒绝它并显示错误消息:
error: no match for 'operator<=' (operand types are 'S' and 'int')
Run Code Online (Sandbox Code Playgroud)
哪个编译器是对的?是怎么operator<=合成的operator<=>?
对于关系 ([expr.rel]) 运算符,重写的候选者包括表达式 x <=> y 的所有未重写的候选者。
和
如果
operator<=>通过 的重载决策选择重写候选者operator @,则使用所选的重写候选者x @ y将其解释为 [...] [...] 。重写的候选者不会在结果表达式的上下文中被考虑。(x <=> y) @ 0operator<=>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,则所有三个编译器都会接受它。
| 归档时间: |
|
| 查看次数: |
165 次 |
| 最近记录: |