gpt4 book ai didi

c++ - 将不可复制的类型转发到 std::thread

转载 作者:太空狗 更新时间:2023-10-29 21:41:39 27 4
gpt4 key购买 nike

以下程序不在 GCC 4.9.2 或 clang 3.6 中构建:

#include <iostream>
#include <vector>
#include <thread>

/* Non-copyable type */
struct Foo {
Foo() {};

Foo(const Foo &) = delete;
Foo &operator=(const Foo &) = delete;

Foo(Foo &&) = default; //EDIT: This fixes CASE 1
};

/* Bar depends on Foo */
struct Bar {
Bar(const Foo &) {}
};

template <class T, class... Args>
void my_function(Args &&... args) {
std::vector<T> data;
auto lambda = [&data](Args &&... ts) { data.emplace_back(ts...); };

lambda(std::forward<Args>(args)...); // <-- Compile
std::thread(lambda, std::forward<Args>(args)...); //<--- Does NOT compile
}

int main() {
//CASE 1: (works)
// my_function<Bar>(Foo());
//CASE 2: (does not work)
Foo my_foo;
my_function<Bar>(my_foo);
}

这是因为 Foo 不可复制,并且将 Foo 的实例转发到 std:thread 会尝试复制它(为什么?)。但是,如果您将同一个实例直接转发给 lambda,它就会编译。

我想,我没有完全理解 std::thread 构造函数的所有要求。任何帮助将不胜感激。

编辑:即使我们使 Foo 可 move ,情况 2 也不起作用。有什么线索吗?

谢谢。

最佳答案

http://en.cppreference.com/w/cpp/thread/thread/thread说:“首先,构造函数将所有参数 args 复制/move 到线程可访问的存储空间”

但是,Foo 既不可复制也不可 move 。如果将 move 构造函数添加到 Foo,则它会编译:

struct Foo {
Foo() {};

Foo(const Foo &) = delete;
Foo &operator=(const Foo &) = delete;

Foo(Foo &&) = default; // newly added
};

如果您想将左值传递给线程,这将不起作用:线程构造函数尝试复制或 move Foo 对象。但是,Foo 不可复制,您不能从左值 (my_foo) move 。你有这些可能性:

  • 将左值转换为右值:

    my_function<Bar>(std::move(my_foo));

这很危险,因为现在 my_foo 处于无法使用的状态。

  • 用引用包装左值并将引用包装器传递给线程:

    my_function<Bar>(std::cref(my_foo));

(或 std::ref ,如果你想修改 my_foo )

关于c++ - 将不可复制的类型转发到 std::thread,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28290125/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com