Reputation: 13575
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
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
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
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
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
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