How-To make C++ types comparable
Often, we find ourselves in a situation where we have some struct or class, and it would be convenient to compare one instance to another. Similarly, we may find that it is conceptually ideal as a key for some std::map we’re using.
This isn’t a particularly complex thing to achieve, but it introduces a lot of boilerplate code. Instead, we can use liberate/cpp/operators/comparison.h.
1#include <liberate/cpp/operators/comparison.h>
2
3struct my_type
4 : public liberate::cpp::comparison_operators<my_type>
5{
6 // ...
7};
8
9my_type a, b;
10
11assert(a == b);
The liberate::cpp::comparison_operators
struct adds a number of
comparison operators to your class including operator==()
– but the
compilation of the above will nonetheless fail, because how to compare
my_struct
is unclear.
You will have to provide a function for performing this comparison,
is_equal_to
.
1struct my_type
2 : public liberate::cpp::comparison_operators<my_type>
3{
4 bool is_equal_to(my_type const & other) const
5 {
6 // do your comparison here
7 }
8};
How is this any better than implementing operator==()
directly? Simply
because the liberate class also provides an operator!=()
from the same
function.
The utility of this may become more apparent when considering less-than comparison instead.
1struct my_type
2 : public liberate::cpp::comparison_operators<my_type>
3{
4 bool is_less_than(my_type const & other) const
5 {
6 // do your comparison here
7 }
8};
9
10my_type a, b;
11
12if (a < b) { /* ... */ }
13if (a > b) { /* ... */ }
14if (a <= b) { /* ... */ }
15if (a >= b) { /* ... */ }
All of the above four operators are provided via the single is_less_than
function. Providing both functions yields 6 operators altogether, enough for
comparisions required for key types in std::map
, etc.
Note
All operators are inline functions, so will not generate code unless you
use them. This means that it’s entirely possible to provide only an
implementation of e.g. is_equal_to
so long as you never perform any
less-than, greater-than or similar comparisons.
Sometimes it’s easier to make a type comparable with free functions when it
already has defined an operator==
and an operator<
. You can do this
very easily. It’s also possible to combine both approaches. There’s a simple
macro for that.
1LIBERATE_MAKE_COMPARABLE(my_type);