C++编译器如何匹配Class::operator==?C++20相等运算符行为疑问
C20与C17中
operator==匹配规则差异及代码问题解析 你的猜测是否正确?
你的猜测方向是对的,但更准确的表述是:C++20为相等类运算符(==、!=)引入了对称查找机制,当直接匹配a == b失败时,编译器会自动尝试交换操作数顺序,匹配b == a,这就是代码在C++20下能正常编译的核心原因。
代码编译差异的具体原因
C++17编译失败的原因
在C++17及更早标准中,执行a == b(A& == B&)时,编译器的查找逻辑是:
- 首先查找
A的成员operator==,它的参数是A&。由于B是私有继承A,在main函数这类外部作用域中,B到A的类型转换是不可访问的,无法将B&隐式转换为A&来匹配这个运算符。 - C++17不会自动尝试交换操作数顺序,因此没有机会匹配
B的operator==(A&),最终因找不到合法的运算符而报错。
C++20编译成功的原因
C++20对==和!=运算符新增了对称查找规则:
当原顺序的运算符匹配失败后,编译器会自动生成交换操作数后的表达式(即把a == b转为b == a),再重新进行查找。
对于你的代码,b == a会直接匹配B的成员operator==(A&)——b是B&类型,a是A&类型,完全符合参数要求,因此可以正常调用,编译通过。
C++中operator==的匹配规则
C++20之前的规则
对于表达式x == y,编译器会按以下顺序查找:
- 成员运算符查找:优先查找
x的类型中定义的成员operator==,要求参数能匹配y的类型(或通过隐式转换匹配)。 - 非成员运算符查找:如果成员查找失败,在全局命名空间以及
x、y类型所在的命名空间中,查找非成员operator==,要求参数能匹配(x, y)的类型组合。 - 不会自动交换操作数顺序,必须手动写
y == x才能触发对y的运算符查找。
C++20的规则(新增对称查找)
C++20仅对==和!=运算符扩展了查找逻辑:
- 先执行C++20之前的常规查找(成员+非成员)。
- 如果常规查找失败,且运算符是
==或!=,则交换操作数顺序,生成y == x,再重新执行一次常规查找。 - 若交换后的查找成功,则使用该运算符;若仍失败,才会编译报错。
注意:该对称查找仅适用于相等类运算符,
+、-、>等其他运算符不支持自动交换查找。
代码中各表达式的匹配情况
a == a:直接匹配A::operator==(A&),正常执行。a == b(C++20):原顺序匹配失败,交换为b == a,匹配B::operator==(A&)。b == a:直接匹配B::operator==(A&),正常执行。b == b:直接匹配B::operator==(B&),正常执行。
内容的提问来源于stack exchange,提问作者AlphaGolang
相关产品推荐
相关产品推荐

