Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How to group data in tuples of tuples into a tuple of vectors

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).

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

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;
}

>Solution :

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);

Demo

Note that vec cannot be constexpr even in C++20 since its allocation is non-transient.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading