Signature differences in C ++ 11

Given C ++ 11 lambdas with the following code,

template <typename M> void call(void (*f)(M), M m) { f(m); } int main() { call<int>([](int n) { }, 42); // OK int r; call<int>([&](int n) { r = n; }, 42); // KO } 

Is there a difference of signatures between lambdas, which makes the second incompatible with the call argument?

I am using g ++ 4.6.1.

Side question: why the parameter cannot be displayed if I write call([](int n) { }, 42); ?

+6
source share
2 answers

Only an illiterate lambda can be implicitly converted to a function pointer.

A lambda that captures variables cannot be converted to a function pointer because it has a state that must be supported (captured variables), and this state cannot be represented by a function pointer.

Type M cannot be inferred from function arguments, because conversion is required to convert lambda to function pointer. This conversion prohibits the output of a template argument. If you were to call the call function with the actual function (e.g. void f(int) ), the output of the argument will work fine.

+15
source

As James said, only illiterate lambdas can be converted to function pointers. Lambdas that have state create object objects that implement operator() , and member function pointers are incompatible with free function pointers.

When the compiler processes: [&](int n){ r = n; } [&](int n){ r = n; } it generates something like:

 class __annonymous_lambda_type { int & r; public: __annonymous_lambda_type( int & r ) : r(r) {} void operator()( int n ) const { r = n; } } __lambda_instatiation; 

The class must store the state of the lambda, in this case, a reference to an external object that will be changed when the lambda is executed. That void operator()(int) cannot be bound to void (*)(int) .

On the other hand, if a lambda has no status, it can be implemented as a free function, for example, in the case of []( int n ) { std::cout << "Hi" << n << std::endl ; } []( int n ) { std::cout << "Hi" << n << std::endl ; }

 void __annonymous_lambda_function( int n ) { std::cout << "Hi " << n << std::endl; } 

Since lambda does not need to save any state at all, and as such it can be stored as a simple function.

+7
source

Source: https://habr.com/ru/post/885461/


All Articles