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...); }
CodePudding user response:
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.