【问题标题】:Chained equal operator overloading链式相等运算符重载
【发布时间】:2016-05-27 12:03:30
【问题描述】:

我想添加一个选项来对MyClass 的对象进行链式比较。例如:

MyClass one;
MyClass two;
MyClass three;
/*....*/
if (one == two == three){
    /*....*/
}

因此,如果所有人都相等,它将返回true,否则将返回false。 我目前有这个运算符重载,在仅比较 MyClass 的两个实例时可以正常工作:

bool operator==(const MyClass &other);

我知道one==two==three 等于((one==two)==three),所以我想这应该将我的operator== 更改为:

MyClass& operator==(const MyClass &other);

但我无法理解如何完成此操作以便能够连续比较两个以上的实例(链接)。

【问题讨论】:

  • 为什么不遵循正常语义并使用if (one == two && two == three)
  • 不要。
  • @NathanOliver:确实,“EqualExpr”对象必须计算所有等式,而普通语义可能会短路。
  • “让它工作”是什么意思? (one == two) == three 在语义上不等同于 one == two && two == three
  • 1) Principle of least astonishment。以奇怪和意想不到的方式做某事会导致用户体验/支持出现问题。 2) 提供一个具有实际帮助和不言自明的名称的辅助函数。编辑:回答此评论↓

标签: c++ operator-overloading


【解决方案1】:

正如 cmets 中所指出的,以这种方式破坏通常的语义是不好的。如前所述,应遵循Principle of least Astonishment

但我无法理解如何完成此操作以便能够连续比较两个以上的实例(链接)。

我认为这样做并不是一个好主意1,但这里有一个可行的解决方案:

#include <iostream>

using namespace std;

class MyClass {
public:
     MyClass(int x_) : x(x_), isfalse(false) {}

     const MyClass& operator==(const MyClass& rhs) const {
         if(!isfalse && x == rhs.x) {
             return rhs;
         }
         return FalseInst;
     }
     operator bool() const {
         return !isfalse;
     }
private:
     int x;
     MyClass() : x(), isfalse(true)  {}
     const bool isfalse;
     static MyClass FalseInst;
};

MyClass MyClass::FalseInst;

int main()
{
    MyClass one(1);
    MyClass two(1);
    MyClass three(1);

    if(one == two == three) {
        cout << "Yay!" << endl;
    }

    MyClass four(1);
    MyClass five(0);
    MyClass six(0);

    if(!(four == (five == six))) {
        cout << "Yay!" << endl;
    }
}

Live Demo


1)注意编译器发出的警告。

【讨论】:

  • 非常令人印象深刻的解决方案,开销最小。虽然one == (two == three) 打破了它,three 有另一个值:)
  • 现在 one == two == three 打破了它,twothree 都是 0
  • @coyotte508 我明白了,这实际上无法合理解决。
  • if(x == rhs.x)-> if(!isfalse &amp;&amp; x == rhs.x) -- 抱歉,我对你的回答有点着迷,static 成员让我印象深刻:)
【解决方案2】:

作为一个纯理论问题,这里有一个解决方法:

#include <iostream>
using namespace std;

class A {
public:
    int x;

    A(int x = 0) : x(x) {}

    struct Cmp {
        const A *ptr;
        mutable bool val;

        operator bool() const {
            return val;
        }

        const Cmp &operator == (const A &other) const {
            return other == *this;
        }
    };

    bool isEqualTo (const A &other) const {
        return x == other.x;
    }

    Cmp operator == (const A &other) const {        
        return {this, isEqualTo(other)};
    }

    const Cmp &operator == (const Cmp &other) const {
        //other.val = other.val && (*this == *other.ptr).val;
        other.val &= other.ptr->isEqualTo(*this);
        return other;
    }
};

int main() {
    cout << (A(10) == A(10) == A(10)) << endl;
    cout << (A(10) == A(9) == A(10)) << endl;

    return 0;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-09-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-27
    • 1970-01-01
    • 2020-01-21
    相关资源
    最近更新 更多