You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++17可编译的operator==代码在C++20下编译失败的兼容方案咨询

问题原因

C++20引入了比较运算符的自动重写与合成规则:只要类自定义了operator==且没有自定义operator!=,编译器会自动合成对应的operator!=,同时支持参数顺序交换的表达式重写(即a != b可被重写为!(a == b)或!(b == a))。
你的代码中a_1 != a表达式会产生3个优先级相同的候选重载,编译器无法选出最优解,因此报二义性错误:

  1. 重写为!(a_1 == a),匹配A类的operator==(const A&),仅需将A_1类型的a_1转换为const A&
  2. 重写为!(a == a_1),同样匹配A类的operator==(const A&),仅需将A_1类型的a_1转换为const A&
  3. 匹配全局模板operator!=<A_1>(const T&, const Base&),仅需将A类型的a转换为const Base&
    三个候选的转换序列都是派生类到基类的隐式转换,优先级完全一致,因此产生二义性。而C++17没有比较运算符合成规则,只会匹配全局模板,因此可以正常编译。

解决方案

优先选择仅修改Base类的方案,核心思路是在Base类中显式定义通用的operator!=,阻止派生类自动合成operator!=,从根源消除二义性,同时完全兼容C++17的运行逻辑。修改后的完整代码如下:

#include <stdlib.h>

struct Base {
    // 原有全局比较逻辑移为Base的友元,保持原有语义不变
    template<typename T>
    friend bool operator==(const T&, const Base&)
    {
        return true;
    }
    template<typename T>
    friend bool operator!=(const T& lhs, const Base& rhs)
    {
        return !(lhs == rhs);
    }
    // 新增通用!=重载,阻止编译器自动合成operator!=
    template<typename T>
    bool operator!=(const T&) const
    {
        // 保持和C++17版本完全一致的返回逻辑
        return false;
    }
};

struct A : public Base
{
    bool operator==(const A&) const { return true; }
};

struct A_1 final : public A { };

int main()
{
    const A a;
    const A_1 a_1;
    if (a_1 != a) {}

    return EXIT_SUCCESS;
}

该方案无需修改任何派生类代码,在C17和C20下均可正常编译,运行结果和原有代码完全一致。

内容的提问来源于stack exchange,提问作者Jack Brown

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 08:15:07