Related
It is possible to use template parameters pack as follows:
template <int T1, int... Ts>
struct Test {
static constexpr int sizes[] = {Ts...};
};
template <int T1, int... Ts>
constexpr int Test<T1, Ts...>::sizes[];
However, as it is detailed here, the template parameter pack must be the last template parameter. Hence, we cannot have a code such as this:
template <int T1, int... Ts, int Tn>
struct Test {
static constexpr int sizes[] = {Ts...};
Foo<Ts...> foo;
};
template <int T1, int... Ts, int Tn>
constexpr int Test<T1, Ts..., Tn>::sizes[];
In many cases, we need to have access to the last element of a set of template parameters. My question is, what's the best practice for realizing the above code?
Edit:
This is not duplicate of this question. I am trying to get everything except the last parameter (not the last parameter itself), since I need to define Foo as follows:
Foo<Ts...> foo;
You could go with the standard method of using std::index_sequence
template<template<auto...> typename Tmp, size_t... Is, typename... Args>
constexpr auto take_as(std::index_sequence<Is...>, Args...)
{
using Tup = std::tuple<Args...>;
return Tmp<std::tuple_element_t<Is, Tup>{}...>{};
}
template<auto... Vals>
struct except_last
{
template<template<auto...> typename Tmp>
using as = decltype(take_as<Tmp>(std::make_index_sequence<sizeof...(Vals) - 1>{},
std::integral_constant<decltype(Vals), Vals>{}...));
};
Which you use as
using F = except_last<1, 2, 3, 4>::as<Foo>; // F is Foo<1, 2, 3>
This is both easier to implement and read, but you potentially get O(n) instantiation depth. If you are obsessed with efficiency, you could do O(1) instantiation depth by abusing fold expressions
template<typename T>
struct tag
{
using type = T;
};
template<typename F, typename... Ts>
using fold_t = decltype((F{} + ... + tag<Ts>{}));
template<size_t N, typename... Ts>
struct take
{
template<typename T>
auto operator+(tag<T>) -> take<N - 1, Ts..., T>;
};
template<typename... Ts>
struct take<0, Ts...>
{
template<template<auto...> typename Tmp>
using as = Tmp<Ts{}...>;
template<typename T>
auto operator+(tag<T>) -> take<0, Ts...>;
};
template<auto... Vals>
struct except_last
{
template<template<auto...> typename Tmp>
using as = fold_t<take<sizeof...(Vals) - 1>,
std::integral_constant<decltype(Vals), Vals>...>::template as<Tmp>;
};
What's the most efficient way to access the last template parameter?
You could use a little helper to convert the parameter pack into an array.
template<int... Args>
struct pack {
static constexpr std::array as_array{ Args... };
};
You can then get the last argument with array indexing:
template <int T1, int... Ts>
struct Test {
static constexpr int last = pack<Ts...>::as_array[sizeof...(Ts) - 1];
integer_sequence is a way:
template <typename SeqN, typename Seq> struct TestImpl;
template <int... Ns, std::size_t ... Is>
struct TestImpl<std::integer_sequence<int, Ns...>, std::index_sequence<Is...>>
{
private:
using SeqTuple = std::tuple<std::integral_constant<int, Ns>...>;
public:
static constexpr int sizes[] = {std::tuple_element_t<Is, SeqTuple>::value...};
Foo<std::tuple_element_t<Is, SeqTuple>::value...> foo;
};
template <int N1, int N2, int... Ns> // At least 2 numbers
using Test = TestImpl<std::integer_sequence<int, N1, N2, Ns...>,
std::make_index_sequence<1 + sizeof...(Ns)>>;
Demo
I am using GCC8.2 and I would like to define a hierarchical tuple like this:
std::tuple<std::array<double,N>,
std::array<double,N/2>,
std::array<double,N/4>,
...,
std::array<double,2> > v ;
And then I have an algorithm to fill those arrays with the following specification:
template <int N>
std::array<double,N> get_array()
How can I write a generic algorithm to declare the tuple and fill it at compile time for any N?
Without recursion, you might do something like:
template <std::size_t N>
std::array<double, N> get_array() { return {{}}; }
namespace detail
{
constexpr std::size_t log2(std::size_t n)
{
std::size_t res = 0;
while (n != 0) {
n /= 2;
++res;
}
return res;
}
template <std::size_t N, std::size_t ...Is>
auto make_array_tuple_impl(std::index_sequence<Is...>)
{
return make_tuple(get_array<(N >> Is)>()...);
}
}
template <std::size_t N>
auto make_array_tuple()
{
return detail::make_array_tuple_impl<N>(std::make_index_sequence<detail::log2(N) - 1>());
}
Demo
This feels a bit involved, maybe there's a simpler solution.
// Pack of values
template <auto...>
struct vpack { };
// Concatenating two packs
template <class, class>
struct vpack_cat_;
template <auto... lhs, auto... rhs>
struct vpack_cat_<vpack<lhs...>, vpack<rhs...>> {
using type = vpack<lhs..., rhs...>;
};
template <class Lhs, class Rhs>
using vpack_cat = typename vpack_cat_<Lhs, Rhs>::type;
// Building a decreasing exp scale...
template <int N>
struct exp_scale_ {
using type = vpack_cat<
vpack<N>,
typename exp_scale_<N / 2>::type
>;
};
// ... stopping at 2
template <>
struct exp_scale_<2> {
using type = vpack<2>;
};
template <int N>
using exp_scale = typename exp_scale_<N>::type;
// Building the tuple's type from the scale
template <class ScalePack>
struct exp_tuple_;
template <auto... Scale>
struct exp_tuple_<vpack<Scale...>> {
using type = std::tuple<std::array<double, Scale>...>;
};
template <class Scale>
using exp_tuple = typename exp_tuple_<Scale>::type;
// The known get_array() function
template <int N>
std::array<double,N> get_array() { return {}; }
// Initializing the tuple
template <auto... Scale>
auto get_tuple(vpack<Scale...>) {
return exp_tuple<vpack<Scale...>>{
get_array<Scale>()...
};
}
template <int N>
auto get_tuple() {
return get_tuple(exp_scale<N>{});
}
See it live on Coliru
Are you sure that your sequence in
std::tuple<std::array<double,N>,
std::array<double,N/2>,
std::array<double,N/4>,
...,
std::array<double,2> > v ;
ends with 2?
Supposing that you want to end with 2 or 1, I suppose you can use the following custom type traits to get the wanted index sequence
template <std::size_t N, std::size_t ... Is>
struct divSequence : public divSequence<(N>>1u), Is..., (N>>1u)>
{ };
template <std::size_t ... Is>
struct divSequence<2u, Is...> : public std::index_sequence<Is...>
{ };
template <std::size_t ... Is>
struct divSequence<1u, Is...> : public std::index_sequence<Is...>
{ };
So you only need the following make function (with helper)
template <std::size_t ... Is>
std::tuple<std::array<double, Is>...>
getDivTupleHelper (std::index_sequence<Is...> const &)
{ return { get_array<Is>()... }; }
template <std::size_t N>
auto getDivTuple ()
{ return getDivTupleHelper(divSequence<N>{}); }
The following is a full compiling C++14 example
#include <array>
#include <tuple>
#include <utility>
template <std::size_t N>
std::array<double,N> get_array ()
{ return {{ }}; }
template <std::size_t N, std::size_t ... Is>
struct divSequence : public divSequence<(N>>1u), Is..., (N>>1u)>
{ };
template <std::size_t ... Is>
struct divSequence<2u, Is...> : public std::index_sequence<Is...>
{ };
template <std::size_t ... Is>
struct divSequence<1u, Is...> : public std::index_sequence<Is...>
{ };
template <std::size_t ... Is>
std::tuple<std::array<double, Is>...>
getDivTupleHelper (std::index_sequence<Is...> const &)
{ return { get_array<Is>()... }; }
template <std::size_t N>
auto getDivTuple ()
{ return getDivTupleHelper(divSequence<N>{}); }
int main ()
{
using t0 = decltype( getDivTuple<15u>() );
using t1 = std::tuple<std::array<double, 7u>,
std::array<double, 3u>,
std::array<double, 1u>>;
using t2 = decltype( getDivTuple<16u>() );
using t3 = std::tuple<std::array<double, 8u>,
std::array<double, 4u>,
std::array<double, 2u>>;
static_assert( std::is_same<t0, t1>::value, "!");
static_assert( std::is_same<t2, t3>::value, "!");
}
If you need a C++11 solution... well... instead of std::index_sequence you can use a custom trivial substitute as
template <std::size_t ...>
struct myIndexSequence
{ }
and you need rewrite getDivTuple() to explicit the return type using decltype(); something as
template <std::size_t N>
decltype(getDivTupleHelper(divSequence<N>{})) getDivTuple ()
{ return getDivTupleHelper(divSequence<N>{}); }
I have to following problem:
template< size_t... N_i >
class A
{
// ...
};
template< size_t N, size_t... N_i >
A</* first N elements of N_i...*/> foo()
{
A</* first N elements of N_i...*/> a;
// ...
return a;
}
int main()
{
A<1,2> res = foo<2, 1,2,3,4>();
return 0;
}
Here, I want foo to have the return type A</* first N size_t of N_i...*/>, i.e., the class A which has as template arguments the first N elements of the parameter pack N_i.
Does anyone know how this can be implemented?
Here is the shortest solution that came to my mind (with two lines spent for an alias).
It follows a minimal, working example based on the code posted by the OP:
#include<functional>
#include<cstddef>
#include<utility>
#include<tuple>
template<std::size_t... V>
class A {};
template<std::size_t... V, std::size_t... I>
constexpr auto func(std::index_sequence<I...>) {
return A<std::get<I>(std::make_tuple(V...))...>{};
}
template<std::size_t N, std::size_t... V>
constexpr auto func() {
return func<V...>(std::make_index_sequence<N>{});
}
template<std::size_t N, std::size_t... V>
using my_a = decltype(func<N, V...>());
int main() {
A<1,2> res1 = func<2, 1, 2, 3, 4>();
// Or even better...
decltype(func<2, 1, 2, 3, 4>()) res2{};
// Or even better...
my_a<2, 1, 2, 3, 4> res3{};
}
This is a slight variation on #skypjack's answer that avoids using tuples:
template <size_t... N_i,size_t... M_i>
auto foo2(std::index_sequence<M_i...>)
{
constexpr size_t values[] = {N_i...};
return A<values[M_i]...>();
}
template <size_t N,size_t... N_i>
auto foo()
{
return foo2<N_i...>(std::make_index_sequence<N>());
}
The most direct subproblem is in the land of typelists:
template <class... Ts>
struct typelist {
using type = typelist;
static constexpr std::size_t size = sizeof...(Ts);
};
template <class T>
struct tag { using type = T; };
template <std::size_t N, class TL>
struct head_n {
using type = ???;
};
Now, head_n is just a matter of simple recursion - move an element from one list to another list N times starting from an empty list.
template <std::size_t N, class R, class TL>
struct head_n_impl;
// have at least one to pop from and need at least one more, so just
// move it over
template <std::size_t N, class... Ts, class U, class... Us>
struct head_n_impl<N, typelist<Ts...>, typelist<U, Us...>>
: head_n_impl<N-1, typelist<Ts..., U>, typelist<Us...>>
{ };
// we have two base cases for 0 because we need to be more specialized
// than the previous case regardless of if we have any elements in the list
// left or not
template <class... Ts, class... Us>
struct head_n_impl<0, typelist<Ts...>, typelist<Us...>>
: tag<typelist<Ts...>>
{ };
template <class... Ts, class U, class... Us>
struct head_n_impl<0, typelist<Ts...>, typelist<U, Us...>>
: tag<typelist<Ts...>>
{ };
template <std::size_t N, class TL>
using head_n = typename head_n_impl<N, typelist<>, TL>::type;
Going from this to your specific problem I leave as an exercise to the reader.
An alternate approach is via concatenation. Convert every element of a typelist<Ts...> into either a typelist<T> or a typelist<>, and then concat them all together. concat is straightforward:
template <class... Ts>
struct concat { };
template <class TL>
struct concat<TL>
: tag<TL>
{ };
template <class... As, class... Bs, class... Rest>
struct concat<typelist<As...>, typelist<Bs...>, Rest...>
: concat<typelist<As..., Bs...>, Rest...>
{ };
And then we can do:
template <std::size_t N, class TL, class = std::make_index_sequence<TL::size>>
struct head_n;
template <std::size_t N, class... Ts, std::size_t... Is>
struct head_n<N, typelist<Ts...>, std::index_sequence<Is...>>
: concat<
std::conditional_t<(Is < N), typelist<Ts>, typelist<>>...
>
{ };
template <std::size_t N, class TL>
using head_n_t = typename head_n<N, TL>::type;
The advantage of this latter approach is that concat can be replaced in C++17 by a fold-expression given an appropriate operator+:
template <class... As, class... Bs>
constexpr typelist<As..., Bs...> operator+(typelist<As...>, typelist<Bs...> ) {
return {};
}
which allows:
template <std::size_t N, class... Ts, std::size_t... Is>
struct head_n<N, typelist<Ts...>, std::index_sequence<Is...>>
{
using type = decltype(
(std::conditional_t<(Is < N), typelist<Ts>, typelist<>>{} + ... + typelist<>{})
);
};
This is fairly simple with Boost.Hana:
namespace hana = boost::hana;
template<size_t... vals>
auto make_a(hana::tuple<hana::integral_constant<size_t, vals>...>)
{
return A<vals...>{};
}
template<size_t N, size_t... vals>
auto foo(){
constexpr auto front = hana::take_front(
hana::tuple_c<size_t, vals...>,
hana::integral_c<size_t,N>
);
return detail::make_a(front);
}
live demo
You could also make use of variadic generic lambda expression and reusable helper structure to perform compile-time iteration:
#include <utility>
#include <tuple>
template <std::size_t N, class = std::make_index_sequence<N>>
struct iterate;
template <std::size_t N, std::size_t... Is>
struct iterate<N, std::index_sequence<Is...>> {
template <class Lambda>
auto operator()(Lambda lambda) {
return lambda(std::integral_constant<std::size_t, Is>{}...);
}
};
template <size_t... Is>
struct A { };
template <size_t N, size_t... Is>
auto foo() {
return iterate<N>{}([](auto... ps){
using type = std::tuple<std::integral_constant<std::size_t, Is>...>;
return A<std::tuple_element_t<ps, type>{}...>{};
});
}
int main() {
decltype(foo<3, 1, 2, 3, 4>()) a; // == A<1, 2, 3> a;
}
Unfortunately, such method requires to define additional Helper types
template< size_t... N_i >
class A
{
};
template <size_t... N_i>
struct Helper;
template <size_t... N_i>
struct Helper<0, N_i...>
{
typedef A<> type;
};
template <size_t N0, size_t... N_i>
struct Helper<1, N0, N_i...>
{
typedef A<N0> type;
};
template <size_t N0, size_t N1, size_t... N_i>
struct Helper<2, N0, N1, N_i...>
{
typedef A<N0, N1> type;
};
template< size_t N, size_t... N_i >
typename Helper<N, N_i...>::type foo()
{
typename Helper<N, N_i...>::type a;
return a;
}
Suppose I have a template which is parametrized by a class type and a number of argument types. a set of arguments matching these types are stored in a tuple. How can one pass these to a constructor of the class type?
In almost C++11 code:
template<typename T, typename... Args>
struct foo {
tuple<Args...> args;
T gen() { return T(get<0>(args), get<1>(args), ...); }
};
How can the ... in the constructor call be filled without fixing the length?
I guess I could come up with some complicated mechanism of recursive template calls which does this, but I can't believe that I'm the first to want this, so I guess there will be ready-to-use solutions to this out there, perhaps even in the standard libraries.
C++17 has std::make_from_tuple for this:
template <typename T, typename... Args>
struct foo
{
std::tuple<Args...> args;
T gen() { return std::make_from_tuple<T>(args); }
};
You need some template meta-programming machinery to achieve that.
The easiest way to realize the argument dispatch is to exploit pack expansion on expressions which contain a packed compile-time sequence of integers. The template machinery is needed to build such a sequence (also see the remark at the end of this answer for more information on a proposal to standardize such a sequence).
Supposing to have a class (template) index_range that encapsulates a compile-time range of integers [M, N) and a class (template) index_list that encapsulates a compile-time list of integers, this is how you would use them:
template<typename T, typename... Args>
struct foo
{
tuple<Args...> args;
// Allows deducing an index list argument pack
template<size_t... Is>
T gen(index_list<Is...> const&)
{
return T(get<Is>(args)...); // This is the core of the mechanism
}
T gen()
{
return gen(
index_range<0, sizeof...(Args)>() // Builds an index list
);
}
};
And here is a possible implementation of index_range and index_list:
//===============================================================================
// META-FUNCTIONS FOR CREATING INDEX LISTS
// The structure that encapsulates index lists
template <size_t... Is>
struct index_list
{
};
// Collects internal details for generating index ranges [MIN, MAX)
namespace detail
{
// Declare primary template for index range builder
template <size_t MIN, size_t N, size_t... Is>
struct range_builder;
// Base step
template <size_t MIN, size_t... Is>
struct range_builder<MIN, MIN, Is...>
{
typedef index_list<Is...> type;
};
// Induction step
template <size_t MIN, size_t N, size_t... Is>
struct range_builder : public range_builder<MIN, N - 1, N - 1, Is...>
{
};
}
// Meta-function that returns a [MIN, MAX) index range
template<unsigned MIN, unsigned MAX>
using index_range = typename detail::range_builder<MIN, MAX>::type;
Also notice, that an interesting proposal by Jonathan Wakely exists to standardize an int_seq class template, which is something very similar to what I called index_list here.
Use index_sequence to unpack a std::tuple (or std::pair, std::array, or anything else supporting the tuple interface):
#include <utility>
#include <tuple>
template <typename Tuple, std::size_t... Inds>
SomeClass help_make_SomeClass(Tuple&& tuple, std::index_sequence<Inds...>)
{
return SomeClass(std::get<Inds>(std::forward<Tuple>(tuple))...);
}
template <typename Tuple>
SomeClass make_SomeClass(Tuple&& tuple)
{
return help_make_SomeClass(std::forward<Tuple>(tuple),
std::make_index_sequence<std::tuple_size<Tuple>::value>());
}
std::index_sequence and std::make_index_sequence will be in C++1y. If you can't find a header that defines them, you could use these:
template <std::size_t... Inds>
struct index_sequence {
static constexpr std::size_t size()
{ return sizeof...(Inds); }
};
template <std::size_t N, std::size_t... Inds>
struct help_index_seq {
typedef typename help_index_seq<N-1, N-1, Inds...>::type type;
};
template <std::size_t... Inds>
struct help_index_seq<0, Inds...> {
typedef index_sequence<Inds...> type;
};
template <std::size_t N>
using make_index_sequence = typename help_index_seq<N>::type;
Live example, in C++11 mode: http://coliru.stacked-crooked.com/a/ed91a67c8363061b
C++14 will add standard support for index_sequence:
template<typename T, typename... Args>
struct foo {
tuple<Args...> args;
T gen() { return gen_impl(std::index_sequence_for<Args...>()); }
private:
template <size_t... Indices>
T gen_impl(std::index_sequence<Indices...>) { return T(std::get<Indices>(args)...); }
};
You'll need to use the indices trick, which means a layer of indirection:
template <std::size_t... Is>
struct indices {};
template <std::size_t N, std::size_t... Is>
struct build_indices
: build_indices<N-1, N-1, Is...> {};
template <std::size_t... Is>
struct build_indices<0, Is...> : indices<Is...> {};
template<typename T, typename... Args>
struct foo {
tuple<Args...> args;
T gen() { return gen(build_indices<sizeof...(Args)>{}); }
private:
template<std::size_t... Is>
T gen(indices<Is...>) { return T(get<Is>(args)...); }
};
Create a sequence of indexes from 0 through n-1:
template<size_t... indexes>
struct seq {};
template<size_t n, size_t... indexes>
struct make_seq: make_seq<n-1, n-1, indexes...> {};
template<size_t... indexes>
struct make_seq: make_seq<0, indexes...> {
typedef seq<indexes...> type;
};
unpack them in parallel with your args, or as the index to get<> in your case.
The goal is something like:
template< typename T, typename Tuple, typename Indexes >
struct repack;
template< typename... Ts, size_t... indexes >
struct repack< tuple<Ts...>, seq<indexes...> > {
T operator()( tuple<Ts...> const& args ) const {
return T( get<indexes>(args)... );
}
};
use repack in your gen like this:
T gen() {
repack<T, tuple<Args...>, typename make_seq<sizeof...(Args)>::type> repacker;
return repacker( args );
}
Suppose I have a template which is parametrized by a class type and a number of argument types. a set of arguments matching these types are stored in a tuple. How can one pass these to a constructor of the class type?
In almost C++11 code:
template<typename T, typename... Args>
struct foo {
tuple<Args...> args;
T gen() { return T(get<0>(args), get<1>(args), ...); }
};
How can the ... in the constructor call be filled without fixing the length?
I guess I could come up with some complicated mechanism of recursive template calls which does this, but I can't believe that I'm the first to want this, so I guess there will be ready-to-use solutions to this out there, perhaps even in the standard libraries.
C++17 has std::make_from_tuple for this:
template <typename T, typename... Args>
struct foo
{
std::tuple<Args...> args;
T gen() { return std::make_from_tuple<T>(args); }
};
You need some template meta-programming machinery to achieve that.
The easiest way to realize the argument dispatch is to exploit pack expansion on expressions which contain a packed compile-time sequence of integers. The template machinery is needed to build such a sequence (also see the remark at the end of this answer for more information on a proposal to standardize such a sequence).
Supposing to have a class (template) index_range that encapsulates a compile-time range of integers [M, N) and a class (template) index_list that encapsulates a compile-time list of integers, this is how you would use them:
template<typename T, typename... Args>
struct foo
{
tuple<Args...> args;
// Allows deducing an index list argument pack
template<size_t... Is>
T gen(index_list<Is...> const&)
{
return T(get<Is>(args)...); // This is the core of the mechanism
}
T gen()
{
return gen(
index_range<0, sizeof...(Args)>() // Builds an index list
);
}
};
And here is a possible implementation of index_range and index_list:
//===============================================================================
// META-FUNCTIONS FOR CREATING INDEX LISTS
// The structure that encapsulates index lists
template <size_t... Is>
struct index_list
{
};
// Collects internal details for generating index ranges [MIN, MAX)
namespace detail
{
// Declare primary template for index range builder
template <size_t MIN, size_t N, size_t... Is>
struct range_builder;
// Base step
template <size_t MIN, size_t... Is>
struct range_builder<MIN, MIN, Is...>
{
typedef index_list<Is...> type;
};
// Induction step
template <size_t MIN, size_t N, size_t... Is>
struct range_builder : public range_builder<MIN, N - 1, N - 1, Is...>
{
};
}
// Meta-function that returns a [MIN, MAX) index range
template<unsigned MIN, unsigned MAX>
using index_range = typename detail::range_builder<MIN, MAX>::type;
Also notice, that an interesting proposal by Jonathan Wakely exists to standardize an int_seq class template, which is something very similar to what I called index_list here.
Use index_sequence to unpack a std::tuple (or std::pair, std::array, or anything else supporting the tuple interface):
#include <utility>
#include <tuple>
template <typename Tuple, std::size_t... Inds>
SomeClass help_make_SomeClass(Tuple&& tuple, std::index_sequence<Inds...>)
{
return SomeClass(std::get<Inds>(std::forward<Tuple>(tuple))...);
}
template <typename Tuple>
SomeClass make_SomeClass(Tuple&& tuple)
{
return help_make_SomeClass(std::forward<Tuple>(tuple),
std::make_index_sequence<std::tuple_size<Tuple>::value>());
}
std::index_sequence and std::make_index_sequence will be in C++1y. If you can't find a header that defines them, you could use these:
template <std::size_t... Inds>
struct index_sequence {
static constexpr std::size_t size()
{ return sizeof...(Inds); }
};
template <std::size_t N, std::size_t... Inds>
struct help_index_seq {
typedef typename help_index_seq<N-1, N-1, Inds...>::type type;
};
template <std::size_t... Inds>
struct help_index_seq<0, Inds...> {
typedef index_sequence<Inds...> type;
};
template <std::size_t N>
using make_index_sequence = typename help_index_seq<N>::type;
Live example, in C++11 mode: http://coliru.stacked-crooked.com/a/ed91a67c8363061b
C++14 will add standard support for index_sequence:
template<typename T, typename... Args>
struct foo {
tuple<Args...> args;
T gen() { return gen_impl(std::index_sequence_for<Args...>()); }
private:
template <size_t... Indices>
T gen_impl(std::index_sequence<Indices...>) { return T(std::get<Indices>(args)...); }
};
You'll need to use the indices trick, which means a layer of indirection:
template <std::size_t... Is>
struct indices {};
template <std::size_t N, std::size_t... Is>
struct build_indices
: build_indices<N-1, N-1, Is...> {};
template <std::size_t... Is>
struct build_indices<0, Is...> : indices<Is...> {};
template<typename T, typename... Args>
struct foo {
tuple<Args...> args;
T gen() { return gen(build_indices<sizeof...(Args)>{}); }
private:
template<std::size_t... Is>
T gen(indices<Is...>) { return T(get<Is>(args)...); }
};
Create a sequence of indexes from 0 through n-1:
template<size_t... indexes>
struct seq {};
template<size_t n, size_t... indexes>
struct make_seq: make_seq<n-1, n-1, indexes...> {};
template<size_t... indexes>
struct make_seq: make_seq<0, indexes...> {
typedef seq<indexes...> type;
};
unpack them in parallel with your args, or as the index to get<> in your case.
The goal is something like:
template< typename T, typename Tuple, typename Indexes >
struct repack;
template< typename... Ts, size_t... indexes >
struct repack< tuple<Ts...>, seq<indexes...> > {
T operator()( tuple<Ts...> const& args ) const {
return T( get<indexes>(args)... );
}
};
use repack in your gen like this:
T gen() {
repack<T, tuple<Args...>, typename make_seq<sizeof...(Args)>::type> repacker;
return repacker( args );
}