Does lambda capture cause an error on incompatible operand types?

Consider the following code:

main() { bool t; ... std::function<bool (bool)> f = t ? [](bool b) { return b; } : [](bool b) { return !b; }; // OK std::function<bool (bool)> f = t ? [t](bool b) { return t == b; } : [t](bool b) { return t != b; }; // error } 

When compiling with Clang 3.1, non-capture lambda assignment works while capture fails:

 main.cpp:12:36: error: incompatible operand types ('<lambda at main.cpp:12:38>' and '<lambda at main.cpp:12:71>') std::function<bool (bool)> f2 = t ? [t](bool b) { return t == b; } : [t](bool b) { return t != b; }; // error ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 

Why does capturing the same variable cause 2 lambdas to have incompatible types?

+6
source share
1 answer

A lambda type is a "unique, non-unit class type" called a closure type. Each lambda is implemented as a different type, local to the declaration area, which has an overloaded operator () to call the function body.

Example : if you write this:

 auto a=[t](bool b){return t==b;}; auto b=[t](bool b){return t!=b;}; 

The compiler then compiles this (more or less):

 class unique_lambda_name_1 { bool t; public: unique_lambda_name_1(bool t_) t(_t) {} bool operator () (bool b) const { return t==b; } } a(t); class unique_lambda_name_2 { bool t; public: unique_lambda_name_2(bool t_) t(_t) {} bool operator () (bool b) const { return t!=b; } } b(t); 

a and b are of different types and cannot be used in the operator :.

However, in paragraph 5.1.2 (6) it is said that the type of closure of a lambda without capture has an implicit, public conversion operator that converts a lambda to a function pointer - non-blocking can be implemented as simple functions. Any lambda with the same arguments and return types can be converted to the same pointer type, and therefore the ternary?: Operator can be applied to them.

Example: non-capture lambda:

 auto c=[](bool b){return b;}; 

performed as follows:

 class unique_lambda_name_3 { static bool body(bool b) { return b; } public: bool operator () (bool b) const { return body(b); } operator decltype(&body) () const { return &body; } } c; 

which means this line:

 auto x = t?[](bool b){return b;}:[](bool b){return !b;}; 

actually means this:

 // a typedef to make this more readable typedef bool (*pfun_t)(bool); pfun_t x = t?((pfun_t)[](bool b){return b;}):(pfun_t)([](bool b){return !b;}); 
+12
source

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


All Articles