c++stdtuple

Copying elements of multiple source tuples to the destination tuple


I'm trying to assign values of all elements from multiple source tuples to elements of one destination tuple as follows:

#include <tuple>

template<std::size_t from_element, typename dstT, typename srcTs, std::size_t... Is>
void assign_elms(dstT& dst, const srcTs& src, std::index_sequence<Is...>) {
    ((std::get<from_element + Is>(dst) = std::get<Is>(src)), ...);
}

template<std::size_t from_element, typename dstT, typename srcT>
void assign_impl(dstT& dst, const srcT& src) {
    assign_elms<from_element>(dst, src, std::make_index_sequence<std::tuple_size_v<srcT>>());
}

template<typename dstT, typename... srsTs>
void assign(dstT& dst, const srsTs&... srcs) {
    (assign_impl<???>(dst, srcs), ...); // ???
}

template<typename... Ts>
using tuple_concat_t = decltype(std::tuple_cat(std::declval<Ts>()...));

int main() {

    std::tuple t1{ 1, 2.2f, 3.33 };
    std::tuple t2{ 4, 5.5f };
    std::tuple t3{ 6 };

    tuple_concat_t<decltype(t1), decltype(t2), decltype(t3)> tr;
    assign(tr, t1, t2, t3); // required (1, 2.2f, 3.33, 4, 5.5f, 6)
}

I want to create a destination tuple in advance and then assign elements many times. But I don't know what to substitute instead of '???'. Please help me.

I solved this problem using recursion, but I want to do it without recursion.

Creating a new tuple doesn't suit me:

template <typename... Ts>
auto tuple_concat(const Ts&... srcs) { return std::tuple_cat(srcs...); }

Solution

  • You might create an array of offsets and iterate over it:

    template<typename dstT, typename... srsTs>
    void assign(dstT& dst, const srsTs&... srcs) {
        constexpr std::array offsets = [](){
            std::array<std::size_t, 1 + sizeof...(srcs)> res{{0, std::tuple_size_v<srsTs>...}};
            std::partial_sum(res.begin(), res.end(), res.begin());
    
            return res;
        }();
        [&]<std::size_t...Is>(std::index_sequence<Is...>){
            (assign_impl<offsets[Is]>(dst, srcs), ...);
        }(std::make_index_sequence<sizeof...(srsTs)>());
    }
    

    Demo.