【问题标题】:can't pass std::vector<std::unique_ptr<>> to std::thread无法将 std::vector<std::unique_ptr<>> 传递给 std::thread
【发布时间】:2015-01-18 15:29:48
【问题描述】:

我创建了一个线程池,它将函数和参数捕获到元组中,然后在任务出队时完美转发。

但是我无法通过右值将 unique_ptr 的向量传递给线程。一个简化的项目如下:

#include <future>
#include <memory>
#include <vector>

template <typename F, typename... Args>
typename std::result_of<F(Args...)>::type pushTask(F&& f, Args&&... args)
{
    using result_type = typename std::result_of<F(Args...)>::type;

    // create a functional object of the passed function with the signature std::function<result_type(void)> by creating a
    // bound Functor lambda which will bind the arguments to the function call through perfect forwarding and lambda capture
    auto boundFunctor = [func = std::move(std::forward<F>(f)),
                         argsTuple = std::move(std::make_tuple(std::forward<Args>(args)...))](void) mutable->result_type
    {
        // forward function and turn variadic arguments into a tuple
        return result_type();
    };

    // create a packaged task of the function object
    std::packaged_task<result_type(void)> taskFunctor{ std::move(boundFunctor) };
}

 int main(int argc, char *argv [])
 {
     auto testvup = [](std::vector<std::unique_ptr<int>>&& vup)
    {

    };
    std::vector<std::unique_ptr<int>> vup;
    pushTask(testvup, std::move(vup));
}

我使用 VS2015 得到以下编译器错误,而不是我使用 std::function 或 std::packaged_task

严重性描述项目文件行

Error   error C2280: 'std::unique_ptr<int,std::default_delete<_Ty>>::unique_ptr(const std::unique_ptr<_Ty,std::default_delete<_Ty>> &)': attempting to reference a deleted function Stack   xmemory0    659

通过右值传递其他参数,包括std::vector 有效。

有没有其他人遇到过这个问题或有建议。

【问题讨论】:

  • std::function 执行类型擦除。它是可复制的,因此它需要您存储在其中的函数对象的可复制性。
  • 是的,我选择的 std::function 就是一个糟糕的例子。但是,我得到与 std::packaged_task 相同的错误,它应该采取移动可构造对象

标签: multithreading c++11 unique-ptr


【解决方案1】:

C++ 标准部分 §20.9.11.2.1 [func.wrap.func]

template&lt;class F&gt; function(F f);

template <class F, class A> function(allocator_arg_t, const A& a, F f);

要求:F 应可复制构造。 f 应可调用 参数类型 ArgTypes 和返回类型 R。复制构造函数和 A 的析构函数不会抛出异常。

您的 lambda 函数 boundFunctor 是仅移动类型(因为它捕获仅移动类型,因为无法复制 std::unique_ptr

因此,boundFunctor 不可复制且不适合作为 std::function 的参数

【讨论】:

  • 感谢您的快速回复。但是,当我使用 std::packaged_task taskFunctor{ std::move(boundFunctor) }; } 而不是 std::function 我得到相同的结果。 packaged_task 应该采取移动可构造对象。
  • @bryanzim : 为我工作,see here,虽然我没有 VS2015
  • 感谢您的备用验证。它必须是 packaged_task 实现中的 Microsoft 特定错误。我应该向他们提交错误报告。
猜你喜欢
  • 2019-11-07
  • 2020-12-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-02
  • 1970-01-01
  • 1970-01-01
  • 2014-11-25
相关资源
最近更新 更多