5

I see the C++11 documentation (http://en.cppreference.com/w/cpp/language/lambda) 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)?
Community
  • 1
  • 1
James Adkison
  • 9,412
  • 2
  • 29
  • 43

1 Answers1

3

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

Yes, they're equivalent in this code. Captured references aren't special in any way that I can think of: you have fully defined behavior, as long as f is in scope and can be moved from.

Mooing Duck
  • 64,318
  • 19
  • 100
  • 158