I have a class with an attribute of type std::string. I'd like to provide some comparison operator functions like <, >, ==, <=, and >= for the class by comparing the attribute.
My questions is that: any easy way or tool to
(1) just write one or two functions, such as the one for operator < (and ==), others can be automatically generated.
(2) or even simpler since the class comparison is depending on its attribute of type std::string
whose comparison functions are already provided.
This means C++ has the ability to provide the operators with a special meaning for a data type, this ability is known as operator overloading. For example, we can overload an operator '+' in a class like String so that we can concatenate two strings by just using +.
[13.6] Can I overload operator== so it lets me compare two char[] using a string comparison? No: at least one operand of any overloaded operator must be of some class type.
These operators cannot be overloaded. The comparison operators must be overloaded in pairs. That is, if either operator of a pair is overloaded, the other operator must be overloaded as well.
In this case you provide a simple base class which implements all needed operators and simply inherit from it:
template <class T> struct implement_relational_operators{ friend bool operator<=(const T & a,const T & b){ return a < b || a == b; } friend bool operator>(const T & a, const T & b){ return !(a <= b); } friend bool operator!=(const T & a, const T & b){ return !(a == b);} friend bool operator>=(const T & a, const T & b){ return !(a < b); } }; template <class T> struct scalar : public implement_relational_operators<scalar<T> >{ T value; bool operator<(const scalar& o) const { return value < o.value;} bool operator==(const scalar& o) const { return value == o.value;} };
This doesn't share the drawbacks from std::rel_ops
(see below). However, you still need to implement operator<
and operator==
. A similar trick is used by boost
.
C++20's <=>
might improve the situation further (see below).
std::rel_ops
(deprecated in C++20)std::rel_ops
provides the additional operations based on <
an ==
, so you just need to write two operators.
However, it will be deprecated in C++20, where a <=> b
will get thrown into the mix.
You just need the equality (operator=
) and the lesser than (operator<
) comparison operator. The rest can be generated automatically with std::rel_ops
, since the following holds:
a != b equal to !(a == b) a <= b equal to (a < b) || (a == b) a >= b equal to !(a < b) a > b equal to !(a <= b)
Note that these are less efficient than writing those by hand.
However, since it's easy to provide those operators yourself you should just take the extra effort and write them. And they also have some drawbacks, as mentioned by R. Martinho Fernandes:
Note that [they] won't work properly unless you:
- add
using namespace std::rel_ops
on every context you use the operators; or- add
using::operator!=; using::operator<=; using::operator>=; using::operator>;
in the namespace of your class (using namespace std::rel_ops
in the namespace of your class is not acceptable because it does not get picked up by ADL).
You could use std::rel_ops
, but it would be wrong. That's a sledgehammer that doesn't belong in anyone's toolkit.
The usual approach is to define operator==
and operator<
with knowledge of the details of the class. The remaining four operators can be written with those:
a != b
is !(a == b)
a <= b
is !(b < a)
a > b
is b < a
a >= b
is !(a < b)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With