Reputation: 726639
I would like to access type's index when expanding a type parameter pack into an std::tuple<...>
.
For example, given a type pack of <int, double, float>
I would like to build an std::tuple<...>
that looks as follows:
std::tuple<std::array<int,0>, std::array<double,1>, std::array<float, 2>>
// ^ ^ ^ ^ ^ ^
// T I T I T I
Here is an implementation that does almost exactly what I want, but it works only for type packs of size 3 (see the comment next to the hack). How do I fix this to work independently of TT...
s size?
#include <tuple>
#include <utility>
#include <array>
#include <iostream>
template <typename... TT>
struct Foo {
template <std::size_t... Indices>
struct Baz {
std::tuple<std::array<TT,Indices>...> baz;
};
Baz<0,1,2> bar; // <<<=== Here is the hack: I make a fixed-size pack; I want it to match TT...
};
int main() {
Foo<int,double,float> foo;
std::cout << std::get<0>(foo.bar.baz).size() << std::endl;
std::cout << std::get<1>(foo.bar.baz).size() << std::endl;
std::cout << std::get<2>(foo.bar.baz).size() << std::endl;
return 0;
}
Upvotes: 4
Views: 892
Reputation: 122516
You are on the right track of nesting to have two packs. What you need now is a std::integer_sequence
that lets you create the desired pack instead of hardcoding it via Baz<0,1,2> bar;
.
The basic idea is to define a function template that takes a std::integer_sequence<size_t,I...>
parametrized on a pack and call that with a std::make_integer_sequence<size_t,N>
so the pack I...
can be deduced from a single number N
, then it is just folding:
#include <tuple>
#include <utility>
#include <array>
#include <iostream>
#include <utility>
#include <type_traits>
template <typename...Ts>
struct foo {
static const size_t N = sizeof...(Ts);
template <size_t ... I>
static auto helper(std::integer_sequence<size_t,I...>){
return std::tuple<std::array<Ts,I>...>{};
}
using type = decltype(helper(std::make_integer_sequence<size_t,N>{}));
};
int main() {
std::cout << std::is_same< std::tuple<std::array<int,0>, std::array<double,1>, std::array<float, 2>>,
foo<int,double,float>::type >::value;
}
Upvotes: 6