Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to best overload operator < > <= >= but only write one or two comparison functions?

Tags:

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.

like image 556
user1899020 Avatar asked Dec 17 '12 16:12

user1899020


People also ask

What is operator overloading overload <= operator with example?

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 +.

Can I overload operator == so it lets me compare two char [] using a string comparison?

[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.

Can comparison operators be overloaded?

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.


2 Answers

Curiously recurring template pattern

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.

Requirements

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.

Warning

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:

  1. add using namespace std::rel_ops on every context you use the operators; or
  2. 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).
like image 161
Zeta Avatar answered Oct 28 '22 03:10

Zeta


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)

like image 29
Pete Becker Avatar answered Oct 28 '22 05:10

Pete Becker