La solución de Luc es limpia y directa, pero le falta mucha diversión.
Debido a que sólo hay una forma correcta de utilizar plantillas variadic y es abusar de ellos para hacer cosas locas metaprogramming excesivamente complicada :)
De esta manera:
template <class T, size_t... Indx, class... Ts>
std::array<T, sizeof...(Indx)>
split_array_range_imp(pack_indices<Indx...> pi, Ts... ts)
{
return std::array<T, sizeof...(Indx)>{get<Indx>(ts...)...}; //TADA
}
template <class T, size_t begin, size_t end, class... Ts>
std::array<T, end - begin>
split_array_range(Ts... ts)
{
typename make_pack_indices<end, begin>::type indices;
return split_array_range_imp<T>(indices, ts...);
}
template <size_t N>
struct DoubleArray
{
std::array <int, N> p, q;
template <typename ... Ts>
DoubleArray (Ts ... ts) :
p(split_array_range<int, 0 , sizeof...(Ts)/2 >(ts...)),
q(split_array_range<int, sizeof...(Ts)/2, sizeof...(Ts) >(ts...))
{
}
};
int main()
{
DoubleArray<3> mya{1, 2, 3, 4, 5, 6};
std::cout << mya.p[0] << "\n" << mya.p[1] << "\n" << mya.p[2] << std::endl;
std::cout << mya.q[0] << "\n" << mya.q[1] << "\n" << mya.q[2] << std::endl;
}
Es bastante corto, excepto que necesitamos para codificar alguna ayuda:
Primero necesitamos la estructura make_pack_indices, que se usa para generar un rango de entero en tiempo de compilación. Por ejemplo make_pack_indices<5, 0>::type
es en realidad el tipo pack_indices<0, 1, 2, 3, 4>
template <size_t...>
struct pack_indices {};
template <size_t Sp, class IntPack, size_t Ep>
struct make_indices_imp;
template <size_t Sp, size_t ... Indices, size_t Ep>
struct make_indices_imp<Sp, pack_indices<Indices...>, Ep>
{
typedef typename make_indices_imp<Sp+1, pack_indices<Indices..., Sp>, Ep>::type type;
};
template <size_t Ep, size_t ... Indices>
struct make_indices_imp<Ep, pack_indices<Indices...>, Ep>
{
typedef pack_indices<Indices...> type;
};
template <size_t Ep, size_t Sp = 0>
struct make_pack_indices
{
static_assert(Sp <= Ep, "__make_tuple_indices input error");
typedef typename make_indices_imp<Sp, pack_indices<>, Ep>::type type;
};
También necesitamos una función get(), muy similar a std :: conseguir para tupla, como std::get<N>(ts...)
retorno del elemento enésimo de un paquete de parámetros.
template <class R, size_t Ip, size_t Ij, class... Tp>
struct Get_impl
{
static R& dispatch(Tp...);
};
template<class R, size_t Ip, size_t Jp, class Head, class... Tp>
struct Get_impl<R, Ip, Jp, Head, Tp...>
{
static R& dispatch(Head& h, Tp&... tps)
{
return Get_impl<R, Ip, Jp + 1, Tp...>::dispatch(tps...);
}
};
template<size_t Ip, class Head, class... Tp>
struct Get_impl<Head, Ip, Ip, Head, Tp...>
{
static Head& dispatch(Head& h, Tp&... tps)
{
return h;
}
};
template <size_t Ip, class ... Tp>
typename pack_element<Ip, Tp...>::type&
get(Tp&... tps)
{
return Get_impl<typename pack_element<Ip, Tp...>::type, Ip, 0, Tp...>::dispatch(tps...);
}
Pero para construir get() también necesitamos una estructura pack_element ayudante, de nuevo, muy similar a std :: tuple_element, como pack_element<N, Ts...>::type
es del tipo N de la manada parámetros.
template <size_t _Ip, class _Tp>
class pack_element_imp;
template <class ..._Tp>
struct pack_types {};
template <size_t Ip>
class pack_element_imp<Ip, pack_types<> >
{
public:
static_assert(Ip == 0, "tuple_element index out of range");
static_assert(Ip != 0, "tuple_element index out of range");
};
template <class Hp, class ...Tp>
class pack_element_imp<0, pack_types<Hp, Tp...> >
{
public:
typedef Hp type;
};
template <size_t Ip, class Hp, class ...Tp>
class pack_element_imp<Ip, pack_types<Hp, Tp...> >
{
public:
typedef typename pack_element_imp<Ip-1, pack_types<Tp...> >::type type;
};
template <size_t Ip, class ...Tp>
class pack_element
{
public:
typedef typename pack_element_imp<Ip, pack_types<Tp...> >::type type;
};
Y aquí vamos.
En realidad, realmente no entiendo por qué pack_element y get() ya no están en la biblioteca estándar. Esos ayudantes están presentes para std :: tuple, ¿por qué no para el paquete de parámetros?
Nota: Mi implementación de pack_element y make_pack_indices es una transposición directa de std :: tuple_element y __make_tuple_indices implementación encontrada en libC++.
pregunta interesante. Pensé que, dado que probablemente puedas dividir los args en tuplas, se podría comenzar con esto: http://ideone.com/YyeNC. Lamentablemente, los paquetes de parámetros múltiples para el constructor son ilegales, a pesar de que en esta situación debe quedar claro cuáles son los tipos en cada paquete. – visitor