【问题标题】:Passing member functions with variadic template arguments to variadic constructors将带有可变参数模板参数的成员函数传递给可变参数构造函数
【发布时间】:2016-01-30 08:25:42
【问题描述】:

我不知道如何将带有可变模板参数的成员函数传递给std::thread 构造函数。我有一个接收函数及其参数的方法,需要将它们传递给在新线程中调用并在那里调用传递函数的其他方法。 这是简化版:

class Test
{
public:
    template<typename Function, typename... Args>
    void Run(Function&& f, Args&&... args)
    {
        std::thread t(&Test::Operation, this, f, args...); // how???
        t.detach();
    }

    template<typename Function, typename... Args>
    void Operation(Function&& f, Args&&... args)
    {
        f(args...);
    }
};

Test test;
test.Run([](const std::string& msg) { std::cout << msg; }, "Hi!");

以这种方式传递参数有问题,我收到以下错误:'std::thread::thread':没有重载函数需要 4 个参数。我该怎么做?

【问题讨论】:

  • 为什么不直接使用函数重载?
  • @vonbrand 我需要在类似的场景中执行大量的各种功能,所以我想最小化代码

标签: c++ multithreading c++11


【解决方案1】:

这里的问题是当你将&amp;Test::Operation传递给线程构造函数时,它无法推导出&amp;Test::Operation的模板参数。 (如果您想了解为什么无法进行此推论,您可能应该提出一个单独的问题。)关键是您需要明确指定 &amp;Test::Operation 的模板参数。

这将如下所示:

template<typename Function, typename... Args>
void Run(Function&& f, Args&&... args)
{
    std::thread t(&Test::Operation<std::decay_t<Function>, std::decay_t<Args>...>,
                  this, std::forward<Function>(f), std::forward<Args>(args)...);
    t.detach();
}

我为您添加了完美转发:这很重要,因为您不想执行不必要的复制,对吧?

但是为什么我们需要decay_t?这是因为线程构造函数在将它们的副本存储到新线程的内部存储之前先衰减了它的参数,所以,例如,如果你传入"Hi!",那么推导的类型是const char (&amp;)[4],但它会变成const char*一旦衰减,衰减是不可逆的,所以Test::Operation 一定不能期待一个const char (&amp;)[4],它不能从衰减的const char* 中初始化。所以Test::Operation必须指定为衰减类型。

您可能还希望在实际调用期间完美转发。

链接:http://coliru.stacked-crooked.com/a/c9d04c03a3758b51

【讨论】:

  • 绝对是我想要的。谢谢解释!
猜你喜欢
  • 1970-01-01
  • 2014-10-20
  • 1970-01-01
  • 2011-03-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-29
  • 2011-09-05
相关资源
最近更新 更多