简体   繁体   English

为什么在三元运算符的分支之间返回lambda对于某些lambda起作用?

[英]Why does returning lambdas between branches of ternary operator work for some lambdas?

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. 我想根据某些条件选择一个lambda,但是对于某些lambda,编译器会说lambda的类型在三元运算符的分支之间不匹配。

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: 但以下2个摘要无法编译:

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 . 第一个代码段会进行编译,因为两个lambda都可以隐式转换为int(*)(int) ,因此编译器可以将其用作?:表达式的类型,从而推断出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. 如果捕获列表是非空的(情况2),则不存在对指针到函数的这种转换(N4141中的5.1.2 / 6),因此我们最终得到了两个不相关的类型,没有通用的隐式转换目标作为第二个类型。运算operator?:第三个操作数operator?:因此不再可以推导出三元表达式的类型。

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. 在情况3中,我们有一个通用的lambda,如果捕获列表为空,则它具有一个转换操作符,该操作符具有定义了一组可能转换的所谓的发明模板-参数-列表。 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. 在这里的特定情况下,通用lambda可转换为T2(*)(T1) ,其中T1是为参数推导的类型,而T2是lambda推导的返回类型。 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. 三元表达式类型是true和false分支的通用类型。 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. 但是两个不同的lambda具有不同的,不同的,不兼容的类型。 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. 但是,某些类型的lambda(非临时性,非模板性)可以转换为函数指针。 If you have two lambdas, convertible to same function ponter type, ternary operator deduces that pointer to be the common type. 如果您有两个可转换为相同功能ponter类型的lambda,则三元运算符会推导该指针为通用类型。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM