在 Lambda 中移动捕获
问题:
我们如何实现移动捕获在 C 11 lambda 中称为右值引用?例如:
std::unique_ptr<int> myPointer(new int); std::function<void(void)> example = [std::move(myPointer)] { *myPointer = 4; };
答案:
C 14 中的广义 Lambda 捕获
在 C 14 中,广义 lambda capture 允许移动捕捉。此代码现在有效:
using namespace std; auto u = make_unique<some_type>(some, parameters); go.run([u = move(u)] { do_something_with(u); });
要将对象从 lambda 移动到另一个函数,请使 lambda 可变:
go.run([u = move(u)] mutable { do_something_with(std::move(u)); });
C 11 中移动捕获的解决方法
辅助函数 make_rref 可以促进移动捕捉。其实现如下:
#include <cassert> #include <memory> #include <utility> template <typename T> struct rref_impl { rref_impl() = delete; rref_impl(T&& x) : x{std::move(x)} {} rref_impl(rref_impl& other) : x{std::move(other.x)}, isCopied{true} { assert(other.isCopied == false); } rref_impl(rref_impl&& other) : x{std::move(other.x)}, isCopied{std::move(other.isCopied)} { } rref_impl& operator=(rref_impl other) = delete; T& operator&&() { return std::move(x); } private: T x; bool isCopied = false; }; template<typename T> rref_impl<T> make_rref(T&& x) { return rref_impl<T>{std::move(x)}; }
make_rref 的测试用例:
int main() { std::unique_ptr<int> p{new int(0)}; auto rref = make_rref(std::move(p)); auto lambda = [rref]() mutable -> std::unique_ptr<int> { return rref.move(); }; assert(lambda()); assert(!lambda()); }
在 C 11 中模拟广义 Lambda Capture
另一个capture() 提供了解决方法函数:
#include <cassert> #include <memory> int main() { std::unique_ptr<int> p{new int(0)}; auto lambda = capture(std::move(p), [](std::unique_ptr<int>& p) { return std::move(p); }); assert(lambda()); assert(!lambda()); }
捕获实现如下:
#include <utility> template <typename T, typename F> class capture_impl { T x; F f; public: capture_impl(T&& x, F&& f) : x{std::forward<T>(x)}, f{std::forward<F>(f)} {} template <typename ...Ts> auto operator()(Ts&& ...args) -> decltype(f(x, std::forward<Ts>(args)...)) { return f(x, std::forward<Ts>(args)...); } template <typename ...Ts> auto operator()(Ts&& ...args) const -> decltype(f(x, std::forward<Ts>(args)...)) { return f(x, std::forward<Ts>(args)...); } }; template <typename T, typename F> capture_impl<T, F> capture(T&& x, F&& f) { return capture_impl<T, F>( std::forward<T>(x), std::forward<F>(f)); }
如果捕获的类型不可复制,此解决方案可防止复制 lambda,从而避免运行时错误。
以上是如何在 C Lambda 中实现移动捕获?的详细内容。更多信息请关注PHP中文网其他相关文章!