模板函数上的C++模板类成员

模板函数上的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>); 如您所见,打包的_任务是模板化的。现在,我的线程池使用一个无锁队列作为类

我有一个线程池,可以接受任何std::packaged_任务,并给出未来

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
};