繁体   English   中英

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

[英]C++ Template class member on a template function

我有一个线程池,应该接受任何std :: packaged_task并给出一个未来。

template<typename RetType>
template<typename Args...>
std::future<RetType> submitWork(std::packaged_task<RetType(Args...)>&& callableWork>);

如您所见,packaged_task是模板化的。 现在我的线程池使用无锁队列作为该类的成员

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'));

在编译时为workQueue提供以下类型:

llQueue<boost::variant<std::packaged_task<bool(int)>,
                       std::packaged_task<int(c)>
                      >
        >

如何使类的成员使用模板化SubmitWork的类型? 我想强制llQueue只保留std :: packaged_task,并且我使用了一个变体,因此我可以避免堆分配,因为这需要非常高性能。

我想避免堆分配,并且我需要同一个池才能执行具有任何返回类型或参数类型的任何工作

您发布的大多数代码都不会编译。

pool.submitWork<bool(int)>(std::bind(runByPool, 1));

std::bind(runByPool, 1)的签名是bool()而不是bool(int) 在您的另一个示例中,同样的错误,忽略了那里的其他语法错误。

std::future<RetType> submitWork(std::packaged_task<RetType&&(Args&&...)&& callableWork>);

这个签名是精神错乱。 它应该是;

std::future<RetType> submitWork(std::packaged_task<RetType(Args...)> callableWork);

接下来,进行仍然需要非均匀类型arg的工作几乎没有任何意义。 这反映在您的示例中。

实际上,在这里执行打包任务是没有意义的。

std::future<RetType> submitWork(std::function<RetType()> callableWork>);

更有意义。 您执行返回T的操作,并返回将来的T。

llQueue<boost::variant<???>> workQueue;

这里不需要变体。 您需要一个可以运行的任务队列。 它们的返回类型应该已经路由到其他地方,并且它们的参数已经绑定。

llQueue<std::function<void()>> workQueue;

现在仍然存在一个技术问题。 std::function<void()>要求它是可复制的; 将callableWork连接到将来的简单方法使您面临不可复制的打包任务。

有几种解决方法。 首先是将打包的任务推送到共享的ptr中,然后将其存储在函数中。 第二个要注意的是packaged_task<T()>是只能通过签名void()调用的移动,可以将其存储在packaged_task<void()>

因此,我们来了一圈。

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

作为奖励,它可以为您推断出退货类型。 现场例子

我相信我已经看到至少一个C ++编译器搞砸了,使打包的任务需要可复制的内容。 因此,包含共享ptr的功能可能是您的备份计划。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM