/*
* In order to clarify the core concept, let's reduce it to a more basic
* example. Although `std::tie` is useful for functions returning (a
* tuple of) more values, we can understand it just fine with just one
* value:
*/
int a;
std::tie(a) = std::make_tuple(24);
return a; // 24
/*
* Things we need to know in order to go forward:
*
* + `std::tie` constructs and returns a tuple of references.
* + `std::tuple<int>` and `std::tuple<int&>` are 2 completely different
* classes, with no connection between them, other that they were
* generated from the same template, `std::tuple`.
* + tuple has an `operator=` accepting a tuple of different types (but
* same number), where each member is assigned individually—from
* [cppreference][1]:
*
* > template< class... UTypes >
* > tuple& operator=( const tuple<UTypes...>& other );
* >
* > (3) For all i, assigns `std::get<i>(other)` to `std::get<i>(*this)`.
*
* The next step is to get rid of those functions that only get in your
* way, so we can transform our code to this:
*/
int a;
std::tuple<int&>{a} = std::tuple<int>{24};
return a; // 24
/*
* The next step is to see exactly what happens inside those structures.
* For this, I create 2 types `T` substituent for `std::tuple<int>` and
* `Tr` substituent `std::tuple<int&>`, stripped down to the bare minimum
* for our operations:
*/
struct T { // substituent for std::tuple<int>
int x;
};
struct Tr { // substituent for std::tuple<int&>
int& xr;
auto operator=(const T& other)
{
// std::get<I>(*this) = std::get<I>(other);
xr = other.x;
}
};
auto foo()
{
int a;
Tr{a} = T{24};
return a; // 24
}
/*
* And finally, I like to get rid of the structures all together (well,
* it's not 100% equivalent, but it's close enough for us, and explicit
* enough to allow it):
*/
auto foo()
{
int a;
{ // block substituent for temporary variables
// Tr{a}
int& tr_xr = a;
// T{24}
int t_x = 24;
// = (asignement)
tr_xr = t_x;
}
return a; // 24
}
/*
* So basically, `std::tie(a)` initializes a data member reference to
* `a`. `std::tuple<int>(24)` creates a data member with value `24`, and
* the assignment assigns 24 to the data member reference in the first
* structure. But since that data member is a reference bound to `a`,
* that basically assigns `24` to `a`.
*
* [1]: http:en.cppreference.com/w/cpp/utility/tuple/operator%3D
*
* [bolov] [so/q/43762651] [cc by-sa 3.0]
*/
$
cheat.sh