I’ve used std::tie to unbind the underlying data from a std::tuple in the past:
auto t = std::make_tuple( 1, 42, 100 ); int a, b, c; std::tie( a, b, c ) = t;
But I hadn’t seen this handy trick for using std::tie to implement operator<
#include <tuple> struct S { S(int a_, int b_, int c_) : a(a_), b(b_), c(c_) {} int a; int b; int c; }; bool operator<( const S& lhs, const S& rhs ) { return std::tie( lhs.a, lhs.b, lhs.c ) < std::tie( rhs.a, rhs.b, rhs.c ); } int main() { S s1( 1, 2, 3), s2 ( 1, 2, 4 ), s3 ( 0, 2, 3); std::cout << "s1 should be less than s2: " << (s1 < s2) << "\n" << "s3 should be less than s1: " << (s3 < s1) << "\n"; return 0; }
Notice that std::tie does not copy the variables (as per the earlier example, it takes them by reference). You can also mimic the use of use of underscore in F#
let f i = (i, i*2, i*4) let a, _, c = f 5
using std::ignore
auto f = []( int i){ return std::tuple(i, i*2, i*4); } int a, b; std::tie( a, std::ignore, b ) = f( 5 );
I’ve used this idiom for a while, and, of course, it easily extends to all six of the relational operations, so you can write:
struct S {
{
bool operator==( const S& that ) const
{ return tie(a,b,c) == tie(that.a,that.b,that.c); }
bool operator<( const S& that ) const
{ return tie(a,b,c) decltype(tie(a,b,c) )
{ return tie(a,b,c); }
public:
bool operator==( const S& that ) const { return orderable() == that.orderable(); }
// etc
};
At least here you only have *two* places you need to update when you add a member variable (and they’re right next to each other). Fortunately, there’s a proposal (that I was reading quite literally yesterday) to allow ‘auto’ to deduce the return type of member functions. so we get:
struct S {
protected:
auto orderable() const { return tie(a,b,c); }
public:
bool operator==( const S& that ) const { return orderable() == that.orderable(); }
// etc
};
Which is even simpler.
Thanks Andy – I like the orderable function. We have something similar in our F Sharp framework for implementing IComparable and related functions – I need to write the C++ equivalent soon, so I’ll give this a go.
Hi Steve, I think wordpress ate my code there (there were actually *three*) forms. But the good news is that WG21 voted in “Return Type Deduction for normal functions” a few minutes ago, so the ‘orderable’ function becomes much easier to implement (or at least, maintain).
(Of course, this still leaves the question of “is operator< the right name for an ordering operation" – and it's my belief that it's not)
Cool – thanks for the update.
Pingback: C++17: structured bindings | musingstudio