Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mixing types and nontypes in variadic template parameters?

Is it possible to do mixing of types and nontypes in variadic template parameters? If I were to pass a std::array for instance to this class as parameter T, I would need to also pass a type for the array and a length, but the way I tried it below causes an error when encountering a value, because it only expects types for Types:

template <
    template<class, std::size_t>  class T,
    class ... Types>
class C {

    T<Types...> storage;
};

int main(){
    C<std::array, int, 3> c;
}

Error message:

error: template argument for template type parameter must be a
      type
    Container<std::array, int, 3> c;
                               ^

Is there a way to pass types and values in a variadic context?

like image 564
lo tolmencre Avatar asked Feb 08 '17 23:02

lo tolmencre


People also ask

What is args && args?

Args declares an "object parameter" (pass by value) and Args&& declares a reference parameter (pass by reference). Passing by reference allows one to avoid copying the argument when that is unnecessary.

What is the use of Variadic templates?

With the variadic templates feature, you can define class or function templates that have any number (including zero) of parameters. To achieve this goal, this feature introduces a kind of parameter called parameter pack to represent a list of zero or more parameters for templates.

What is Variadic template in C++?

Variadic templates are class or function templates, that can take any variable(zero or more) number of arguments. In C++, templates can have a fixed number of parameters only that have to be specified at the time of declaration.

What is parameter pack in c++?

Parameter packs (C++11) A parameter pack can be a type of parameter for templates. Unlike previous parameters, which can only bind to a single argument, a parameter pack can pack multiple parameters into a single parameter by placing an ellipsis to the left of the parameter name.


2 Answers

Is it possible to do mixing of types and nontypes in variadic template parameters?

No. You can't mix and match. But since you can wrap a value in a type but not the other way around, you can just stay in the world of types:

template <template<class...> class T, class ... Types>
class C {    
    T<Types...> storage;
};

And then it's just a matter of making std::array work with just types:

template <class T, class N>
using my_array = std::array<T, N::value>;

template <size_t N>
using size_ = std::integral_constant<size_t, N>;

So your original example becomes:

C<my_array, int, size_<3>> c;
like image 147
Barry Avatar answered Sep 19 '22 13:09

Barry


As I see, you alreadty hardcoded the number and types of parameter the class T must take as template parameter. You don't need variadic templates here. Just do this instead:

template <
    template<class, std::size_t>  class T,
    class A, std::size_t N>
class C {

    T<A, N> storage;
};

int main(){
    C<std::array, int, 3> c; // works!
}

If you wish to use variadic templates, then put it in the template template parameter too:

template <
    template<typename...>  class T,
    typename... Types>
class C {

    T<Types...> storage;
};

If you wish to use that version but still want to use std::array, you can create an alias to std::array that already has a size:

template<typename T>
using array3 = std::array<T, 3>;

C<array3, int> c;

Alternatively, you can also create some sort of template template alias that let you choose the size:

template<std::size_t n>
struct sized_array {
    template<typename T>
    using array = std::array<T, n>;
};

C<sized_array<5>::array, int>;
like image 40
Guillaume Racicot Avatar answered Sep 22 '22 13:09

Guillaume Racicot