模板函数上的C++模板类成员
我有一个线程池,可以接受任何std::packaged_任务,并给出未来模板函数上的C++模板类成员,c++,multithreading,templates,metaprogramming,C++,Multithreading,Templates,Metaprogramming,我有一个线程池,可以接受任何std::packaged_任务,并给出未来 template<typename RetType> template<typename Args...> std::future<RetType> submitWork(std::packaged_task<RetType(Args...)>&& callableWork>); 如您所见,打包的_任务是模板化的。现在,我的线程池使用一个无锁队列作为类
template<typename RetType>
template<typename Args...>
std::future<RetType> submitWork(std::packaged_task<RetType(Args...)>&& callableWork>);
如您所见,打包的_任务是模板化的。现在,我的线程池使用一个无锁队列作为类的成员
class ThreadPool
{
public:
private:
llQueue<boost::variant<???>> workQueue;
}
我希望工作队列是submitWork被调用的类型的变体。例:这个代码
bool runByPool(int var)
{
//do stuff
}
int runAlso(char c)
{
//do other stuff
}
ThreadPool pool; // 4 worker threads
pool.submitWork<bool(int)>(std::bind(runByPool, 1));
pool.submitWork<int<c>>(std::bind(runAlso, 'a'));
为编译时的工作队列提供以下类型:
llQueue<boost::variant<std::packaged_task<bool(int)>,
std::packaged_task<int(c)>
>
>
如何使类成员使用模板化子网络的类型?我想强制llQueue只保存std::packaged_任务,我使用了一个变体,这样我就可以避免堆分配,因为这需要非常高的性能
我希望避免堆分配,并且我需要相同的池,以便能够使用任何返回类型或参数类型执行任何工作大多数您发布的代码都不会编译
pool.submitWork<bool(int)>(std::bind(runByPool, 1));
这个签名太疯狂了。应该是,
std::future<RetType> submitWork(std::packaged_task<RetType(Args...)> callableWork);
作为奖励,它可以为您推断出回报类型
<>我相信我看到至少一个C++编译器,它会使打包的任务需要可拷贝的内容。因此,包含共享ptr的功能可能是您的备份计划。请从打包的任务签名中删除&&顺便说一句。它与您认为的不一样。谢谢,您能否解释一下为什么它不是完美转发?因为完美转发是转发引用的一个不好的术语。当模式匹配其他模板的模板参数时,没有什么可转发的,当没有模式匹配时,转发引用的行为对大多数人来说都不是直观的。哦,太好了,我没有考虑将其视为模式匹配,这更像是一个正在扩展的树,在实例化的时候,在我的脑海中充满了关于事情崩溃的规则。很抱歉,我发布了伪代码,显然错过了很多,谢谢。我有一个问题,当void打包任务最终在一个工作线程中执行时,它不会返回void吗?我如何从完成未来的任务中获得返回值是微不足道的。@steph furure连接在submitWork函数中。一旦它被执行,就没什么可做的了。哦,我明白了。出于某种原因,我认为你必须在以后明确地实现未来,亲爱的,这比我想象的还要干净我遇到了一个小小的障碍。enqueue上的隐式转换似乎不起作用,我也不知道为什么。相反,如果我通过添加以下行使赋值显式,它将起作用:std::packaged_task voidTaskstd::movetask;为什么我必须显式构造一个空的打包任务?@StephenEckels当然。事实证明,来自函数的打包任务是显式的。那么,修好它?
std::future<RetType> submitWork(std::packaged_task<RetType(Args...)> callableWork);
std::future<RetType> submitWork(std::function<RetType()> callableWork>);
llQueue<boost::variant<???>> workQueue;
llQueue<std::function<void()>> workQueue;
struct ThreadPool {
template<class F, class R=std::result_of_t<F&()>>
std::future<R> submitWork(F f){
auto task=std::packaged_task<R()>(std::move(f));
auto r=task.get_future();
workQueue.push_back(std::packaged_task<void()>(std::move(task)));
return r;
}
std::vector<std::packaged_task<void()>> workQueue;
// or:
//llQueue<std::packaged_task<void()>> workQueue;
// with changes to how things are enqueued
};