C++23中类的比较运算符能否拥有非类类型的显式对象参数?
C++23中类的比较运算符能否使用与类类型不同的显式对象参数?
先看示例代码:
struct A { int i; constexpr bool operator==(this int x, int y) { return x == y; } constexpr operator int() const { return i; } };
我们结合两种比较场景的编译器行为,对照C++23标准分析合规性:
一、不等比较场景
测试代码:
static_assert( A{0} != A{1} );
编译器行为:
- GCC、Clang可正常编译
- MSVC报错:
error C2803: 'operator ==' must have at least one formal parameter of class type error C2333: 'A::operator ==': error in function declaration; skipping function body
二、相等比较场景
测试代码:
static_assert( A{2} == A{2} );
编译器行为:
- 仅GCC可正常编译
- Clang报错:
error: use of overloaded operator '==' is ambiguous (with operand types 'A' and 'A') 11 | static_assert( A{2} == A{2} ); note: candidate function 3 | constexpr bool operator==(this int x, int y) { return x == y; } note: built-in candidate operator==(int, int)
标准符合性分析
- 运算符声明的合法性
根据C++23标准[dcl.fct.def.this]条款规定:类成员函数的显式对象参数类型必须是该类的cv限定版本、引用或指针(即cv A、cv A&、cv A&&或cv A*),不能是int这类与类无关的类型。
因此示例中operator==的声明本身是非法的,MSVC拒绝编译该函数是正确的(尽管错误信息沿用了旧标准的表述);而GCC和Clang允许该声明,不符合C++23标准。
- 相等比较的歧义问题
即便忽略声明的合法性,Clang的报错也符合标准:当调用A{2} == A{2}时,存在两个可行的候选函数:
- 自定义的
operator==(int, int)(通过显式对象参数绑定左操作数的隐式转换结果,右操作数也转换为int) - 内置的
operator==(int, int)(两个A对象都隐式转换为int后调用)
这两个候选函数签名完全一致,编译器无法区分,因此产生歧义。GCC未检测到该歧义,不符合标准。
内容的提问来源于Stack Exchange,提问作者Fedor
相关产品推荐
相关产品推荐

