"If a worker wants to do his job well, he must first sharpen his tools." - Confucius, "The Analects of Confucius. Lu Linggong"
Front page > Programming > Mobile capture implementation tips in C++ Lambda

Mobile capture implementation tips in C++ Lambda

Posted on 2025-04-12
Browse:355

How to Implement Move Capture in C   Lambdas?

Move Capture in Lambdas

Question:

How do we implement move capture, also known as rvalue references, in C 11 lambdas? For instance:

std::unique_ptr myPointer(new int);

std::function example = [std::move(myPointer)] {
   *myPointer = 4;
};

Answer:

Generalized Lambda Capture in C 14

In C 14, generalized lambda capture allows for move capture. This code is now valid:

using namespace std;

auto u = make_unique(some, parameters);  
go.run([u = move(u)] { do_something_with(u); }); 

To move objects from a lambda to another function, make the lambda mutable:

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

Workaround for Move Capture in C 11

A helper function, make_rref, can facilitate move capture. Its implementation is as follows:

#include 
#include 
#include 

template 
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 rref_impl make_rref(T&& x) {
    return rref_impl{std::move(x)};
}

A test case for make_rref:

int main() {
    std::unique_ptr p{new int(0)};
    auto rref = make_rref(std::move(p));
    auto lambda =
        [rref]() mutable -> std::unique_ptr { return rref.move(); };
    assert(lambda());
    assert(!lambda());
}

Emulating Generalized Lambda Capture in C 11

Another workaround is provided by the capture() function:

#include 
#include 

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

capture is implemented as follows:

#include 

template 
class capture_impl {
    T x;
    F f;
public:
    capture_impl(T&& x, F&& f)
        : x{std::forward(x)}, f{std::forward(f)} {}

    template  auto operator()(Ts&& ...args)
        -> decltype(f(x, std::forward(args)...)) {
        return f(x, std::forward(args)...);
    }

    template  auto operator()(Ts&& ...args) const
        -> decltype(f(x, std::forward(args)...)) {
        return f(x, std::forward(args)...);
    }
};

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

This solution prevents copying the lambda if the captured type is not copyable, avoiding runtime errors.

Latest tutorial More>

Disclaimer: All resources provided are partly from the Internet. If there is any infringement of your copyright or other rights and interests, please explain the detailed reasons and provide proof of copyright or rights and interests and then send it to the email: [email protected] We will handle it for you as soon as possible.

Copyright© 2022 湘ICP备2022001581号-3