Home >Backend Development >C++ >How Can I Achieve Move Capture in C Lambdas (C 11 and C 14)?

How Can I Achieve Move Capture in C Lambdas (C 11 and C 14)?

Barbara Streisand
Barbara StreisandOriginal
2024-12-17 20:56:12806browse

How Can I Achieve Move Capture in C   Lambdas (C  11 and C  14)?

Move Capture in C 11 Lambda

Generalized Lambda Capture in C 14

C 14 introduces generalized lambda capture, enabling move capture. In C 14, code like the following will be valid:

auto u = make_unique<some_type>( some, parameters ); 

// move the unique_ptr into the lambda
go.run( [ u = move(u) ] { do_something_with( u ); } ); 

Note that if you need to move the object from the lambda to another function, the lambda must be marked as mutable:

go.run( [ u = move(u) ] mutable { do_something_with( std::move(u) ); } );

Workaround for Move Capture in C 11

In C 11, capturing by move can be achieved using a helper function make_rref that creates an rvalue reference to the desired value:

#include <cassert>
#include <memory>
#include <utility>

template <typename T>
struct rref_impl
{
    rref_impl() = delete;
    rref_impl( T &amp;&amp; x ) : x{std::move(x)} {}
    // ... implementation
};

template<typename T> rref_impl<T> make_rref( T &amp;&amp; x )
{
    return rref_impl<T>{ std::move(x) };
}

Use the make_rref function to capture the value in the lambda:

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() );
}

Note that this workaround makes the lambda copyable, which may cause problems when capturing non-copyable objects.

Emulating Generalized Lambda Capture in C 11

Another approach to emulate generalized lambda capture involves defining a capture function:

#include <utility>

template <typename T, typename F>
class capture_impl
{
    T x;
    F f;
public:
    // ... implementation
};

template <typename T, typename F>
capture_impl<T,F> capture( T &amp;&amp; x, F &amp;&amp; f )
{
    return capture_impl<T,F>(
        std::forward<T>(x), std::forward<F>(f) );
}

Use capture to capture the value by move:

int main()
{
    std::unique_ptr<int> p{new int(0)};
    auto lambda = capture( std::move(p),
        []( std::unique_ptr<int> &amp; p ) { return std::move(p); } );
    assert(  lambda() );
    assert( !lambda() );
}

This solution provides a cleaner approach that disables copying the lambda if the captured type is not copyable.

The above is the detailed content of How Can I Achieve Move Capture in C Lambdas (C 11 and C 14)?. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn