I have C framework that provides classic deferred callback execution API:
typedef void (*callback_t)(int value_1, int value_2, void* arg);
void schedule(callback_t callback, void* arg);
Here arg
is arbitrary value specified by user that will be passed to the callback and other callback parameters are passed by framework. But really only last argument is used in handlers and it has to be explicitly cast from void*
.
Thinking of how callback signature may be changed to match the real one I got to this solution:
template <typename TArg, void (*Callback)(TArg*)>
void run(TArg* arg)
{
schedule([](int, int, void* arg)
{
Callback((TArg*)arg);
}, arg);
}
...
void handler(int* arg) // instead of handler(int, int, void* arg)
{
}
...
run<int, handler>(arg); // instead of schedule(handler, arg)
The only problem here is that callback argument type has to be explicitly specified at run
invocation.
Is there a way to make the compiler to deduce this type? Ideally the execution code should be just:
run<handler>(arg);
There is another solution to initial problem - to create custom function object and pass it as user argument to native API. Then unpack it from void*
, execute real callback and delete function object. But there are issues with action cancelling when callback is not executed. It will require much more work to be implemented correctly and I prefer to ignore it if there is a more simple way.
Different approach using std::bind (couldn't test though):
Every once in a while the Preprocessor actually can come in handy:
Note that this will not evaluate
arg
orfun
multiple times. The result is also a parenthesized expression (and not something more icky like a declaration) and thus behaves just like an ordinary function call.