I wanted to create a lambda in the following way:
auto l1 = condition ?
[](){ return true; } :
[number](){ return number == 123; };
However, I got error:
operands to ?: have different types ‘main()::<lambda()>’ and ‘main()::<lambda()>’
Obviously, the types seem to be the same. I thought, that capturing number
in only one of lambdas might be a problem, but I get the same error for these:
//check if capturing number in both lambdas would help
auto l2 = condition ?
[number](){ return true; } :
[number](){ return number == 123; };
//maybe the first lambda capture was optimised out? let's make sure:
auto l3 = condition ?
[number](){ return number != 123; } :
[number](){ return number == 123; };
I'm aware I can do it other way (below), but I'm wondering what is the cause of this behavior. It was compiled with GCC6.3.1, C++14 enabled.
//compiles
auto l4 = condition ?
[](const int){ return true; } :
[](const int number){ return number == 123; };
If you really want to use the conditional operator you can do it like this:
In C++17 this can be simplified thanks to Class template argument deduction:
A lambda in C++ is an instance of local class implementing functor contract. I mean, operator() etc. And these classes are unrelated and have different types.
Your code is equivalent to
Every lambda expression has unique type (i.e. the closure type, which is a unique unnamed non-union non-aggregate class type), even with the same signature and function body; the compiler just can't deduce the common type of ternary conditional operator for the variable declared by
auto
, the two closure types are irrelevant at all.You can use
std::function
instead. e.g.For
l4
, note that the lambda-expression with empty capture list could be converted to the corresponding function pointer implicitly. In this case both of them could be converted to the same function pointer type (i.e.bool(*)(int)
), which then could be deduced as the common type of ternary conditional operator and the type ofl4
.