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
Here's a version that relies on the logical short-circuit rule to avoid explicit branching
This assumes that your primitive type of
field1
has anoperator==
. It becomes tedious to type this for more than 2 fields, but you could usestd::lexicographical_compare
if your classobj
stores the fields inside anstd::array<T, N>
for some typeT
and sizeN
Note that there is a draft paper N3326 that discusses adding operators
==
and<
automatically for class types.Think of what happens if
a.field1
is greater thanb.field1
buta.field2
is less thanb.field2
. In that circumstance, you compare based solely onfield2
which is not what you want.You only want to bring
field2
into play where thefield1
fields are equal, so what you're looking for is something like (pseudo-code):No. You need to also catch
(a.field1 > b.field1)
.This is not a strict weak ordering, because it would give
(1,2) < (2,1)
, but also(2,1) < (1,2)
.I'd like to do it all by myself..
You should only compare the values of
Obj::field2
if the values ofObj::field1
are equal.The easy-to-understand way:
The correct (recommended) way:
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.
There must be a way of implementing
operator<
without causing a lot of headache?C++11
You can use
std::tuple
from the STL which already haveoperator<
for multiple fields defined, such as in the below example.C++03
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 usingstd::tie
.using
std::pair
will require copies of the members to be created, which in some circumstances is undesirable.Is this really recommended practise?
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.