mercredi 11 mars 2015

How to move a variable into a lambda expression?

I see the C++11 documentation (http://ift.tt/OEhZWO) for lambda expressions states capture by value and reference are supported but not rvalue reference. The closest SO question I could find related to this is: How to capture a unique_ptr into a lambda expression?, but it seems like my use case doesn't require the use of std::bind.


Code



#include <iostream>
#include <memory>

class Foo
{
public:
explicit Foo(int value = 0) : mValue(value) {}

// The following items are provided just to be explicit
Foo(Foo &&other) = default;
Foo &operator=(Foo &&other) = default;
Foo(const Foo &other) = delete;
Foo &operator=(const Foo &other) = delete;
~Foo() {}

int mValue;
};

void bar(std::unique_ptr<Foo> f)
{
std::cout << "bar: " << std::dec << f->mValue << "\n";
}

int main()
{
{
std::unique_ptr<Foo> f(new Foo(22));
std::cout << "main: " << std::hex << f.get() << "\n";

// Call the bar function directly (requires using std::move)
bar(std::move(f));
std::cout << "main: " << std::hex << f.get() << "\n";
}

{
std::unique_ptr<Foo> f(new Foo(99));
std::cout << "main: " << std::hex << f.get() << "\n";

// Lamda expression captures 'f' by reference and then calls the bar function (again, requires using std::move)
auto fn = [&f](){ bar(std::move(f)); };
fn(); // Execute the closure
std::cout << "main: " << std::hex << f.get() << "\n";
}

return 0;
}


Example Output



main: 0x92e010
bar: 22
main: 0
main: 0x92e010
bar: 99
main: 0


By examining the output it appears this program is running correctly (i.e., the observed results are what I expected. However, I have the following questions.


Questions



  1. Is using the closure equivalent to the code that calls the bar function directly?

    • I'm asking explicitly since the documentation (see beginning of the question) about lambda expressions didn't state anything about using std::move on captured references (i.e., I want to make sure this doesn't run afoul of undefined behavior or similar bad outcomes).



  2. If the answer to the first question is "you can't use std::move on the captured reference", then what is the right way to do this (e.g., the std::bind solution, etc)?


Aucun commentaire:

Enregistrer un commentaire