我应该如何正确地将 packaged_task 移至 lambda?

Max*_*Max 6 c++ lambda move-semantics packaged-task

我一直在尝试将 packaged_task 捕获到 lambda 中,但失败了。
\n我完全理解动作语义,也读过一些现代文学,我想我没有错过任何东西。我还阅读了 Josuttis 的移动语义书,以及关于广义 lambda 捕获的 ISO 主题以及ISO C++ 14 语言扩展
中的类似案例\n我有下一个代码:

\n\n
#include <thread>\n#include <vector>\n#include <functional>\n#include <queue>\n#include <condition_variable>\n#include <mutex>\n#include <future>\n#include <type_traits>\n#include <iostream>\n\n// #include\'s for below code and other purposes\n\nint main() {\n    auto f = []() { return 1; }; \n    std::queue<std::function<void()>> q;\n    std::packaged_task<int()> pack(f);\n    q.emplace([p = std::move(pack)] () mutable { p(); });\n\n    return 0;\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

这里我创建了简单的函数队列,保存一些“void()”和packaged_task,传递“int”返回类型的“f”。
\n然后我尝试将 packaged_task 移动到 lambda 中以便稍后在其他线程中使用它(我需要在其他线程中使用它,这将在稍后执行它,当“pack”将被销毁时,这就是为什么我不能引用它)
\n看起来一切都很好,但是当我用“g++ main.cpp -o main -std=c++14”(甚至使用c++17)编译它时, g++ 告诉我这个:

\n\n
\n

/usr/include/c++/9/bits/std_function.h:176:6: 错误:使用已删除的函数 \xe2\x80\x98main()::::(const main()::&)\xe2\x80
176 | x99 新的 _Functor(*__source._M_access());
\n | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~
\n main.cpp:19:32: 注意: \xe2\x80\x98main()::::(const main()::&)\xe2\x80\x99 被隐式删除,因为默认定义是格式错误:
\n 19 | q.emplace([p = std::move(pack)] () 可变 { p(); });
\n | ^
\n main.cpp:19:32: 错误:使用已删除的函数 \xe2\x80\x98std::packaged_task<_Res(_ArgTypes ...)>::packaged_task(const std::packaged_task<_Res(_ArgTypes .. .)>&) [with _Res = int; _ArgTypes = {}]\xe2\x80\x99
\n 在 main.cpp:8 包含的文件中:
\n /usr/include/c++/9/future:1511:7: 注意:此处声明
\n 1511 | packaged_task(const packaged_task&) = 删除;
\n | ^~~~~~~~~~~~~

\n
\n\n

另外,我可以使用shared_ptr通过将其副本传递给lambda来解决这个问题,但是这种解决问题的方式看起来太丑陋了。\n那么,如果我尝试移动它,为什么我会在复制构造时出错,我该如何修复它呢?

\n

Rev*_*lot 3

你的 lambda 没问题。如果将 lambda 定义移至其自己的行,您会发现其中没有错误。

您的问题实际上在于std::function 构造函数要求其参数为 CopyConstructible,并且由于您的 lambda 包含仅移动对象,因此它不是 CopyConstructible 。

您可以尝试实现类似于std::function仅移动类型的方法,或者尝试以不同的方式解决您的问题。