【发布时间】:2020-01-04 20:34:39
【问题描述】:
我正在为我的 EventLoop 类编写一个异步成员函数,它将繁重的计算任务发布到全局线程池,然后获取该任务的结果并将一个完成回调函数排队,该函数将获取前一个结果作为返回 EventLoop 的参数,让 eventloop 稍后处理(调用)完成回调。
所以一般来说async成员函数应该带两个函数作为参数,第一个被设计成任意返回类型的任务函数,第二个是一个finish回调,它把第一个函数的返回值作为一个范围。
我的第一次尝试代码如下:
class EventLoop
{
public:
using DeferCallback=std::function<void()>;
//call by another thread to queue work into the eventloop
void queue_work(DeferCallback cb);
template<typename F,typename ...Args>
void async(F &&task_func,Args&& ...args,std::function<void(std::invoke_result_t<F,Args...>&)> &&finish_cb){
g_threadpool::get_instance()->post([this,task_func,args...,finish_cb](){
using task_ret_t=std::invoke_result_t<F,Args...>;
task_ret_t res=task_func(args...);
this->queue_work([finish_cb,&res](){
finish_cb(res);
});
});
}
//for task func of void return type
template<typename F,typename ...Args>
void async(F &&task_func,Args&& ...args,std::function<void(void)> &&finish_cb){
g_threadpool::get_instance()->post([this,task_func,args...,finish_cb](){
task_func(args...);
this->queue_work([finish_cb](){
finish_cb();
});
});
}
我测试并发现它只有在我不向...args传递任何东西时才有效,或者编译器无法正常工作。然后我做了一些搜索并找到以下问题:Parameter pack must be at the end of the parameter list... When and why? 它基本上告诉我:
[...]如果主类模板或别名>template的模板参数是模板参数包,它应该是最后一个模板->参数。[...]
如果我必须显式实例化异步函数,它将很难使用。
然后我试试这个:
template<typename Ret,typename ...Args>
void async(std::function<Ret(Args...)> &&task_func,std::function<void(Ret&)> &&finish_cb){ ... }
并发现我无法将 lambda 函数或成员函数(除了 std::function 之外)传递给第一个参数,这并不理想。相关问题:Deduce template argument from std::function call signature
那么有什么办法可以解决吗?
【问题讨论】:
标签: c++ c++11 templates variadic-templates