Search code examples
c++c++17variadic-templatesstdtuplestructure-of-arrays

How to create a tuple of vectors of type deduced from a variadic template in C++17?


I have implemented a collection class that converts a vector of tuples to a tuple of vectors (it is essentially an AOS to SOA conversion). This code works for this example of two template classes. I was trying to make it more generic by using variadic templates. In order to do that I need to create the type for the member variable m_col. In C++17, is it possible to convert a tuple to a tuple of vectors? So the type of the member variance m_col in this example will be generated automatically from template types.

template<class T1, class T2>
class Collection
{
    std::tuple<std::vector<T1>, std::vector<T2>> m_col;

public:
    void addRow(const std::tuple<T1, T2>& data)
    {
        std::get<0>(m_col).push_back(std::get<0>(data));
        std::get<1>(m_col).push_back(std::get<1>(data));
    } 

    void show()
    {
        std::cout << std::get<0>(m_col1).size() <<std::endl;
    }
};


int main()
{
    using data_t = std::tuple<int, double>;
    data_t data{1,1.0};
    using col_t = Collection<int, double>;
    col_t col;
    col.addRow(data);    
    col.show();
}

Solution

  • You're using C++17 so... what about using template folding and some std::apply()?

    I mean

    template <typename ... Ts>
    class Collection
     {
       private:
          std::tuple<std::vector<Ts>...> m_col;
    
       public:
          void addRow (std::tuple<Ts...> const & data)
           {
              std::apply([&](auto & ... vectors){
                         std::apply([&](auto & ... values){
                                    (vectors.push_back(values), ...);},
                                    data); },
                         m_col);        
           } 
    
          void show () const
           {
             std::apply([](auto & ... vectors){
                 ((std::cout << vectors.size() << '\n'), ...);}, m_col);
           }
     };