Posible duplicado:
¿Cómo puedo expandir una tupla en los argumentos de la función de plantilla variadic?
“Desempaquetar” una tupla para llamar a un puntero de función coincidente
En las plantillas de C ++ 11, ¿hay alguna manera de usar una tupla como argumento individual de una función (posiblemente una plantilla)?
Ejemplo:
Digamos que tengo esta función:
void foo(int a, int b) { }
Y tengo la tuple auto bar = std::make_tuple(1, 2)
.
¿Puedo usar eso para llamar a foo(1, 2)
de forma temporal?
No me refiero simplemente a foo(std::get(bar), std::get(bar))
ya que quiero hacer esto en una plantilla que no conoce el número de argumentos.
Un ejemplo más completo:
template void caller(Func func, Args... args) { auto argtuple = std::make_tuple(args...); do_stuff_with_tuple(argtuple); func(insert_magic_here(argtuple)); // <-- this is the hard part }
Debo señalar que preferiría no crear una plantilla que funcione para una arg, otra que funcione para dos, etc.
Pruebe algo como esto:
// implementation details, users never invoke these directly namespace detail { template struct call_impl { static void call(F f, Tuple && t) { call_impl::call(f, std::forward(t)); } }; template struct call_impl { static void call(F f, Tuple && t) { f(std::get(std::forward(t))...); } }; } // user invokes this template void call(F f, Tuple && t) { typedef typename std::decay::type ttype; detail::call_impl::value, std::tuple_size::value>::call(f, std::forward(t)); }
Ejemplo:
#include int main() { auto t = std::make_tuple("%d, %d, %d\n", 1,2,3); call(std::printf, t); }
Con algo de magia extra y usando std::result_of
, probablemente también puedas hacer que la cosa entera devuelva el valor de retorno correcto.
Cree una “tupla de índice” (una tupla de enteros en tiempo de comstackción) y luego reenvíela a otra función que deduzca los índices como un paquete de parámetros y los use en una expansión de paquete para llamar a std::get
en la tupla:
#include template void caller_impl(Func func, Tuple&& t, redi::index_tuple) { func(std::get(t)...); } template void caller(Func func, Args... args) { auto argtuple = std::make_tuple(args...); do_stuff_with_tuple(argtuple); typedef redi::to_index_tuple indices; caller_impl(func, argtuple, indices()); }
Mi implementación de index_tuple
está en https://gitlab.com/redistd/redistd/blob/master/include/redi/index_tuple.h pero depende de los alias de las plantillas, así que si tu comstackdor no admite eso necesitarás modificar usar “template typedefs” tipo C ++ 03 y reemplazar las últimas dos líneas de la caller
con
typedef typename redi::make_index_tuple::type indices; caller_impl(func, argtuple, indices());
Una utilidad similar se estandarizó como std::index_sequence
en C ++ 14 (vea index_seq.h para una implementación independiente de C ++ 11).