I want to choose a lambda depending on some conditional, but the compiler, for some lambdas, says that the types of the lambdas do not match between the branches of the ternary operator.
The following code compiles:
int flag = 4;
auto result = flag % 2
? [](int x) {
return x + x;
}
: [](int x) {
return x * x;
};
but the following 2 snippets do not compile:
int flag = 4;
auto result = flag % 2
? [flag](int x) {
return x + flag;
}
: [flag](int x) {
return x - flag;
};
auto result2 = flag % 2
? [](auto x) {
return x + x;
}
: [](auto x) {
return x * x;
};
resulting in the following errors respectively:
test.cpp: In function 'auto f(int)':
test.cpp:8:9: error: operands to ?: have different types 'f(int)::<lambda(int)>' and 'f(int)::<lambda(int)>'
? [flag](int x) {
test.cpp: In function 'auto f(int)':
test.cpp:10:9: error: operands to ?: have different types 'f(int)::<lambda(auto:1)>' and 'f(int)::<lambda(auto:2)>'
? [](auto x) {
^
Why do the last 2 snippets not compile?
The first snippet compiles because both lambdas are implicitly convertible to int(*)(int)
, so the compiler can use that as the type of the ?:
expression and thus to deduce the type of result
.
If the capture list is non-empty (case 2) no such conversion to pointer-to-function exists (5.1.2/6 in N4141), so we end up with two unrelated types with no common implicit conversion target as the 2nd and 3rd operand of operator?:
and thus the type of the ternary expression can no longer be deduced.
In case 3 we have a generic lambda, which, if the capture list is empty, has a conversion operator with a so called invented template-parameter-list which defines a set possible conversions. In our specific case here, the generic lambdas are convertible to T2(*)(T1)
, where T1
is the type deduced for the argument and T2
is lambda's deduced return type. Long story short: There is no rule to pick a "best conversion" from that set, so again, the compiler cannot deduce a type for our ternary expression.
Ternary Expression type is a common type for both true and false branch. Operator tries to find this type by trying to convert both branches, using complicated rules. But two different lambdas have different, distinct, non-compatible types. Generally, they are not convertible to each other, so you got an erron for your second and third try.
However, certain kind of lambdas (non-campuring, non-templated) can be converted to function pointer. If you have two lambdas, convertible to same function ponter type, ternary operator deduces that pointer to be the common type.
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