0

The following code does not compile:

struct S{};

void foo(std::unique_ptr<S> ptr)
{
    auto l = [p = std::move(ptr)]()
    {
        auto p2 = std::move(p);
    };
    l();
}

The reason is that std::move(p) returns an lvalue reference and hence the compiler tries to call the copy constructor, which is deleted. Why does move return an lvalue reference here?

Here is a full sample.

Timo
  • 9,269
  • 2
  • 28
  • 58

1 Answers1

7

Mark the lambda mutable, otherwise its captures are const. As in

auto l = [p = std::move(ptr)]() mutable { ... };
Igor Tandetnik
  • 50,461
  • 4
  • 56
  • 85
  • That explains it. I was wondering if the captures are const but intellisense told me `p` is `std::remove_reference&>::type` which confused me. Thanks. – Timo Aug 18 '19 at 17:15
  • @Timo Intellisense is *not* the compiler. It tries to help by partially compiling the code and guessing. It may be helpful, sometimes, but never treat it as a source of truth - it very much *is not*. – Jesper Juhl Aug 18 '19 at 17:30
  • @JesperJuhl Yeah I know that, but since the compiler didn't give me much of an answer (except that I try to call a deleted copy constructor) Intellisense was the closest source of information I had. – Timo Aug 18 '19 at 17:33
  • The argument to `foo` is by value. It should be `void foo(std::unique_ptr& ptr)` to pass (and move) the unique ptr into the lambda. Alternately, the move could be at the calling function. – doug Aug 18 '19 at 17:53
  • @doug *"The argument to foo is by value."* So what? I don't see anything wrong with it. Passing by lvalue reference, on the other hand, would prevent you from passing in temporaries. It would also make the semantics of `foo` confusing (when you pass a varible to a function, you generally don't expect it to be moved from, unless you `std::move`'d it explicitly). – HolyBlackCat Aug 18 '19 at 17:57
  • @HolyBlackCat Yeah, I generally pass by reference when I move something later. But arguably, moving in the calling function is clearer and probably better. – doug Aug 18 '19 at 18:01
  • 1
    Actually, the method `operator()` is const, not the captures – JVApen Aug 18 '19 at 18:08