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; };
It is also called a Ternary operator because it has three operands such as boolean condition, first expression, and second expression. We can also write a conditional expression in lambda expression in the below program.
Creating a Lambda Expression in C++auto greet = []() { // lambda function body }; Here, [] is called the lambda introducer which denotes the start of the lambda expression. () is called the parameter list which is similar to the () operator of a normal function.
The [=] you're referring to is part of the capture list for the lambda expression. This tells C++ that the code inside the lambda expression is initialized so that the lambda gets a copy of all the local variables it uses when it's created.
The lambda is capturing an outside variable. A lambda is a syntax for creating a class. Capturing a variable means that variable is passed to the constructor for that class. A lambda can specify whether it's passed by reference or by value.
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.
std::function<bool()> l1; if (condition) l1 = [](){ return true; }; else l1 = [number](){ return number == 123; };
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 of l4
.
If you really want to use the conditional operator you can do it like this:
auto l1 = condition ? std::function<bool()>{[](){ return true; }} : std::function<bool()>{[number](){ return number == 123; }};
In C++17 this can be simplified thanks to Class template argument deduction:
auto l1 = condition ? std::function{[](){ return true; }} : std::function{[number](){ return number == 123; }};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With