Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Implementing comparison operators via 'tuple' and 'tie', a good idea?

(Note: tuple and tie can be taken from Boost or C++11.)
When writing small structs with only two elements, I sometimes tend to choose a std::pair, as all important stuff is already done for that datatype, like operator< for strict-weak-ordering.
The downsides though are the pretty much useless variable names. Even if I myself created that typedef, I won't remember 2 days later what first and what second exactly was, especially if they are both of the same type. This gets even worse for more than two members, as nesting pairs pretty much sucks.
The other option for that is a tuple, either from Boost or C++11, but that doesn't really look any nicer and clearer. So I go back to writing the structs myself, including any needed comparision operators.
Since especially the operator< can be quite cumbersome, I thought of circumventing this whole mess by just relying on the operations defined for tuple:

Example of operator<, e.g. for strict-weak-ordering:

bool operator<(MyStruct const& lhs, MyStruct const& rhs){   return std::tie(lhs.one_member, lhs.another, lhs.yet_more) <          std::tie(rhs.one_member, rhs.another, rhs.yet_more); } 

(tie makes a tuple of T& references from the passed arguments.)


Edit: The suggestion from @DeadMG to privately inherit from tuple isn't a bad one, but it got quite some drawbacks:

  • If the operators are free-standing (possibly friends), I need to inherit publicly
  • With casting, my functions / operators (operator= specifically) can be easily bypassed
  • With the tie solution, I can leave out certain members if they don't matter for the ordering

Are there any drawbacks in this implementation that I need to consider?

like image 708
Xeo Avatar asked Jun 02 '11 18:06

Xeo


People also ask

What is the purpose of the comparison operators?

Comparison Operators. Comparison operators compare the contents in a field to either the contents in another field or a constant. They may be used alone or in combination with other operators and functions in both record expressions and target field expressions.

Which operators are used for doing comparison?

The equality operator uses to compare two values. Using " ==", the equality operator one can compare or check boolean, string, numeral, etc. If the comparison is satisfying then the output will be true, false otherwise.

What are various comparison operators that used to compare two values?

Comparison operators — operators that compare values and return true or false . The operators include: > , < , >= , <= , === , and !== . Logical operators — operators that combine multiple boolean expressions or values and provide a single boolean output.


2 Answers

This is certainly going to make it easier to write a correct operator than rolling it yourself. I'd say only consider a different approach if profiling shows the comparison operation to be a time-consuming part of your application. Otherwise the ease of maintaining this should outweigh any possible performance concerns.

like image 99
Mark B Avatar answered Sep 18 '22 04:09

Mark B


I have come accross this same problem and my solution uses c++11 variadic templates. Here comes the code:

The .h part:

/***  * Generic lexicographical less than comparator written with variadic templates  * Usage:  *   pass a list of arguments with the same type pair-wise, for intance  *   lexiLessthan(3, 4, true, false, "hello", "world");  */ bool lexiLessthan();  template<typename T, typename... Args> bool lexiLessthan(const T &first, const T &second, Args... rest) {   if (first != second)   {     return first < second;   }   else   {     return lexiLessthan(rest...);   } } 

And the .cpp for the base case without arguments:

bool lexiLessthan() {   return false; } 

Now your example becomes:

return lexiLessthan(     lhs.one_member, rhs.one_member,      lhs.another, rhs.another,      lhs.yet_more, rhs.yet_more ); 
like image 33
user2369060 Avatar answered Sep 18 '22 04:09

user2369060