disponibilidad comandos clusvcadm cluster alta c++ c++11 variadic-templates

c++ - comandos - clusvcadm



argumentos de la plantilla variad dividida (5)

Aquí hay otra solución más:

#include <array> #include <tuple> #include <iostream> template <int i, int o> struct cpyarr_ { template < typename T, typename L > static void f (T const& t, L &l) { l[i-1] = std::get<i-1+o> (t); cpyarr_<i-1,o>::f (t,l); } }; template <int o> struct cpyarr_ <0,o> { template < typename T, typename L > static void f (T const&, L&) {} }; template <int i, int o, typename U, typename ... T> std::array < U, i > cpyarr (U u, T... t) { std::tuple < U, T... > l { u, t... }; std::array < U, i > a; cpyarr_<i,o>::f (l, a); // because std::copy uses call to memmov which is not optimized away (at least with g++ 4.6) return a; } template <int d> struct a { std::array <int, d> p, q; template <typename ... T> a (T ... t) : p (cpyarr<d,0> (t...)), q (cpyarr<d,d> (t...)) {} }; int main () { a <5> x { 0,1,2,3,4,5,6,7,8,9 }; for (int i = 0; i < 5; i++) std::cout << x.p[i] << " " << x.q[i] << "/n"; }

¿Cómo divido los argumentos de la plantilla variad en dos mitades? Algo como:

template <int d> struct a { std::array <int, d> p, q; template <typename ... T> a (T ... t) : p ({half of t...}), q ({other half of t...}) {} };


La solución de Luc es limpia y directa, pero carece de diversión.
Debido a que solo hay una forma adecuada de usar plantillas variadas y es abusar de ellas para hacer cosas de metaprogramación demasiado complicadas y complicadas :)

Me gusta esto :

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 un código de ayuda:

Primero necesitamos la estructura make_pack_indices, que se utiliza para generar un rango de enteros 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 :: get for tuple, como std::get<N>(ts...) devolver el elemento Nth 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 compilar get () también necesitamos una estructura de ayuda pack_element, otra vez muy similar a std :: tuple_element, como pack_element<N, Ts...>::type es el tipo Nth del paquete de 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 no entiendo por qué pack_element y get () no están ya 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 la implementación std :: tuple_element y __make_tuple_indices que se encuentra en libc ++.


Sé que esta pregunta es bastante antigua, pero la encontré ayer mientras buscaba una solución a un problema muy similar. Yo mismo encontré una solución y terminé escribiendo una pequeña biblioteca que creo que hace lo que quieres. Puede encontrar una descripción here si todavía está interesado.


Tenga en cuenta que en este caso particular, puede usar std::initializer_list :

template<int... Is> struct index_sequence{}; template<int N, int... Is> struct make_index_sequence { typedef typename make_index_sequence<N - 1, N - 1, Is...>::type type; }; template<int... Is> struct make_index_sequence<0, Is...> { typedef index_sequence<Is...> type; }; template <int d> struct a { std::array <int, d> p, q; constexpr a (const std::initializer_list<int>& t) : a(t, typename make_index_sequence<d>::type()) {} private: template <int... Is> constexpr a(const std::initializer_list<int>& t, index_sequence<Is...>) : p ({{(*(t.begin() + Is))...}}), q ({{(*(t.begin() + d + Is))...}}) {} };


Todavía nos faltan muchos ayudantes para manipular los paquetes de parámetros variadic (o no los conozco). Hasta que una buena biblioteca de Boost nos los traiga, aún podemos escribir la nuestra.

Por ejemplo, si está dispuesto a posponer la inicialización de sus arreglos al cuerpo del constructor, puede crear y usar una función que copie parte del paquete de parámetros a un iterador de salida:

#include <array> #include <cassert> #include <iostream> // Copy n values from the parameter pack to an output iterator template < typename OutputIterator > void copy_n( size_t n, OutputIterator ) { assert ( n == 0 ); } template < typename OutputIterator, typename T, typename... Args > void copy_n( size_t n, OutputIterator out, const T & value, Args... args ) { if ( n > 0 ) { *out = value; copy_n( n - 1, ++out, args... ); } } // Copy n values from the parameter pack to an output iterator, starting at // the "beginth" element template < typename OutputIterator > void copy_range( size_t begin, size_t size, OutputIterator out ) { assert( size == 0 ); } template < typename OutputIterator, typename T, typename... Args > void copy_range( size_t begin, size_t size, OutputIterator out, T value, Args... args ) { if ( begin == 0 ) { copy_n( size, out, value, args... ); } else { copy_range( begin - 1, size, out, args... ); } } template < int N > struct DoubleArray { std::array< int, N > p; std::array< int, N > q; template < typename... Args > DoubleArray ( Args... args ) { copy_range( 0, N, p.begin(), args... ); copy_range( N, N, q.begin(), args... ); } }; int main() { DoubleArray<3> mya(1, 2, 3, 4, 5, 6); std::cout << mya.p[0] << mya.p[2] << std::endl; std::cout << mya.q[0] << mya.q[2] << std::endl; } // Ouput: // 13 // 46

Como puede ver, puede (no tan) crear fácilmente sus propios algoritmos para manipular paquetes de parámetros; todo lo que se necesita es una buena comprensión de la recursión y la coincidencia de patrones (como siempre cuando se realiza la MetaProgramación de plantillas ...)