首页 > 解决方案 > 在 C++ 中,您需要在两个方向上重载 operator== 吗?

问题描述

假设我正在与一个班级一起工作:

class Foo{
public:
  std:string name;
  /*...*/
}/*end Foo*/

我为operator==

bool operator==(const Foo& fooObj, const std::string& strObj) {
    return (fooObj.name == strObj);
}

我是否还需要反向重新实现相同的逻辑?

bool operator==(const std::string& strObj, const Foo& fooObj) {
    return (strObj == fooObj.name);
}

标签: c++operator-overloading

解决方案


(C++20 以后)

随着p1185被 C++20 接受,您不需要提供多个重载。该论文对标准进行了这些更改(其中包括):

[over.match.oper]

3.4 - [...] 对于!=运算符 ([expr.eq]),重写的候选者包括运算符的所有成员、非成员和内置候选者==(x == y)当上下文转换为使用该运算符的布尔值==。对于等式运算符,重写的候选还包括一个合成候选,两个参数的顺序颠倒,对于每个成员、非成员和内置候选,==重写表达式(y == x)在上下文中是格式正确的使用该运算符转换为 bool==. [注意:从成员候选中合成的候选将其隐式对象参数作为第二个参数,因此第一个参数考虑隐式转换,但不考虑第二个参数。— 尾注] [...]

8 [...] 如果通过重载决议为!=运算符选择了重写的候选者,则将其x != y解释为(y == x) ? false : true所选择的候选者是具有相反参数顺序的合成候选者,或者(x == y) ? false : true以其他方式使用所选的重写operator==候选者。如果通过重载决议为==运算符选择了重写的候选者,则将x == y其解释为(y == x) ? true : false使用选定的重写operator==候选者。

以上意味着您不仅不需要向操作员提供操作数颠倒的顺序,还可以!=免费获得!此外,operator==如果有意义,该函数可以成为成员。虽然正如上面第一段中的注释所说,它是一个成员或自由函数会影响隐式转换,所以你仍然需要记住这一点。


(最高 C++17)

如果你想支持字符串在左边和Foo右边的比较,你可以这样做。实现不会将参数重新排序为重载operator==以使其工作。

但是,您可以避免重复实现的逻辑。假设您的操作员应按预期运行:

inline bool operator==(const std::string& objA, const Foo& objB) {
    return objB == objA; // Reuse previously defined operator
}

推荐阅读