我想在回圈中推遲打包任務的執行。
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。
uj5u.com熱心網友回復:
默認情況下,lambda 的呼叫運算子是const-qualified。
在 lambda 的主體內部,this指向lambda 的指標因此也是const限定的,成員也是如此wrapper。
std::packaged_task沒有const-qualified operator(),因此無法呼叫。
您可以通過添加關鍵字使 lambda 成為operator()非const限定mutable:
[wrapper = std::move(wrapper)]()mutable{ wrapper(); }
請注意,當前帶有說明符的 lambda 的語法確實需要將空引數串列作為 給出()。
但是,您有一個更大的問題:std::packaged_task在 lambda 中存盤 a會使 lambda 不可復制。但std::function要求存盤的型別是可復制的。您不能在此用例中使用它,另請參閱如何從移動捕獲 lambda 運算式創建 std::function?
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/397643.html
上一篇:限制惰性列中的專案
下一篇:在另一個類中填充型別別的陣列
