Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Variadic variadic template template parameters

Is there a straightforward way to have variadic variadic template template parameters. For instance consider the following function signature

template<template<typename,size_t...> class Pack, 
  typename T, size_t ... Args>
void foo(const Pack<T,Args...>& a);

If we want to pass two Packs we have to now do an overload

template<template<typename,size_t...> class Pack, 
  typename T, size_t ... Args0, size_t ... Args1>
void foo(const Pack<T,Args0...>& a, const Pack<T,Args1...>& b);

Now what if we want to pass a variable number of objects of Pack with different variadic parameters e.g. Args0...,Args1...,Args2....

So I was thinking if there is a practical way of doing something along the lines of (the following is certainly a sketch representation).

template<template<typename,size_t...> ... class Pack, typename T,...>  
void foo(const Pack<T,...> ... packs);
like image 930
Tasam Farkie Avatar asked Jul 27 '16 11:07

Tasam Farkie


2 Answers

I would just use a normal variadic template:

template<typename... Ts>  
void foo(const Ts&... packs) {

}

Then write a trait to extract the type and size_ts. You could easily add some helper alias templates to do whatever you fancy.

template <typename T> struct extract_args;

template <template <typename, size_t...> class Pack, typename T, size_t... Args> 
struct extract_args<Pack<T,Args...>> {
    using type = T;
    using args = std::index_sequence<Args...>;
};

Then within foo you can extract the arguments and use them however you like. For example, to get a std::tuple containing all the Ts from the packs:

using all_ts = std::tuple<typename extract_args<Ts>::type...>;
like image 155
TartanLlama Avatar answered Oct 16 '22 06:10

TartanLlama


I propose you to manage Pack arguments recursively, in this way

#include <array>

template <typename T, std::size_t ... Args>
struct  testS
 { };

void foo ()
 { /* terminal iteration */ }

template <template <typename, std::size_t...> class Pack,
          typename T, std::size_t ... Args, typename ... Packs>  
void foo (const Pack<T, Args...> pack0, Packs ... packs)
 { 
   // do something with pack0

   foo(packs...);
 }

int main()
 {
   foo(testS<int>{}, std::array<long, 5U>{}, testS<char, 7U, 9U, 11U>{});

   return 0;
 }

--- Edit ---

Modified example to show the use with different types and a variable number of std::size_t template parameters.

like image 41
max66 Avatar answered Oct 16 '22 07:10

max66