Estoy tratando de almacenar un std::tuple
número variable de valores, que luego se utilizarán como argumentos para una llamada a un puntero de función que coincida con los tipos almacenados.
He creado un ejemplo simplificado que muestra el problema que estoy luchando por resolver:
#include <iostream>
#include <tuple>
void f(int a, double b, void* c) {
std::cout << a << ":" << b << ":" << c << std::endl;
}
template <typename ...Args>
struct save_it_for_later {
std::tuple<Args...> params;
void (*func)(Args...);
void delayed_dispatch() {
// How can I "unpack" params to call func?
func(std::get<0>(params), std::get<1>(params), std::get<2>(params));
// But I *really* don't want to write 20 versions of dispatch so I'd rather
// write something like:
func(params...); // Not legal
}
};
int main() {
int a=666;
double b = -1.234;
void *c = NULL;
save_it_for_later<int,double,void*> saved = {
std::tuple<int,double,void*>(a,b,c), f};
saved.delayed_dispatch();
}
Normalmente, para problemas relacionados std::tuple
con plantillas variadas, escribiría otra plantilla como template <typename Head, typename ...Tail>
para evaluar recursivamente todos los tipos uno por uno, pero no puedo ver una manera de hacerlo para enviar una llamada a la función.
La verdadera motivación para esto es algo más compleja y, en general, es solo un ejercicio de aprendizaje. Puede suponer que me entregó la tupla por contrato desde otra interfaz, por lo que no se puede cambiar, pero que el deseo de descomprimirlo en una llamada de función es mío. Esto descarta usarlo std::bind
como una forma barata de esquivar el problema subyacente.
¿Cuál es una manera limpia de despachar la llamada usando el std::tuple
, o una mejor forma alternativa de lograr el mismo resultado neto de almacenar / reenviar algunos valores y un puntero de función hasta un punto futuro arbitrario?
auto saved = std::bind(f, a, b, c);
... luego llamarsaved()
?