For a more concise answer, see what 康桓瑋 suggests.
In case you don't have access to C++20's templated lambda expressions, here is the code that uses C++17's features.
First, I would like to produce a new tuple that will consist of merged entries, that is:
auto t1 = std::tuple<std::vector<int>, std::vector<int>>{
{1, 2, 3}, {7, 8}
};
auto t2 = std::tuple<std::vector<int>, std::vector<int>>{
{4, 5, 6}, {9}
};
auto merged = merge_inner(t1, t2);
Thus, merge_inner needs to accept any number of said tuples:
template <
template <typename> typename Tuple,
template <typename> typename... Tuples,
typename... Vectors
>
auto merge_inner(Tuple<Vectors...> first, Tuples<Vectors...> const&... args) {
constexpr auto number_of_vectors = sizeof...(Vectors);
append_values_elementwise(first, std::make_index_sequence<number_of_vectors>(), args...);
return first;
}
We copy the first argument and take the rest by const&. To all vectors (elements) of first, we append those which are inside args... by calling append_values_elementwise. I used std::index_sequence in order to help fold-expressions making my life a little easier:
template <
template <typename> typename Tuple,
std::size_t... Ns,
template <typename> typename... Tuples,
typename... Vectors
>
auto append_values_elementwise(
Tuple<Vectors...>& first,
std::index_sequence<Ns...> sequence,
Tuple<Vectors...> const& first_arg,
Tuples<Vectors...> const&... args
) {
((std::get<Ns>(first).insert(
std::get<Ns>(first).end(),
std::get<Ns>(first_arg).begin(), std::get<Ns>(first_arg).end()
)), ...);
append_values_elementwise(first, sequence, args...);
}
This is just an implementation detail that extracts the next tuple from args... and inserts the elements of its vectors into first. sequence represents a meta-list of indexes suitable to be used with std::get. This is a metaprogramming way of looping over tuples values.
We then recurse with the rest of the arguments.
Lastly, we need a fallback to when we only have one tuple left to merge. The terminal case, which no longer recurses:
template <
template <typename> typename Tuple,
std::size_t... Ns,
template <typename> typename... Tuples,
typename... Vectors
>
auto append_values_elementwise(
Tuple<Vectors...>& first,
std::index_sequence<Ns...>,
Tuple<Vectors...> const& first_arg
) {
((std::get<Ns>(first).insert(
std::get<Ns>(first).end(),
std::get<Ns>(first_arg).begin(), std::get<Ns>(first_arg).end()
)), ...);
}
Demo.