3

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

#include <thread>
#include <vector>
#include <functional>
#include <queue>
#include <condition_variable>
#include <mutex>
#include <future>
#include <type_traits>
#include <iostream>

// #include's for below code and other purposes

int main() {
    auto f = []() { return 1; }; 
    std::queue<std::function<void()>> q;
    std::packaged_task<int()> pack(f);
    q.emplace([p = std::move(pack)] () mutable { p(); });

    return 0;
}

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

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

我也可以通过将它的副本传递给 lambda 来使用 shared_ptr 来解决这个问题,但是这种解决问题的方式似乎太难看了。那么,如果我试图移动它,为什么我在复制构造时会出错,我该如何解决呢?

4

1 回答 1

2

你的 lambda 很好。如果将 lambda 定义移动到它自己的行,你会发现其中没有错误。

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

您可以尝试实现类似于std::functionfor move-only types 的东西,或者尝试以不同的方式解决您的问题。

于 2020-05-16T14:47:54.360 回答