I have the following operator< that is supposed to sort first by a value, then by another value:
inline bool operator < (const obj& a, const obj& b)
{
if(a.field1< b.field1)
return true;
else
return a.field2 < b.field2;
}
I have the feeling this is incorrect and that you can't do that without another third comparaison test on the members variables, but I can't find any example where this doesn't work. So whould this really sort as expected? thanks
edit : I would have coded it as :
inline bool operator < (const obj& a, const obj& b)
{
if(a.field1< b.field1)
return true;
else if(a.field1> b.field1)
return false;
else
return a.field2 < b.field2;
}
are there any differences? I'm asking because I know mine is correct from experience but also longer than the first one
You should only compare the values of Obj::field2
if the values of Obj::field1
are equal.
/* This will meet the requirements of Strict-Weak-Ordering */
if (a.field1 != b.field1) return a.field1 < b.field1;
else return a.field2 < b.field2;
The "correct" way of implementing it uses only operator<
to compare the fields, the below looks more complicated than it really is.
It will however yield the same result as the easy-to-understand example previously written.
return a.field1 < b.field1 || (
!(b.field1 < a.field1) && a.field2 < b.field2
);
operator<
without causing a lot of headache?You can use std::tuple
from the STL which already have operator<
for multiple fields defined, such as in the below example.
#include <utility>
...
inline bool
operator< (Obj const& lhs, Obj const& rhs)
{
return std::tie (lhs.field1, lhs.field2) < std::tie (rhs.field1, rhs.field);
}
If your compiler doesn't have support for C++11 yet and you only need to compare two fields from each object you could use std::pair
instead.
The reason for std::make_pair
is the same as in the previous example using std::tie
.
#include <utility>
...
inline bool
operator< (Obj const& lhs, Obj const& rhs)
{
return std::make_pair (lhs.field1, lhs.field2)
< std::make_pair (rhs.field1, rhs.field2);
}
using std::pair
will require copies of the members to be created, which in some circumstances is undesirable.
See the below question/answers for more information, but to sum it up; the c++11 approach doesn't cause that much overhead and it's very simple to implement.