Lambda in return statement cannot be implicitly converted to functor

Viewed 79

I have the following code

struct Functor
{
    Functor(std::function<void()> task) : _task {task} {}
    void operator() () {_task();}
    std::function<void()> _task{};
};

Functor run1() //OK
{
    return Functor([](){std::cout << "From function" << std::endl;});
}

Functor run2() //Bad. Compile time error
{
    return [](){std::cout << "From function" << std::endl;};
}

My questions are:

  1. Why run1() is okay but run2() is not allowed?
  2. Is there a constructor in the struct Functor that I can define in order to make run2() valid as it is? I am asking this because currently the return type of run2() in my project is std::function<void()> and all is good, but I now need to change it into a functor to store some additional properties, but return statement like run2() are used in many places, and I am reluctant to modify every occurrences of it into run1().
1 Answers
  1. As it is already mentioned in the comments, run2 requires two implicit user conversions, which is prohibited.

  2. You can create a template constructor in Functor to make your code valid:

#include <functional>
#include <iostream>

struct Functor {
    Functor(auto && task) : _task { task } {}
    void operator() () {_task();}
    std::function<void()> _task{};
};

Functor run1() //OK
{
    return Functor([](){std::cout << "From function" << std::endl;});
}

Functor run2() //Ok
{
    return [](){std::cout << "From function" << std::endl;};
}

Demo: https://gcc.godbolt.org/z/bdnYTbKv4

Related