c++stdtuplestd-tie

Unpacking nested tuples in C++


std::tie provides a convenient way to unpack the contents of a tuple in C++ into separately defined variables, like the sample below illustrates

int a, b, c, d, e, f;

auto tup1 = std::make_tuple(1, 2, 3);
std::tie(a, b, c) = tup1;

However, if we have a nested tuple like below

auto tup2 = std::make_tuple(1, 2, 3, std::make_tuple(4, 5, 6));

attempting to compile the code

std::tie(a, b, c, std::tie(d, e, f)) = tup2;

fails with an error

/tmp/tuple.cpp:10: error: invalid initialization of non-const reference of type ‘std::tuple<int&, int&, int&>&’ from an rvalue of type ‘std::tuple<int&, int&, int&>’
  std::tie(a, b, c, std::tie(d, e, f)) = tup2;
                            ^

Is there an idiomatic way to unpack a tuple of tuples in C++?


Solution

  • When you know that there is no risk, you can convert an rvalue reference to an lvalue one through the following helper function :

    template <class T>
    constexpr T &lvalue(T &&v) {
        return v;
    }
    

    You can then use it thusly :

    std::tie(a, b, c, lvalue(std::tie(d, e, f))) = tup2;
    

    In your case there is indeed no problem in doing that, since the inner tuple only has to be alive for the duration of the statement, and it is (exactly) the case.