ホームページ > バックエンド開発 > C++ > C ラムダでムーブ キャプチャを実装するにはどうすればよいですか?

C ラムダでムーブ キャプチャを実装するにはどうすればよいですか?

Linda Hamilton
リリース: 2024-12-26 13:35:10
オリジナル
788 人が閲覧しました

How to Implement Move Capture in C   Lambdas?

ラムダでのムーブ キャプチャ

質問:

また、ムーブ キャプチャを実装するにはどうすればよいですか? 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 サイトの他の関連記事を参照してください。

ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
著者別の最新記事
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート