user1899020
user1899020

Reputation: 13575

How to tie two tuples?

How to tie two tuples? For example

std::tuple<int, char> a;
std::tuple<double> b;

Is it possible to write a function my_tie(a, b) that returns std::tuple<int&, char&, double&> so that after

my_tie(a, b) = make_tuple(1, 'a', 3.14);

a == std::tuple<int, char>{1, 'a'} and b == std::tuple<double>{3.14}. That is, the my_tie function (different from std::tie) first unties the tuples and then ties all elements together.

Upvotes: 3

Views: 353

Answers (2)

Brian Bi
Brian Bi

Reputation: 119641

(Updated Dec 29, 2014 to use std::index_sequence_for)

Here's a solution that uses C++14's index sequences:

#include <tuple>
#include <utility>

template <class... T1, class... T2,
          std::size_t... i, std::size_t... j>
auto tie_helper(std::tuple<T1...>& t1, std::tuple<T2...>& t2,
                std::index_sequence<i...>, std::index_sequence<j...>) {
    return std::tuple<T1&..., T2&...> {std::get<i>(t1)..., std::get<j>(t2)...};
}

template <class... T1, class... T2>
auto tie(std::tuple<T1...>& t1, std::tuple<T2...>& t2) {
    typedef std::index_sequence_for<T1...> s1;
    typedef std::index_sequence_for<T2...> s2;
    return tie_helper(t1, t2, s1{}, s2{});
}

Upvotes: 3

T.C.
T.C.

Reputation: 137414

Slightly more general than @Brian's version:

// construct a tuple of Ts&... from a tuple of Ts...
template <class... T, std::size_t... i>
auto to_tuple_ref_helper(std::tuple<T...>& t, std::index_sequence<i...>) {
    return std::tuple<T&...> {std::get<i>(t)...};
}

template <class... T>
auto to_tuple_ref(std::tuple<T...>& t) {
    return to_tuple_ref_helper(t, std::index_sequence_for<T...>());
}

// and a tuple containing a single reference from all other types
template <class T>
auto to_tuple_ref(T& t) {
    return std::tuple<T&>{t};
}

// tuple_cat the tuples of references together
template <class... Ts>
auto flattening_tie(Ts &...args) {
    return std::tuple_cat(to_tuple_ref(args)...);
}

Demo.

Upvotes: 3

Related Questions