I want to group data of tuples in tuples into a tuple of vectors. Given is a tuple of tuples containing data. There are multiple duplicate types, that's data should be grouped into a vector of each unique type.
So far boost::mp11
is the most elegant way I found, to build a type
std::tuple<std::vector<T1>, std::tuple<std::vector<T2>, ...>
based on an incoming parameter pack
std::tuple<std::tuple<some_data>, std::tuple<std::tuple<some_more_data>, ...
using mp_unique
and mp_transform
to get vectors for each unique type.
Happy if you know a std::
ish alternative (optional).
I am stuck finding a way to fill tuple elements into matching vectors? I'd be excited, finding a fold expression'ish way to do so.
This example should help to give a better idea of what I have in mind.
template <typename T> using vector_of = std::vector<T>;
static constexpr auto tuple_to_vector(auto&&... Vs) noexcept {
// merged_tuple = std::tuple<int, double, int, char, int, float, char, float, double>
auto merged_tuple = std::tuple_cat(std::forward<decltype(Vs)>(Vs)...);
// vector_t = std::tuple<std::vector<int>, std::vector<double>, std::vector<char>, std::vector<float>>
using vector_t = boost::mp11::mp_transform<vector_of, boost::mp11::mp_unique<decltype(merged_tuple)>>;
vector_t vec;
// how to add merged_tuple elements to vec
// resulting in
// std::tuple< std::vector<int>{1,3,2}, std::vector<double>{2.0,3.0}, std::vector<char>{'b','c'}, std::vector<float>{3.0f,2.0f}>
return std::move(vec);
};
int main() {
constexpr auto vec = tuple_to_vector(
std::make_tuple(1,2.0,3),
std::make_tuple('b',2,3.0f),
std::make_tuple('c',2.0f,3.0)
);
// expecting
// vec = std::tuple<
// std::vector<int>{1,3,2},
// std::vector<double>{2.0,3.0},
// std::vector<char>{'b','c'},
// std::vector<float>{3.0f,2.0f}
// >
return 42;
}
CodePudding user response:
You can use std::apply
to expand the elements of merged_tuple
, and use std::get
to extract the corresponding vector
in vector_t
according to the type of the element, and fill into the vector
through push_back
std::apply([&vec](auto... args) {
(std::get<std::vector<decltype(args)>>(vec).push_back(args), ...);
}, merged_tuple);
Note that vec
cannot be constexpr
even in C 20 since its allocation is non-transient. If you really want to construct a constexpr
tuple, then you can use std::array
since the size of the array can be obtained at compile time. Here is a demo that converts the resulting vec
to the corresponding std::array
type.