Estou tentando armazenar em um std::tuple
número variável de valores, que mais tarde serão usados como argumentos para uma chamada para um ponteiro de função que corresponda aos tipos armazenados.
Eu criei um exemplo simplificado mostrando o problema que estou tentando 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 envolvendo std::tuple
ou modelos variados, eu escreveria outro modelo template <typename Head, typename ...Tail>
para avaliar recursivamente todos os tipos, um por um, mas não vejo uma maneira de fazer isso para despachar uma chamada de função.
A verdadeira motivação para isso é um pouco mais complexa e, na maioria das vezes, é apenas um exercício de aprendizado. Você pode supor que recebi a tupla por contrato de outra interface, portanto não pode ser alterada, mas o desejo de descompactá-la em uma chamada de função é meu. Isso exclui o uso de std::bind
uma maneira barata de contornar o problema subjacente.
Qual é uma maneira limpa de despachar a chamada usando o std::tuple
, ou uma maneira melhor alternativa de alcançar o mesmo resultado líquido de armazenar / encaminhar alguns valores e um ponteiro de função até um ponto futuro arbitrário?
auto saved = std::bind(f, a, b, c);
... e depois apenas ligarsaved()
?