Overblog Suivre ce blog
Editer l'article Administration Créer mon blog
21 mai 2012 1 21 /05 /mai /2012 18:25

Hi everyone, it's been a while !

 

One of the things that I apreciate in D is the way comparison operators overloading is implemented. Instead of having six individual operators to overload (<, <=, ==, !=, >= and >), you just have to implement a single special method called opCmp.

 

This opCmp method behaves exactly as memcmp or strcmp do in C :

  • It must return lesser than 0 if the first operand is lesser than the second.
  • It must return 0 for equality
  • It must return greater than 0 if the first operand is greater than the second.

While reading about template programming tricks, I stumbled across something called the Barton-Nackman trick, which is a special use of the Curiously Recurring Template Pattern.

 

So here is a simple trick to enable the overloading of the six comparison operators in C++ in one member function.

 

First of all, define a template class which has the overloads of the six operators which basically just interpret the return value of the opCmp method of its template parameter.

 

 template <class T>
class comparable
{
friend bool operator<(const T& t1, const T& t2)
{
return t1.opCmp(t2) < 0;
}
friend bool operator<=(const T& t1, const T& t2)
{
return t1.opCmp(t2) <= 0;
}
friend bool operator==(const T& t1, const T& t2)
{
return t1.opCmp(t2) == 0;
}
friend bool operator!=(const T& t1, const T& t2)
{
return t1.opCmp(t2) != 0;
}
friend bool operator>=(const T& t1, const T& t2)
{
return t1.opCmp(t2) >= 0;
}
friend bool operator>(const T& t1, const T& t2)
{
return t1.opCmp(t2) > 0;
}
};



Now, when you will need to implement all these operators at one for one of your types, you will just have to inherit privately from this class by using the CRTP and define an opCmp method in you class. Here is a simple example of such a thing :

 

 class number : private comparable<number>
{
int m_value;
public:
number(int n) : m_value(n)
{
}
int opCmp(const number& n) const
{
return m_value - n.m_value;
}
};

 

As you can see, only one method is now needed to implement all the 6 operators. Private inheritance is sufficient in this case and you be read is-implemented-using-a instead of the classical is-a relationship that is introduced by public inheritance. This is a good thing in terms of conception as it reduced dramatically the coupling and the dependencies between these two classes.

 

You'll find below a basic unit test of this number class :

 

 int main()
{
number three(3);
number three_again(3);
number two(2);
number five(5);
assert(three <= three_again);
assert(three == three_again);
assert(three >= three_again);
assert(two < three);
assert(two <= three);
assert(three > two);
assert(three >= two);
assert(three != two);
assert(two != three);
return EXIT_SUCCESS;
}
 

Partager cet article

Repost 0
Published by Olivier - dans Programmation
commenter cet article

commentaires

Présentation

Recherche

Liens