Search code examples
c++lambdaimplicit-conversionstd-function

Why is class with std::function argument in constructor not implicitly convertible to callable


Here is a simplified class I have:

class Event {
private:
    std::function<void()> m_func;
public:
    Event(std::function<void()> func)
        : m_func(func)
    {}
};

I cannot do implicit conversions on it:

void foo() {}

int main() {
    Event evt = foo; //error
    evt = []() {}; //error
}

Why is this? std::function by itself is implicitly convertible to a callable object: std::function<void()> func = []() {}.


Solution

  • Because only one user-defined implicit conversion is allowed in one conversion sequence.

    For Event evt = foo;, two user-defined conversions are required. One is from function pointer to std::function, one is from std::function to Event.

    Similarly for evt = []() {};, one user-defined conversion is from lambda to std::function, one is from std::function to Event, are required.

    You can apply direct initialization instead of copy initialization, or perform some explicit conversion in advance. E.g.

    Event evt (foo);                      // direct initialization
    evt = std::function<void()>([]() {}); // convert lambda to std::function in advance