La respuesta de dribeas es correcta en lo que se refiere al C++ moderno.
Por el bien de interés, también hay una solución lo-tech simple del mundo C que, hasta donde llega, funciona en C++. En lugar de permitir parámetros arbitrarios, defina la función como void (*func)(void*)
, y haga "params" void*
. Es entonces el trabajo del que llama para definir una estructura que contendrá los parámetros y gestionar su ciclo de vida. Por lo general, la persona que llama también escribiría una envoltura simple de la función que realmente se necesita para ser llamado:
void myfunc(int, float); // defined elsewhere
typedef struct {
int foo;
float bar;
} myfunc_params;
void myfunc_wrapper(void *p) {
myfunc_params *params = (myfunc_params *)p;
myfunc(params->foo, params->bar);
}
int main() {
myfunc_params x = {1, 2};
AddTimer(23, 5, myfunc_wrapper, &x);
sleep(23*5 + 1);
}
En la práctica se quiere "dispara y olvida" temporizadores, así que si usa este esquema también se puede necesitar una forma para que el temporizador logre liberar el puntero userdata una vez que todas las activaciones se hayan completado.
Obviamente, esto tiene seguridad de tipo limitado. En principio, no debería importar, ya que quien suministra el puntero a la función y el puntero de datos del usuario no debería tener grandes dificultades para asegurarse de que coincidan. En la práctica, por supuesto, la gente encuentra formas de escribir errores y formas de culparte porque su compilador no les contó sobre los errores ;-)
llamará y solo tomará las funciones nulas? – Ninja
@Ninja Sí, por supuesto. Como persona que llama, si ni siquiera sabe cuál es el tipo de devolución, ¿cómo puede usar la función? Puede usar 'boost :: function' y convertir el tipo de retorno a lo que desee. Si desea la alternativa moderna de C++, puede usar 'boost :: function ' para jugar con algún tipo de borrado. –
kizzx2