Вопрос

How to get the i-th integer in a integer parameter pack? For example

template<int... Is>
struct A
{
    enum { CONSTANT_0 = Is[0] }; //Assume the sizeof...(Is) > the index requested
};
Это было полезно?

Решение

Like that:

template <size_t I, int N, int... R>
struct pick : pick <I - 1, R...> { };

template <int N, int... R>
struct pick <0, N, R...> : std::integral_constant <int, N> { };

so that

pick <3, 1, 2, 3, 4, 5, 6>::value

equals 4, and

template<int... Is>
struct A
{
    enum { CONSTANT_0 = pick <0, Is...>::value };
};

is how you would use it in your case.


Another way:

template <size_t I, int... N>
using pick = typename std::tuple_element <I,
   std::tuple <std::integral_constant <int, N>...>
>::type;

Другие советы

In your specific example, when the first (or n first) parameters are treated specially, you can define the template like this:

template<int head, int... tail>
struct A {
    enum { CONSTANT_0 = head }; // no need to assume anything about tail...
};

This also makes it clear for the caller that there must be at least one parameter.

Or you could try this solution, which is basically the same as proposed previously but with standard functions:

template<int ... Is>
struct A
{
    enum { CONSTANT_0 = std::get<0>(std::make_tuple(std::forward<int>(Is)...)) };
};

Fails at compile time if the index is out of range

All above answers need deep recursive template instantinations. See following source, without any extra template instantinations:

#include <iostream>

template< int ... i >
struct A
{
    static constexpr int at_f(int idx)
    {
         using int_list = int[sizeof...(i)];
         return int_list{ i... } [ idx];   
    }

    template< int j>
    struct at 
    {
        enum{ value = at_f(j) };
    };

};



int main()
{
    std::cout << A<0,1,3,4>::at<3>::value << std::endl;
    //or
    int b[ A<0,1,2,3,4>::at_f(2) ]  = {0};
}

Use a bit of template metaprogramming:

template<int... INTEGERS>
struct integer_sequence {};

template<typename INDICES , std::size_t INDEX>
struct get;

template<int HEAD , int... TAIL , std::size_t INDEX>
struct get<integer_sequence<HEAD,TAIL...>,INDEX> : public get<integer_sequence<TAIL...>,INDEX-1> {};

template<int HEAD , int... TAIL>
struct get<integer_sequence<HEAD,TAIL...>,0> : public std::integral_constant<int,HEAD>{};

You could use it as:

template<int... Is>
struct A
{
    enum { CONSTANT_0 = get<integer_sequence<Is...>,0>::value }; //Assume the sizeof...(Is) > the index requested
};
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top