You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何编译器无法推导两个同类型lambda对应的std::optional为同一类型?

为何编译器无法推导两个同类型lambda对应的std::optional为同一类型?

咱们先看你遇到的问题场景,这段代码看起来逻辑没问题,但编译器就是抛出了错误:

void func(std::optional<std::function<void(int, int)>> arg1)
{
    return;
}

void callee(bool flag)
{
    auto arg1 = [](int a1)
    {
        return;
    };

    auto arg2 = [](int a1)
    {
        return;
    };

    func(
        (!flag ? std::optional{arg2} : (flag ? std::optional{arg1} : std::nullopt)),
        std::optional{arg2});
}

int main(int argc, char **argv) {
    callee(true);
}

编译器给出的错误提示是:

error: operands to '?:' have different types 'std::optional<callee(bool)::<lambda(int)> >' and 'std::optional<callee(bool)::<lambda(int)> >'

是不是特别困惑?明明两个lambda的代码完全一样,怎么对应的std::optional类型会被判定为不同?

其实核心原因很关键:每个lambda表达式都是编译器生成的独一无二的匿名类型——哪怕它们的参数列表、代码逻辑、返回值完全一致,编译器也会为每一个lambda创建一个独立的、互不相干的类型。

所以你的arg1和arg2本质上是两种不同的类型(虽然编译器报错信息里写的名字看起来一模一样,但实际是两个完全不同的匿名类型),对应的std::optional{arg1}和std::optional{arg2}就是std::optional<LambdaType1>和std::optional<LambdaType2>这两种毫无关联的类型。而三目运算符?:要求两个分支的类型必须一致,或者至少能隐式转换成同一个类型,这俩类型之间没有任何转换关系,编译器自然就报错了。

那为什么显式指定类型就能解决问题呢?比如你把arg1和arg2的类型改成std::function<void(int)>而非用auto:

std::function<void(int)> arg1 = [](int a1) { return; };
std::function<void(int)> arg2 = [](int a1) { return; };

这时候两个lambda都会被隐式转换成同一个std::function<void(int)>类型,对应的std::optional{arg1}和std::optional{arg2}就都是std::optional<std::function<void(int)>>,类型完全一致,三目运算符也就可以正常工作了。

备注:内容来源于stack exchange,提问作者Tyler Kelly

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.22 14:55:30