C++ 正确使用模板将函数传递给线程池
我试图创建一个线程池,它接受任何类型的函数,并为该函数可能具有的任何返回值/异常返回未来。我这样做主要是为了学习现代线程和一些模板编程。我尝试将我的语法松散地建立在MSVC如何实现std::function和futures的基础上 下面是我的问题所在的最起码的一个片段:C++ 正确使用模板将函数传递给线程池,c++,templates,c++17,decltype,C++,Templates,C++17,Decltype,我试图创建一个线程池,它接受任何类型的函数,并为该函数可能具有的任何返回值/异常返回未来。我这样做主要是为了学习现代线程和一些模板编程。我尝试将我的语法松散地建立在MSVC如何实现std::function和futures的基础上 下面是我的问题所在的最起码的一个片段: #include <functional> #include <future> #include <utility> #include <queue> #include <m
#include <functional>
#include <future>
#include <utility>
#include <queue>
#include <memory>
using Job = std::function<void()>;
std::queue<std::unique_ptr<Job>> queue;
template<typename FuncType, typename... Args>
auto add(FuncType&& func, Args&&... args) ->std::future<decltype(func)(decltype(args)...)> {
auto task = std::packaged_task<decltype(func)(decltype(args)...)>(std::bind (std::forward<FuncType>(func), std::forward<Args>(args)...));
auto future = task.get_future();
queue.push(std::make_unique<Job>([task]() { task(); }));
return future;
}
void voidFunc(){};
int main()
{
add(voidFunc);
}
#包括
#包括
#包括
#包括
#包括
使用Job=std::function;
std::队列;
模板
自动添加(FuncType&&func,Args&&…Args)->std::future{
自动任务=std::打包任务(std::bind(std::forward(func)、std::forward(args)…);
自动未来=任务。获取未来();
push(std::make_unique([task](){task();}));
回归未来;
}
void voidFunc(){};
int main()
{
添加(voidFunc);
}
编译失败,出现以下错误:
/usr/include/c++/4.9/future: In instantiation of 'class std::future<void (&())()>':
28:17: required from here
/usr/include/c++/4.9/future:697:7: error: function returning a function
get()
^
In instantiation of 'add(FuncType&&, Args&& ...)::<lambda()> [with FuncType = void (&)(); Args = {}]':
19:37: required from 'struct add(FuncType&&, Args&& ...) [with FuncType = void (&)(); Args = {}; decltype (func) = void (&)()]::<lambda()>'
19:56: required from 'std::future<decltype (func)(decltype (args)...)> add(FuncType&&, Args&& ...) [with FuncType = void (&)(); Args = {}; decltype (func) = void (&)()]'
28:17: required from here
19:52: error: passing 'const std::packaged_task<void (&())()>' as 'this' argument of 'void std::packaged_task<_Res(_ArgTypes ...)>::operator()(_ArgTypes ...) [with _Res = void (&)(); _ArgTypes = {}]' discards qualifiers [-fpermissive]
In instantiation of 'std::future<decltype (func)(decltype (args)...)> add(FuncType&&, Args&& ...) [with FuncType = void (&)(); Args = {}; decltype (func) = void (&)()]':
28:17: required from here
19:36: error: use of deleted function 'std::packaged_task<_Res(_ArgTypes ...)>::packaged_task(const std::packaged_task<_Res(_ArgTypes ...)>&) [with _Res = void (&)(); _ArgTypes = {}]'
In file included from 5:0:
/usr/include/c++/4.9/future:1413:7: note: declared here
packaged_task(const packaged_task&) = delete;
^
21:10: error: could not convert 'future' from 'std::future<void (&)()>' to 'std::future<void (&())()>'
In file included from 5:0:
/usr/include/c++/4.9/future: In instantiation of 'static std::__future_base::_Task_setter<_Res_ptr> std::__future_base::_S_task_setter(_Res_ptr&, _BoundFn&&) [with _Res_ptr = std::unique_ptr<std::__future_base::_Result<void (&)()>, std::__future_base::_Result_base::_Deleter>; _BoundFn = std::_Bind_simple<std::reference_wrapper<std::_Bind<void (*())()> >()>; typename _Res_ptr::element_type::result_type = void (&)()]':
/usr/include/c++/4.9/future:1318:70: required from 'void std::__future_base::_Task_state<_Fn, _Alloc, _Res(_Args ...)>::_M_run(_Args ...) [with _Fn = std::_Bind<void (*())()>; _Alloc = std::allocator<int>; _Res = void (&)(); _Args = {}]'
29:1: required from here
/usr/include/c++/4.9/future:539:57: error: could not convert 'std::ref(_Tp&) [with _Tp = std::_Bind_simple<std::reference_wrapper<std::_Bind<void (*())()> >()>]()' from 'std::reference_wrapper<std::_Bind_simple<std::reference_wrapper<std::_Bind<void (*())()> >()> >' to 'std::function<void (&())()>'
return _Task_setter<_Res_ptr>{ __ptr, std::ref(__call) };
^
In file included from /usr/include/c++/4.9/memory:81:0,
from /usr/include/c++/4.9/thread:40,
from /usr/include/c++/4.9/future:40,
from 5:
/usr/include/c++/4.9/bits/unique_ptr.h:764:5: error: 'typename std::_MakeUniq<_Tp>::__single_object std::make_unique(_Args&& ...) [with _Tp = std::function<void()>; _Args = {add(FuncType&&, Args&& ...) [with FuncType = void (&)(); Args = {}; decltype (func) = void (&)()]::<lambda()>}; typename std::_MakeUniq<_Tp>::__single_object = std::unique_ptr<std::function<void()> >]', declared using local type 'add(FuncType&&, Args&& ...) [with FuncType = void (&)(); Args = {}; decltype (func) = void (&)()]::<lambda()>', is used but never defined [-fpermissive]
make_unique(_Args&&... __args)
^
In function 'std::future<decltype (func)(decltype (args)...)> add(FuncType&&, Args&& ...) [with FuncType = void (&)(); Args = {}; decltype (func) = void (&)()]':
22:2: warning: control reaches end of non-void function [-Wreturn-type]
/usr/include/c++/4.9/future:在“class std::future”的实例化中:
28:17:从这里开始需要
/usr/include/c++/4.9/future:697:7:错误:函数返回函数
得到()
^
在“add(FuncType&,Args&&…):[with FuncType=void(&)(;Args={}]”的实例化中:
19:37:从“结构添加(FuncType&&,Args&&…[其中FuncType=void(&)();Args={};decltype(func)=void(&)(]):”中必须输入
19:56:在“std::future add(FuncType&&,Args&&…[其中FuncType=void(&)();Args={};decltype(func)=void(&)(])”中必须输入
28:17:从这里开始需要
19:52:错误:将'const std::packated_task'传递为'void std::packated_task::operator()(_ArgTypes…)[with _Res=void(&();_ArgTypes={}]'的'this'参数将丢弃限定符[-fppermissive]
在“std::future add(FuncType&&,Args&&…[其中FuncType=void(&)();Args={};decltype(func)=void(&)(])”的实例化中:
28:17:从这里开始需要
19:36:错误:使用已删除的函数“std::packated_task::packated_task(const std::packated_task&)[with _Res=void(&)(;_ArgTypes={}]”
在从5:0开始包含的文件中:
/usr/include/c++/4.9/future:1413:7:注意:此处声明
打包任务(const packaged_task&)=删除;
^
21:10:错误:无法将“future”从“std::future”转换为“std::future”
在从5:0开始包含的文件中:
/usr/include/c++/4.9/future:In'static std::__future_base::_Task_setter std::__future_base:::_S_Task_setter(_Res_ptr&,_BoundFn&)[with _resuptr=std::unique_ptr;_BoundFn=std:_Bind:_Bind_simple;typename _resu ptr::element::resu type::resu type::resu type=void(&)]:
/usr/include/c++/4.9/future:1318:70:void std::u future_base::_Task_state::_M_run(_Args…)[with _Fn=std:_Bind;_Alloc=std::allocator;_Res=void(&)(;_Args={}]
29:1:从这里开始需要
/usr/include/c++/4.9/future:539:57:错误:无法将“std::ref(_-Tp&)[with _-Tp=std::_-Bind_-simple]()”从“std::reference_-wrapper”转换为“std::function”
返回{u任务设置器{u任务设置器,std::ref({u调用)};
^
在/usr/include/c++/4.9/memory:81:0中包含的文件中,
从/usr/include/c++/4.9/thread:40,
从/usr/include/c++/4.9/future:40,
从5日起:
/usr/include/c++/4.9/bits/unique\ptr.h:764:5:error:'typename std::'u MakeUniq::'u single_object std:'make_unique('u Args&&…)[with the _Tp=std::function;'u Args={add(FuncType&&,Args&…[with FuncType=void(&());Args={};decltype(func)=void(&)]:};typename std:',使用本地类型“add(FuncType&&,Args&&…[其中FuncType=void(&();Args={};decltype(func)=void(&())]:”声明,但从未定义[-fpermissive]
使_唯一(_参数&&…_参数)
^
在函数“std::future add(FuncType&&,Args&&…[其中FuncType=void(&)();Args={};decltype(func)=void(&)(])”中:
22:2:警告:控件到达非无效函数的末尾[-Wreturn类型]
我想我在这里有两个问题:我不知道如何正确使用decltype来获得正确的函数签名(我也研究了invoke_result,但我在那里也没有任何运气),我想我可能也没有正确地将打包的任务传递给队列
如何为将来和打包的任务获得正确的函数签名,以及如何将打包的任务正确地传递给队列上的std::函数(稍后将被另一个线程捕获)?两个问题:
1) 打包任务的签名应为
std::打包任务
。这使用invoke\u result\t
计算返回类型,但也将参数类型传递给打包任务
2) 更大的问题:std::function
要求函数是可复制构造的,而std::packaged\u task
则不是。您必须创建自己的队列来保存打包的任务。在使用带有模板化派生类的基类任务来保存打包任务之前,我已经实现了它。两个问题:
1) 打包任务的签名应为
std::打包任务
。这使用invoke\u result\t
计算返回类型,但也将参数类型传递给打包任务
2) 更大的问题:
std::function
要求函数是可复制构造的,而std::packaged\u task
则不是。您必须创建自己的队列来保存打包的任务。在使用带有模板化派生类的基类任务来保存打包任务之前,我已经实现了它。不确定,但尝试更改add to std::future的返回类型,这样future将生成指向函数的指针。不确定,但尝试更改add to std::future的返回类型,这样,future将生成一个指向函数的指针。