代码之家  ›  专栏  ›  技术社区  ›  wakey

模糊重载操作符C++ 20

  •  3
  • wakey  · 技术社区  · 5 年前

    我试图在最新的visualstudio和Clang版本中测试我的项目。弹出的错误之一与不明确的运算符有关 (with reversed parameter order) . 这似乎并没有出现在C++ 17中。

    例如:( https://godbolt.org/z/Gazbbo )

    struct A {
        bool operator==(const A& other) const { return false; }
    };
    
    struct B : private A {
        B(const A&);
        bool operator==(const B& other) const { return false; }
    };
    
    bool check(A a, B b) {
        return b == a;
    }
    

    我不确定为什么这会是个问题。在我看来,这里唯一可行的功能是 bool operator==(const B& other) const 作为 A 可以隐式转换为 B 但不是相反。的确,如果我标记 B(const A&) 具有 explicit 我得到了一个错误 B类 无法转换为的私有基 A .

    我想知道除了使用 明确的 或使用 B(a) . 想象 A B类 是库代码,我如何支持C++ 20而不破坏我的低版本的接口?

    1 回复  |  直到 5 年前
        1
  •  3
  •   Barry    5 年前

    在C++ 17中,是唯一可行的候选者是 b.operator==(B(a)) .


    但在C++ 20中,比较运算符具有更多的功能。平等现在也可以考虑反转和重写的候选人。所以当我们考虑 b == a 我们还考虑 a == b . 因此,我们有两位候选人:

    bool B::operator==(B const&);
    bool A::operator==(A const&); // reversed
    

    这个 B 成员函数在左侧是完全匹配的,但需要转换第二个参数。这个 A 成员函数在右侧是完全匹配的,但需要转换第一个参数。两个候选人都不比另一个好,所以结果变得模棱两可。

    至于怎么修。这是一种奇怪的情况( B类 两者都继承自 A 并且可以从 A ?). 如果放弃继承,则删除 A 成员候选人。如果你移除 B(A const&) 构造函数,则会出现访问冲突,因为唯一的候选对象是 A 需要转换的 b 到它的 A (这表明这是可疑的)。

    或者,您可以添加 B类 ,与 A 去定义这到底意味着什么。因为这里的问题是有两个选择,编译器不知道哪一个是最好的,所以只需提供一个更好的选择:

    struct B  : private A {
        B(const A&);
        bool operator==(B const&) const;
        bool operator==(A const&) const; // <== add this one
    };
    

    现在这个新的在这两个论点中是完全匹配的,并且是绝对优越的候选人。