Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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

like image 814
Kyle Strand Avatar asked Mar 26 '15 00:03

Kyle Strand


People also ask

What are the different types of comparison operators?

The < (less than), > (greater than), <= (less than or equal), and >= (greater than or equal) comparison, also known as relational, operators compare their operands. Those operators are supported by all integral and floating-point numeric types.

Which operators are supported by all types of numeric types?

Those operators are supported by all integral and floating-point numeric types. For the ==, <, >, <=, and >= operators, if any of the operands is not a number ( Double.NaN or Single.NaN ), the result of operation is false.

Is it possible to implement comparison operators in C++?

Implementing comparison operators in C++ is easier said than done. Indeed, for most types, if we could talk to the compiler we would say something like: “to order them, use a lexicographical order on their members”.

What is the difference between < less than and > operators?

Less than or equal operator <=. Greater than or equal operator >=. Operator overloadability. C# language specification. See also. The < (less than), > (greater than), <= (less than or equal), and >= (greater than or equal) comparison, also known as relational, operators compare their operands.


2 Answers

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));
}
like image 168
Dietmar Kühl Avatar answered Oct 17 '22 07:10

Dietmar Kühl


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.

like image 43
Mark B Avatar answered Oct 17 '22 07:10

Mark B