Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to typedef a parameter pack?

Is it possible to typedef a parameter pack? For example

template<class T, class... Args>
struct A
{
    typedef T Type; // We typedef it, then its derived class can use it.
                    // How about for parameter packs?

    // Option 1:
    typedef Args Arguments;

    // Option 2:
    using Arguments = Args;

    // Option 3: I can put in a tuple, but how can I untuple it to a pack
    typedef tuple<Args...> Tuple;
};

I want to using the above technique to implement the following

template<int... VALUES>
struct IntegralSequence
{
    enum { SIZE = sizeof...(VALUES) };

    template <unsigned I>
    struct At
    {
        enum { VALUE = typename tuple_element<I, 
                       tuple<integral_constant<int, VALUES>...>>::type::value
             };
    };
};

template<unsigned N>
struct AscendingSequence
{
    typedef IntegralSequence<AscendingSequence<N-1>::VALUES..., N> Type;
    using VALUES = Type::VALUES; // if it works
};

template<>
struct AscendingSequence<1>
{
    typedef IntegralSequence<0> Type;
    using VALUES = Type::VALUES; // if it works
};
like image 329
user1899020 Avatar asked Apr 09 '14 16:04

user1899020


People also ask

What is a 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.

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. However, variadic templates help to overcome this issue.

What is Pack expansion?

Pack expansion A pattern followed by an ellipsis, in which the name of at least one parameter pack appears at least once, is expanded into zero or more comma-separated instantiations of the pattern, where the name of the parameter pack is replaced by each of the elements from the pack, in order. template<class...


1 Answers

You can pack them in a tuple, or in a arbitrary empty class template (I prefer to call it pack):

template<typename... Args>
struct pack { };

template<class T, class... Args>
struct A
{
    using args = pack<Args...>;
};

If you are then given A e.g. in function template and you want to deduce Args..., you can do it like this:

template<typename... Args, typename A>
void f(pack<Args...>, A a) { /* use Args... here */ }

template<typename A>
void f(A a) { f(typename A::args(), a); }

pack being empty is convenient in situations like that. Otherwise you'd need some other means to pass args without actually passing a tuple that contains data (e.g. wrapping it into yet another empty struct).

Or, in a class template specialization:

template<typename T, typename = typename T::args>
struct B_impl;

template<typename T, typename... Args>
struct B_impl <T, pack<Args...> >
{
    // use Args... here
};

template<typename T>
using B = B_impl<T>;

I guess these are the options of deduction and partial specialization that @dyp mentioned.


EDIT This is in response to the edited question. Ok, this is clearly an XY problem. If IntegralSequence is all you need, you can use std::make_integer_sequence in C++14 or check my answer to another question just a few minutes ago for an efficient implementation.

like image 165
iavr Avatar answered Oct 22 '22 11:10

iavr