Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cannot pass std::unique_ptr in std::function<>

#include <functional>
#include <memory>
#include <string>
#include <iostream>

void foo(std::function<void()> f)
{
    f();
}

int main()
{
    std::unique_ptr<int> handle = std::make_unique<int>(5);
    foo(
        [h = std::move(handle)]() mutable
    {
        std::cout << *h << std::endl;
    });
}

Following code doen't compile with error

C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Tools\MSVC\14.28.29910\include\functional(914,58): error C2280: 'main::<lambda_1aa523ba59bbecea5306bc1fd178120f>::<lambda_1aa523ba59bbecea5306bc1fd178120f>(const main::<lambda_1aa523ba59bbecea5306bc1fd178120f> &)': attempting to reference a deleted function

  1. Why it is happen?
  2. Is there are way how pass std::unique_ptr in std::function<void()> without passing it by reference?
like image 324
magicDM Avatar asked Dec 30 '22 14:12

magicDM


1 Answers

The std::function requires the function object to be Copy-Constructible, so you can't expect a lamdba to be moved to it. On initialization, it attempts to copy the lambda and so the std::unique_ptr with it, which is a member of this lambda, and, expectedly, fails to do so. What you can do is store your lambda in a variable and pass it to function that accepts const std::function& using std::ref like that:

        void foo(const std::function<void()>& f); // function declaration
        auto a = [h = std::move(handle)]() mutable
        {
            std::cout << *h << std::endl;
        };
        foo(std::ref(a));

This is a related question with much more detailed answers: How to create an std::function from a move-capturing lambda expression?

like image 62
Моргунов Владислав Avatar answered Jan 02 '23 02:01

Моргунов Владислав