Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Question about custom conversion of "lambda []void ()->void"

TestCase2 and TestCase3 can compile normally. However, in TestCase1 I get the following error:

E0312, Custom conversion from "lambda []void ()->void" to
       "EventHandler" is not appropriate.

Why am I getting this error? I want to know how to solve it.

#include <functional>
#include <iostream>

class EventHandler
{
    std::function<void()> _func;

public:
    int id;
    static int counter;

    EventHandler() : id{ 0 } {}
    EventHandler(const std::function<void()>& func) : _func{ func }
    {
        id = ++EventHandler::counter;
    }
};

int EventHandler::counter = 0;

int main()
{
    EventHandler TestCase1 = []() {};
    EventHandler TestCase2([]() {});
    EventHandler TestCase3 = static_cast<std::function<void()>>([]() {});
}
like image 713
Sitanimyu Avatar asked May 13 '26 14:05

Sitanimyu


1 Answers

Why am I getting this error?

The lambda []() {} is not the same as std::function<void()>. That means

decltype([]() {}) != std::function<void()>

and it has to be implicitly or explicitly converted.

At the line

EventHandler TestCase1 = []() {};

copy initialization take place, where compiler first has to convert the lambda to a std::function<void()> and then a EventHandler object. Compiler can not do double implicit conventions.

Therefore, you need to be explicit here, like in TestCase3 for instance.


I want to know how to solve it.

One way is to provide a templated constructor (if you willing to)

#include <type_traits> // std::is_convertible_v

class EventHandler
{
    std::function<void()> _func;
public:

    template<typename Func> EventHandler(Func func)
        : _func{ func }
    {
        static_assert(std::is_convertible_v<Func, decltype(_func)>
                                            , "is not valid arg!");
        // ....
    }
    // or in C++20 with <concepts> header
    // template<typename Func> EventHandler(Func func)
    //     requires std::convertible_to<Func, decltype(_func)>
    //  : _func{ func }
    // { ... }
};

Now you can

EventHandler TestCase1 = []() {}; // works

Demo

like image 164
JeJo Avatar answered May 15 '26 04:05

JeJo