为什么在三元运算符的分支之间返回lambda会为某些lambda工作?

Mic*_*ang 5 c++ lambda

我想根据一些条件选择一个lambda,但是对于一些lambdas,编译器说lambdas的类型在三元运算符的分支之间不匹配.

以下代码编译:

int flag = 4;
auto result = flag % 2
    ? [](int x) {
        return x + x;
    }
    : [](int x) {
        return x * x;
    };
Run Code Online (Sandbox Code Playgroud)

但以下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;
    };
Run Code Online (Sandbox Code Playgroud)

分别导致以下错误:

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) {
         ^
Run Code Online (Sandbox Code Playgroud)

为什么最后2个片段无法编译?

Bau*_*gen 7

第一个代码段编译因为两个lambda都可以隐式转换为int(*)(int),所以编译器可以使用它作为?:表达式的类型,从而推导出类型result.

如果捕获列表非空(情况2),则不存在对指向函数的转换(N4141中的5.1.2/6),因此我们最终得到两个不相关的类型,没有共同的隐式转换目标作为第二个和operator?:不再推断出第三个操作数以及因此三元表达式的类型.

在第3种情况下,我们有一个通用的lambda,如果捕获列表为空,它有一个转换运算符,带有一个所谓的本发明模板参数列表,它定义了一组可能的转换.在我们这里的具体情况中,泛型lambda可以转换为T2(*)(T1),其中T1是为参数推导出的类型,并且T2是lambda推导的返回类型.长话短说:没有规则可以从该集合中选择"最佳转换",因此编译器也无法为我们的三元表达式推导出类型.