0

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 = []() {}.

TwistedBlizzard
  • 931
  • 2
  • 9
  • 1
    Duplicate: [Question about custom conversion of "lambda [\]void ()->void"](https://stackoverflow.com/questions/72400779/question-about-custom-conversion-of-lambda-void-void). Because *"Compiler can not do double implicit conversions."* – Jason Nov 08 '22 at 06:10

1 Answers1

4

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
songyuanyao
  • 169,198
  • 16
  • 310
  • 405
  • 2
    If you're curious about _why_ only one user-defined conversion is allowed in an implicit conversion sequence, [this question](https://stackoverflow.com/questions/21337198/why-user-defined-conversions-are-limited) gets into the motivation for the policy – Nathan Pierson Nov 08 '22 at 06:00
  • 1
    I see. Thanks for showing alternate ways of initialization too. – TwistedBlizzard Nov 08 '22 at 06:04