2010-04-25 14 views
5

Yo estaba jugando con plantillas variadic (gcc 4.5) y pulsa este problema: mensaje de error¿Boost.Tuple es compatible con las plantillas variadic de C++ 0x?

template <typename... Args> 
boost::tuple<Args...> 
my_make_tuple(Args... args) 
{ 
    return boost::tuple<Args...>(args...); 
} 

int main (void) 
{ 
    boost::tuple<int, char> t = my_make_tuple(8, 'c'); 
} 

GCC:

sorry, unimplemented: cannot expand 'Arg ...' into a fixed-length argument list 
In function 'int my_make_tuple(Arg ...)' 

Si puedo reemplazar todas las apariciones de boost::tuple por std::tuple, que compila bien.
¿Hay algún problema en la implementación de boost tuple? ¿O es esto un error de gcc?

Debo quedarme con Boost.Tuple por el momento. ¿Conoces alguna solución?
Gracias.

+0

http://stackoverflow.com/questions/1989552/gcc-error-with-variadic-templates-sorry-unimplemented-cannot-expand-identif? – kennytm

Respuesta

7

No parece gustarle expandir Args... a T1, T2, T3, ..., T9 ya que Boost lo tiene.

Como solución, usar construcciones que no requieren de esta expansión:

#include <boost/tuple/tuple.hpp> 

template <typename... Args> 
auto my_make_tuple(Args... args) -> decltype(boost::make_tuple(args...)) 
{ 
    return {args...}; 
} 

int main (void) 
{ 
    boost::tuple<int, char> t = my_make_tuple(8, 'c'); 
} 

Otra opción podría ser la de hacer la expansión de forma manual, al ver que boost::tuple soporta hasta 10 argumentos.

#include <boost/tuple/tuple.hpp> 

template <unsigned, class, class...> struct nth_argument; 

template <unsigned N, class Default, class T, class... Args> 
struct nth_argument<N, Default, T, Args...> 
{ 
    typedef typename nth_argument<N - 1, Default, Args...>::type type; 
}; 

template <class Default, class T, class... Args> 
struct nth_argument<0, Default, T, Args...> 
{ 
    typedef T type; 
}; 

template <unsigned N, class Default> 
struct nth_argument<N, Default> 
{ 
    typedef Default type; 
}; 

template <typename ...Args> 
struct tuple_from_var_template 
{ 
    typedef boost::tuple< 
     typename nth_argument<0, boost::tuples::null_type, Args...>::type, 
     typename nth_argument<1, boost::tuples::null_type, Args...>::type, 
     typename nth_argument<2, boost::tuples::null_type, Args...>::type, 
     typename nth_argument<3, boost::tuples::null_type, Args...>::type, 
     typename nth_argument<4, boost::tuples::null_type, Args...>::type, 
     typename nth_argument<5, boost::tuples::null_type, Args...>::type, 
     typename nth_argument<6, boost::tuples::null_type, Args...>::type, 
     typename nth_argument<7, boost::tuples::null_type, Args...>::type, 
     typename nth_argument<8, boost::tuples::null_type, Args...>::type, 
     typename nth_argument<9, boost::tuples::null_type, Args...>::type 
    > type; 
}; 

template <typename... Args> 
typename tuple_from_var_template<Args...>::type my_make_tuple(Args... args) 
{ 
    return typename tuple_from_var_template<Args...>::type(args...); 
} 

int main (void) 
{ 
    boost::tuple<int, char> t = my_make_tuple(8, 'c'); 
} 
Cuestiones relacionadas