我应该如何将packaged_task正确移动到lambda?

问题描述 投票:2回答:1

我一直试图将packaged_task捕获到lambda中,但是我失败了。我完全了解移动语义学,也读过一些现代文学,我当时以为我什么都没错过。另外,我在ISO C++ 14 Language Extensions处阅读了Josuttis的move语义书,以及有关广义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()::&)”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 ...> :: packaged_task(const std :: packaged_task <_res ...>&)[with _Res = int; _ArgTypes = {}]’在main.cpp:8包含的文件中:/ usr / include / c ++ / 9 / future:1511:7:注意:在此声明1511 | packaged_task(const packaged_task&)=删除;| ^ ~~~~~~~~~~~~~

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

c++ lambda move-semantics packaged-task
1个回答
0
投票

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

您的问题实际上在于std::function constructor requires its argument to be CopyConstructible,并且由于您的lambda包含仅移动对象,因此它不是CopyConstructible。

您可以尝试implement something similar to std::function for move-only types,或尝试以其他方式解决您的问题。

© www.soinside.com 2019 - 2024. All rights reserved.