Convenient way to define all comparison operators for class with one numeric data member?

こ雲淡風輕ζ 提交于 2019-12-01 03:01:17

问题


If I have a type that consists of a single numeric data member (say, an int) and various methods, is there a convenient way to tell the compiler to automatically generate all the obvious comparison operators?

I.e., instead of this (using inline instead of constexpr for C++03, of course):

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
}

I want something like Ruby's Comparable mixin, which basically allows you to define one operator and let Ruby take care of the rest. And I'd even assume that the compiler-generated versions would probably be better than mine: should rhs be a const ref for each case? Should I define versions that take forwarding references? What if I forget one of the operators? Etc.

So...does something like this exist?

(Please forgive me if this is a duplicate; I assumed someone would have already asked this somewhere, because it seems like an obvious feature to want, but I can't find any.)

EDIT: Automatic generation of comparison operators has been proposed as a feature: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3950.html


回答1:


The C++ way of doing this is to use a tag type and ADL. Here is a quick example:

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));
}



回答2:


Have you looked at boost operators (http://www.boost.org/doc/libs/1_56_0/libs/utility/operators.htm)? It defines a bunch of templates to help you automatically define operators in your class.




回答3:


While in general ADL/KL is blessed way to go (kudos to Dietmar Kuhl), there is Curiously Recurring Template Pattern which might be used to facilitate such task (I've implemented not all methods, but idea is clear enough, I hope)

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;
}


来源:https://stackoverflow.com/questions/29269124/convenient-way-to-define-all-comparison-operators-for-class-with-one-numeric-dat

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!