使用一个数字数据成员为类定义所有比较运算符的便捷方法?

时间:2015-03-26 00:36:54

标签: c++ c++11 comparison-operators

如果我的类型包含单个数字数据成员(例如,int)和各种方法,是否有方便的方法告诉编译器自动生成所有明显的比较运算符?

即,而不是这个(当然,使用inline代替constexpr代替C ++ 03):

class MyValueType
{
    private:
        int myvalue;
    public:
        constexpr bool operator<(MyValueType rhs) const { return myvalue < rhs.myvalue; }
        constexpr bool operator>(MyValueType rhs) const { return myvalue > rhs.myvalue; }
        constexpr bool operator>=(MyValueType rhs) const { return myvalue >= rhs.myvalue; }
        constexpr bool operator==(MyValueType rhs) const { return myvalue == rhs.myvalue; }
        /// .... etc
}

我想要类似Ruby的Comparable mixin,它基本上允许你定义一个运算符,让Ruby来处理剩下的事情。我甚至认为编译器生成的版本可能比我的更好:每个案例rhs应该是const参考吗?我应该定义转发引用的版本吗?如果我忘了其中一个操作员怎么办?等

所以...这样的事情存在吗?

(如果这是重复的话,请原谅我;我认为有人会在某个地方问这个问题,因为这似乎是一个明显的特征,但是我找不到。)

编辑:已提议自动生成比较运算符作为功能:http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3950.html

3 个答案:

答案 0 :(得分:10)

C ++这样做的方法是使用标签类型和ADL。这是一个简单的例子:

namespace relational {
    struct tag {};

    template <typename T>
    bool operator== (T const& lhs, T const& rhs) { return !(rhs < lhs) && !(lhs < rhs); }
    template <typename T>
    bool operator!= (T const& lhs, T const& rhs) { return !(lhs == rhs); }

    template <typename T>
    bool operator> (T const& lhs, T const& rhs) { return rhs < lhs; }
    template <typename T>
    bool operator<= (T const& lhs, T const& rhs) { return !(rhs < lhs); }
    template <typename T>
    bool operator>= (T const& lhs, T const& rhs) { return !(lhs < rhs); }
}

struct foo: relational::tag {
    int value;
    foo(int value): value(value) {}
    bool operator< (foo const& other) const { return this->value < other.value; }
};

#include <iostream>
void compare(foo f0, foo f1) {
    std::cout << std::boolalpha
              << f0.value << " == " << f1.value << " => " << (f0 == f1) << '\n'
              << f0.value << " != " << f1.value << " => " << (f0 != f1) << '\n'
              << f0.value << " <  " << f1.value << " => " << (f0 <  f1) << '\n'
              << f0.value << " <= " << f1.value << " => " << (f0 <= f1) << '\n'
              << f0.value << " >  " << f1.value << " => " << (f0 >  f1) << '\n'
              << f0.value << " >= " << f1.value << " => " << (f0 >= f1) << '\n'
        ;
}
int main() {
    compare(foo(1), foo(2));
    compare(foo(2), foo(2));
}

答案 1 :(得分:2)

你看过boost运算符(http://www.boost.org/doc/libs/1_56_0/libs/utility/operators.htm)了吗?它定义了一组模板,以帮助您自动定义类中的运算符。

答案 2 :(得分:0)

虽然一般来说ADL / KL是有福的方式(对Dietmar Kuhl赞不绝口),但是有一种奇怪的重复模板模式可能会用来促进这样的任务(我并没有实施所有方法,但想法很明确够了,我希望)

template <typename D> struct B
{
    bool operator==(const D& rhs) const { return !(rhs < *(const D*)this ) && !(*(const D*)this < rhs); }
    bool operator!=(const D& rhs) const { return !(*(const D*)this == rhs); }
};

struct D: public B<D>
{
    int _value;

    D(int value): _value(value) {}

    bool operator< (const D& rhs) const {return this->_value < rhs._value;}
};

int main()
{
    D a(1);
    D b(2);
    D c(1);

    std::cout << (a == b) << " " << (a == c) << " " << (a != c) << std::endl;

    return 0;
}