template parameter packs access Nth type and Nth element
Solution 1:
Others have already answered that it can be done via std::tuple
. If you want to access the Nth type of a parameter pack, you may find the following metafunction handy:
template<int N, typename... Ts> using NthTypeOf =
typename std::tuple_element<N, std::tuple<Ts...>>::type;
Usage:
using ThirdType = NthTypeOf<2, Ts...>;
Solution 2:
C++11 doesn't have corresponding operators which is the reason they are proposed. With C++11 you'll need to either extract the corresponding information yourself or use a class which already does the necessary operation. The easiest approach is probably to just use std::tuple<T...>
which already implements the corresponding logic.
If you wonder how std::tuple<T...>
currently implements these operations: it is basically an exercise in functional programming using a fairly bad functional programming notation. Once you know how to get the n
-th type of the sequence, getting the n
-th element using inheritance from base classes parameterized on index and type is fairly trivial. Implementing something like tuple_element<N, T...>
could look something like this:
template <int N, typename... T>
struct tuple_element;
template <typename T0, typename... T>
struct tuple_element<0, T0, T...> {
typedef T0 type;
};
template <int N, typename T0, typename... T>
struct tuple_element<N, T0, T...> {
typedef typename tuple_element<N-1, T...>::type type;
};
The actual more challenging bit in implementing something like std::tuple<T...>
is conjuring up a list of indices so you got a parallel list of type and integers which can then be expanded, e.g., for a list of base classes using something like (how the internal details look exactly will differ but the basic idea of having a parallel parameters packs for the types and their indices will be somehow there):
template <typename... T, int... I>
class tuple_base<tuple_types<T...>, tuple_indices<I...>>:
public tuple_field<T, I>... {
};
Solution 3:
Access N-th element?
Using std::forward_as_tuple
:
template <int I, class... Ts>
decltype(auto) get(Ts&&... ts) {
return std::get<I>(std::forward_as_tuple(ts...));
}
Example usage:
template<class...Ts>
void foo(Ts&&...ts){
auto& first = get<0>(ts...);
auto second = get<1>(ts...);
first = 'H';
second = 'E';
(std::cout << ... << ts);
}
foo('h','e','l','l','o');
// prints "Hello"
This answer is to supplement Emile Cormier's answer which gives only the n-th type.