2

Using this:

https://stackoverflow.com/a/16968463/629530

I can capture a unique_ptr in a lambda. But I have problems when I try to pass the lambda function around with a captured unique_ptr. Here's an example:

// test.cc
#include <iostream>
#include <memory>

std::function<int()>
get_func()
{
    auto i = std::make_unique<int>(2);
    return [i=std::move(i)]() {
        return *i;
    };
}

int
main(int argc, char* argv[])
{
    auto func = get_func();
    std::cout << "val: " << func() << std::endl;
    return 0;
}

When I compile (running on my mac, but I see similar errors in Linux):

g++ -g -Wall -Werror -std=c++17 test.cc -o test

There's a lot of output, but this seems to be the salient part:

test.cc:9:13: note: copy constructor of '' is implicitly deleted because field '' has a deleted copy constructor
    return [i=std::move(i)]() {
            ^
/Library/Developer/CommandLineTools/usr/include/c++/v1/memory:2490:3: note: copy constructor is implicitly deleted because 'unique_ptr<int, std::__1::default_delete<int> >' has a user-declared move constructor
  unique_ptr(unique_ptr&& __u) noexcept

If I understand things right, this happens because the function itself is being copied. Is there a way for me to std::move the function to the caller to avoid the copy in the return? Or can I accomplish this with an output parameter?

Barry
  • 286,269
  • 29
  • 621
  • 977
firebush
  • 5,180
  • 4
  • 34
  • 45
  • The problem is earlier than that. `std::function` [requires that the wrapped object be CopyConstructible](https://en.cppreference.com/w/cpp/utility/functional/function/function), but your lambda is not (it's move-only). The failure is in the construction of the `std::function` from the lambda. We haven't even gotten to trying to copy the `std::function`. You can work around it by returning the lambda directly instead of wrapping it inside a `std::function`. – Raymond Chen Oct 15 '19 at 00:10
  • Interesting. What do you mean by “return the lambda directly?” What should my return type be if not a std::function? – firebush Oct 15 '19 at 00:22
  • `auto get_func() { return [i=std::make_unique(2)]() { return *i; }; }` – Raymond Chen Oct 15 '19 at 03:16

1 Answers1

2

As pointed out in comments - callable wrapped in std::function has to copy constructible. So instead of returning function just return lambda itself like that:

auto get_func()
{
    auto i = std::make_unique<int>(2);
    return [i=std::move(i)]() {
        return *i;
    };
}
bartop
  • 9,971
  • 1
  • 23
  • 54