(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 pair
s 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:
operator=
specifically) can be easily bypassedtie
solution, I can leave out certain members if they don't matter for the orderingAre there any drawbacks in this implementation that I need to consider?
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.
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.
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.
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.
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 );
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