Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Defining operator< for a struct

People also ask

How do you define a function operator?

An operator function is a user-defined function, such as plus() or equal(), that has a corresponding operator symbol. For an operator function to operate on the opaque data type, you must overload the routine for the opaque data type.

Which operator is Overloadable?

An overloaded operator is called an operator function. You declare an operator function with the keyword operator preceding the operator. Overloaded operators are distinct from overloaded functions, but like overloaded functions, they are distinguished by the number and types of operands used with the operator.

How do you create a struct in C++?

To create a structure, use the struct keyword and declare each of its members inside curly braces.

What is an operator overloading in C++?

It's a type of polymorphism in which an operator is overloaded to give it the user-defined meaning. C++ allows us to specify more than one definition for a function name or an operator in the same scope, which is called function overloading and operator overloading, respectively.


This is quite an old question and as a consequence all answers here are obsolete. C++11 allows a more elegant and efficient solution:

bool operator <(const MyStruct& x, const MyStruct& y) {
    return std::tie(x.a, x.b, x.c) < std::tie(y.a, y.b, y.c);
}

Why is this better than using boost::make_tuple? Because make_tuple will create copies of all the data members, which can be costly. std::tie, by contrast, will just create a thin wrapper of references (which the compiler will probably optimise away entirely).

In fact, the above code should now be considered the idiomatic solution to implementing a lexicographical compare for structures with several data members.


Others have mentioned boost::tuple, which gives you a lexicographical comparison. If you want to keep it as a structure with named elements, you can create temporary tuples for comparison:

bool operator<(const MyStruct& x, const MyStruct& y)
{
    return boost::make_tuple(x.a,x.b,x.c) < boost::make_tuple(y.a,y.b,y.c);
}

In C++0x, this becomes std::make_tuple().

UPDATE: And now C++11 is here, it becomes std::tie(), to make a tuple of references without copying the objects. See Konrad Rudolph's new answer for details.


I would do this:

#define COMPARE(x) if((x) < (rhs.x)) return true; \
                   if((x) > (rhs.x)) return false;
COMPARE(a)
COMPARE(b)
COMPARE(c)
return false;
#undef COMPARE

In this case you can use boost::tuple<int, int, int> - its operator< works just the way you want.


I think the easiest way is to stick with the < operator for all comparisons and don't use > or ==. Below is the pattern I follow, and you can follow for all your structs

typedef struct X
{
    int a;
    std::string b;
    int c;
    std::string d;

    bool operator <( const X& rhs ) const
    {
        if (a < rhs.a) { return true; }
        else if ( rhs.a < a ) { return false; }

        // if neither of the above were true then 
        // we are consdidered equal using strict weak ordering
        // so we move on to compare the next item in the struct

        if (b < rhs.b) { return true; }
        if ( rhs.b < b ) { return false; }

        if (c < rhs.c) { return true; }
        if ( rhs.c < c ) { return false; }

        if (d < rhs.d) { return true; }
        if ( rhs.d < d ) { return false; }

        // if both are completely equal (based on strict weak ordering)
        // then just return false since equality doesn't yield less than
        return false;
    }
};

The best way I know is to use a boost tuple. It offers among others a builtin comparison and constructors.

#include <boost/tuple/tuple.hpp>
#include <boost/tuple/tuple_comparison.hpp>

typedef boost::tuple<int,int,int> MyStruct;

MyStruct x0(1,2,3), x1(1,2,2);
if( x0 < x1 )
   ...

I also like Mike Seymors suggestion to use temporary tuples through boost's make_tuple