问题描述
我有一个C框架提供经典的延迟回调执行API:
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);
这里 arg
是用户指定的任意值它将被传递给回调,其他回调参数由框架传递。但实际上只有最后一个参数用于处理程序,它必须从 void *
中显式转换。
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);
有另一个解决方案来初始化问题 - 创建自定义函数对象,并将其作为用户参数传递给native API。然后从 void *
解压缩,执行真正的回调和删除函数对象。但是,当没有执行回调时,动作取消有问题。
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.
推荐答案
每一个都需要更多的工作才能正确实现,我宁愿忽略它。一次在预处理器实际上可以派上用场:
Every once in a while the Preprocessor actually can come in handy:
#define myRun(fun, arg) (::run<::std::remove_pointer_t<decltype(arg)>, fun>(arg))
这将不会多次评估 arg
或 fun
。 结果也是一个括号表达式(而不是更像一个声明的东西),因此表现得像一个普通的函数调用。
Note that this will not evaluate arg
or fun
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.
这篇关于在函数参数化的模板中推导参数类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!