user1899020
user1899020

Reputation: 13575

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

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
};

Upvotes: 3

Views: 567

Answers (5)

Khurshid
Khurshid

Reputation: 2724

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};
}

Upvotes: 2

scalexm
scalexm

Reputation: 11

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

Upvotes: 1

eerorika
eerorika

Reputation: 238361

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.

Upvotes: 1

iavr
iavr

Reputation: 7637

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;

Upvotes: 6

Manu343726
Manu343726

Reputation: 14174

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
};

Upvotes: 0

Related Questions