gpt4 book ai didi

c++ - 无法将 std::packaged_task 移动到 lambda 中

转载 作者:行者123 更新时间:2023-12-05 03:32:08 25 4
gpt4 key购买 nike

我想在循环中延迟执行打包任务。

class ILoop {
public:
virtual void Deffer(std::function<void()>&& task) = 0;
void Deffer(std::function<void()>& task) = delete;

static void set_loop(ILoop*);
static ILoop& loop();

private:
static ILoop* loop_;
};

template <typename T>
struct LoopExecutor {
std::future<T> Commit(std::function<T()>&& task) {
std::packaged_task<T()> wrapper([t = std::move(task)] { return t(); });
std::future<T> future = wrapper.get_future();

ILoop::loop().Deffer([wrapper = std::move(wrapper)] { wrapper(); });
return future;
}
};

当我尝试编译它时

auto t = executor.Commit([] { return 100; });

我有编译错误:

[1/2] Building CXX object unit_tests/CMakeFiles/reduct_tests.dir/reduct/async/awaiters_test.cc.o
FAILED: unit_tests/CMakeFiles/reduct_tests.dir/reduct/async/awaiters_test.cc.o
/usr/bin/g++-11 -I/home/atimin/.conan/data/fmt/8.0.1/_/_/package/20da98908a15523bbe9f086a5c57a4bde424a9c0/include -I/home/atimin/.conan/data/uwebsockets/20.8.0/_/_/package/c84c7dca9672f88b95bafb2f5754a22669d1bbe5/include -I/home/atimin/.conan/data/uwebsockets/20.8.0/_/_/package/c84c7dca9672f88b95bafb2f5754a22669d1bbe5/include/uWebSockets -I/home/atimin/.conan/data/nlohmann_json/3.9.1/_/_/package/5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9/include -I/home/atimin/.conan/data/gtest/1.11.0/_/_/package/63868df56b76903d4ad40ecbd5b2e8238cee50c9/include -I/home/atimin/.conan/data/catch2/2.13.7/_/_/package/5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9/include -I/home/atimin/.conan/data/zlib/1.2.11/_/_/package/be27726f9885116da1158027505be62e913cd585/include -I/home/atimin/.conan/data/usockets/0.8.1/_/_/package/f3766c5a18b2feee4dc2c3a94335008aaaea2543/include -I/home/atimin/Projects/flipback/reduct-storage/src -I/home/atimin/Projects/flipback/reduct-storage/cmake-build-debug-gcc11 -I/home/atimin/Projects/flipback/reduct-storage/unit_tests -g -DLIBUS_NO_SSL -std=gnu++20 -MD -MT unit_tests/CMakeFiles/reduct_tests.dir/reduct/async/awaiters_test.cc.o -MF unit_tests/CMakeFiles/reduct_tests.dir/reduct/async/awaiters_test.cc.o.d -o unit_tests/CMakeFiles/reduct_tests.dir/reduct/async/awaiters_test.cc.o -c /home/atimin/Projects/flipback/reduct-storage/unit_tests/reduct/async/awaiters_test.cc
In file included from /home/atimin/Projects/flipback/reduct-storage/src/reduct/async/awaiters.h:10,
from /home/atimin/Projects/flipback/reduct-storage/unit_tests/reduct/async/awaiters_test.cc:3:
/home/atimin/Projects/flipback/reduct-storage/src/reduct/async/executors.h: In instantiation of ‘std::future<_Res> reduct::async::LoopExecutor<T>::Commit(std::function<T()>&&) [with T = int]’:
/home/atimin/Projects/flipback/reduct-storage/src/reduct/async/awaiters.h:40:68: required from ‘reduct::async::Run<T, Executor>::Run(std::function<T()>&&) [with T = int; Executor = reduct::async::LoopExecutor<int>]’
/home/atimin/Projects/flipback/reduct-storage/unit_tests/reduct/async/awaiters_test.cc:52:92: required from here
/home/atimin/Projects/flipback/reduct-storage/src/reduct/async/executors.h:19:66: error: no match for call to ‘(const std::packaged_task<int()>) ()’
19 | ILoop::loop().Deffer([wrapper = std::move(wrapper)] { wrapper(); });
| ~~~~~~~^~
In file included from /home/atimin/Projects/flipback/reduct-storage/src/reduct/async/awaiters.h:8,
from /home/atimin/Projects/flipback/reduct-storage/unit_tests/reduct/async/awaiters_test.cc:3:
/usr/include/c++/11/future:1577:7: note: candidate: ‘void std::packaged_task<_Res(_ArgTypes ...)>::operator()(_ArgTypes ...) [with _Res = int; _ArgTypes = {}]’ (near match)
1577 | operator()(_ArgTypes... __args)
| ^~~~~~~~
/usr/include/c++/11/future:1577:7: note: passing ‘const std::packaged_task<int()>*’ as ‘this’ argument discards qualifiers
In file included from /usr/include/c++/11/future:47,
from /home/atimin/Projects/flipback/reduct-storage/src/reduct/async/awaiters.h:8,
from /home/atimin/Projects/flipback/reduct-storage/unit_tests/reduct/async/awaiters_test.cc:3:
/usr/include/c++/11/bits/std_function.h:414:9: error: ‘std::function<_Res(_ArgTypes ...)>::function(_Functor) [with _Functor = reduct::async::LoopExecutor<int>::Commit(std::function<int()>&&)::<lambda()>; <template-parameter-2-2> = void; <template-parameter-2-3> = void; _Res = void; _ArgTypes = {}]’, declared using local type ‘reduct::async::LoopExecutor<int>::Commit(std::function<int()>&&)::<lambda()>’, is used but never defined [-fpermissive]
414 | function(_Functor __f)

实际上,即使是更简单的代码(没有 Defer 函数)也是行不通的:


auto t = [w = std::move(wrapper)] { w(); };
t();

另一方面,没关系:

   std::thread t(std::move(wrapper));

我使用 GCC 11.2。

最佳答案

默认情况下,lambda 的调用运算符是 const 限定的。

因此,在 lambda 的主体内,指向 lambda 的 this 指针也是 const 限定的,成员 wrapper 也是如此。std::packaged_task 没有 const 限定的 operator(),因此无法调用。

您可以通过添加 mutable 关键字使 lambda 的 operator() 成为非 const 限定:

[wrapper = std::move(wrapper)]()mutable{ wrapper(); }

请注意,目前带有说明符的 lambda 的语法确实需要将空参数列表作为 () 给出。


但是,您有一个更大的问题:在 lambda 中存储 std::packaged_task 会使 lambda 不可复制。但是 std::function 要求存储的类型是可复制的。您不能将它用于此用例,另请参阅 How to create an std::function from a move-capturing lambda expression?

关于c++ - 无法将 std::packaged_task 移动到 lambda 中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70519893/

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