Search code examples
c++containersvariadic-templates

Template pack of pack


For example, we have types containers Container1< Pack1...> , Container2< Pack2...> etc. And if we wrote:

template <template <typename... Pack>
          typename ...Containers,

          typename... Pack
          >
auto Concatinate(Container<Pack...>...)
    -> Container<Pack...>;

This would not work with containers of different types of template arguments.That is, The function cannot be instantiated with these containers: Container1<Pack1...>, Container2<Pack2...> etc. If Pack1... != Pack2... etc.

But I want one small function, like this one, that can combine the types of the template arguments into a container.

Is there

typename ... ... PackOfPack

?

(Types container means structure kind of tuple)


Solution

  • What about using std::tuple_cat()?

    I mean... what about something as follows ?

    template <template <typename ...> class Cnt, typename ... Ts>
    std::tuple<Ts...> to_tuple (Cnt<Ts...>);
    
    template <typename ... Ts>
    auto concatinate (Ts ... ts)
       -> decltype ( std::tuple_cat(to_tuple(ts)...) );
    

    The preceding concatinate() return a std::tuple with all types contained in all Ts... type container (given that all Ts... are types container) but if you want another return-container, the construction of a from_tuple() function (so -> decltype ( from_tuple(std::tuple_cat(to_tuple(ts)...)) );) is trivial

    The following is a full compiling example

    #include <tuple>
    #include <iostream>
    #include <functional>
    
    template <template <typename ...> class Cnt, typename ... Ts>
    std::tuple<Ts...> to_tuple (Cnt<Ts...>);
    
    template <typename ... Ts>
    auto concatinate (Ts ... ts)
       -> decltype ( std::tuple_cat(to_tuple(ts)...) );
    
    
    template <typename...> struct cnt1 { };
    template <typename...> struct cnt2 { };
    template <typename...> struct cnt3 { };
    
    int main()
     {
       using pack1 = cnt1<int, long, long long>;
       using pack2 = cnt2<long, long long, long>;
       using pack3 = cnt3<long long, long, int>;
    
       using expected_tuple = std::tuple<int, long, long long,
                                         long, long long, long,
                                         long long, long, int>;
    
       using final_tuple = decltype(concatinate(std::declval<pack1>(),
                                                std::declval<pack2>(),
                                                std::declval<pack3>()));
    
       static_assert( std::is_same_v<expected_tuple, final_tuple>, "!" );
    
     }