Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why cannot pass the address of lambda function to another function here?

Tags:

c++

c++17

When I ran the code below I got a "bad_function_call" thrown

void fn(void* f) {
    auto fu = static_cast<std::function<void()>*>(f);
    (*fu)();
}

int main() {
    auto f1 = [] () {
        std::cout << "f1";
    };

    fn(&f1);
}

Of course code would work if I wrote:

void fn(void(*f)()) {
    f();
}

int main() {
    auto f1 = [] () {
        std::cout << "f1";
    };

    fn(f1);
}

but it fails when passing &f1 as a void* and converting it to std::function<void()>*.

What's the correct way if I want to do this?

like image 306
scengka Avatar asked Aug 11 '26 09:08

scengka


1 Answers

The second version of your code is ok because a lambda without capture can be converted to a function pointer. This conversion is from the type of the lambda to the type of the function pointer.

Once you converted the lambda to a void* you left the type system. There is no proper conversion from void* to a function pointer. To do this you would first need to cast the void* back to the type of the lambda, and then this can again be converted to a function pointer.

Your faulty code is similar to this:

  int x = 42;
  void* p = &x;
  float y = *static_cast<float*>(p);

Expecting the last line to make a proper conversion from int to float is wrong. The void* carries no information on what the actual type of the object is. static_cast<float*>(p) pretends that p would point to a float but it does not.

In modern C++ there is no reason to use void* for type erasure anymore. Only when interfacing legacy code that expects a void* you may need to resort to such unsafe casts. For other cases of type erasure, there is std::any, std::variant, std::function, and more.

like image 147
463035818_is_not_a_number Avatar answered Aug 13 '26 00:08

463035818_is_not_a_number



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!