Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't I convert a lambda to a type constructed from std::function? [duplicate]

Tags:

c++

Why doesn't this code compile?

#include <functional>

struct S { S(std::function<void()>) { } };

int main()
{
    S a([]() {});   // compiles
    S b = []() {};  // doesn't compile (except pre-C++20 on MSVC!)
}

Clang's error:

error: no viable conversion from '(lambda at <source>:6:8)' to 'S'
      |         S b = []() {};  // doesn't compile (except pre-C++20 on MSVC!)
      |           ^   ~~~~~~~
note: candidate constructor not viable: no known conversion from '(lambda at <source>:6:8)' to 'std::function<void ()>' for 1st argument
      | struct S { S(std::function<void()>) { } };
      |            ^ ~~~~~~~~~~~~~~~~~~~~~
like image 676
user541686 Avatar asked Apr 29 '26 05:04

user541686


2 Answers

Let's put std::function and lambdas aside, because the issue is more general, and look at a simpler example:

struct A {};

struct B {
    B(A) {}
};

struct C {
    C(B) {}
};

int main() {
    C c1(A{});      // I
    C c2 = A{};     // II
}

I is ok but II fails with:

<source>:15:7: error: no viable conversion from 'A' to 'C'

(Full error here: https://godbolt.org/z/GYbezWEG5)

The reason is that only a single user provided conversion is taken into account.

C c1(A{}) requires to convert A to B to call the constructor of C. This is ok.

C c2 = A{}; on the other hand would require to first convert the A to B and then B to C. This is not ok.

For more details I refer you to cppreference.

like image 108
463035818_is_not_a_number Avatar answered Apr 30 '26 20:04

463035818_is_not_a_number


in MSVC C++20 flag automatically adds /permissive- , it doesn't compile with C++17 and /permissive- non working godbolt demo

technically it shouldn't compile because this requires 2 implicit conversions, lambda -> std::function -> S

you need a constructor that can accept anything convertible to std::function<void()>

struct S { 
    S(std::function<void()>) { }

    S(auto&& arg) requires requires {std::function<void()>{arg};} {}
};

godbolt demo

like image 36
Ahmed AEK Avatar answered Apr 30 '26 20:04

Ahmed AEK



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!