ラムダでのムーブ キャプチャ
質問:
また、ムーブ キャプチャを実装するにはどうすればよいですか? C 11 ラムダでは右辺値参照として知られていますか?例:
std::unique_ptr<int> myPointer(new int); std::function<void(void)> example = [std::move(myPointer)] { *myPointer = 4; };
答え:
C 14 の一般化ラムダキャプチャ
C 14 では、一般化ラムダキャプチャでは移動キャプチャが可能になります。このコードは現在有効です:
using namespace std; auto u = make_unique<some_type>(some, parameters); go.run([u = move(u)] { do_something_with(u); });
オブジェクトをラムダから別の関数に移動するには、ラムダを可変にします:
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 での一般化ラムダ キャプチャのエミュレーション
別の回避策はcapture()によって提供されますfunction:
#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)); }
このソリューションは、キャプチャされた型がコピー可能でない場合にラムダをコピーすることを防ぎ、実行時エラーを回避します。
以上がC ラムダでムーブ キャプチャを実装するにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。