为什么对于具有多个 return 路径的 lambda returning lambda 会出现类型推导错误?

Why do I get a type deduction error for a lambda returning lambda with multiple return paths?

我有以下代码:

int main() {
    auto f = [] {
        if (1) return [] { return 1; };
        else return [] { return 2; };
    };
    return f()();
}

使用 GCC 5.2.1 会引发以下编译器错误:

error: inconsistent types ‘main()::<lambda()>::<lambda()>’ and 
       ‘main()::<lambda()>::<lambda()>’ deduced for lambda 
       return type else return [] { return 2; };

很明显这两种类型看起来是一样的,所以我不确定这是 GCC 的误导性错误消息还是它实际上是一个错误。据我所知,这应该编译; lambda return 类型应该推导为 std::function<int()>。有趣的是,如果我预先声明 lambda return 和 return 同一个变量两次,它就起作用了。

任何人都可以阐明正在发生的事情吗?我发现了类似的问题,其中许多问题归因于 GCC 错误,但这看起来不同。

Now obviously those two types are the same,

不,他们不是。每个 lambda 表达式的类型都是唯一的、不同的类型。

来自 [expr.prim.lambda]/3:

The type of the lambda-expression (which is also the type of the closure object) is a unique, unnamed non-union class type — called the closure type — whose properties are described below.

因此,return f 的类型推导失败 ,并且不会导致 std::function<int()>。后者是一个不相关的库类型,它不是任何闭包类型的 "common type"。

当然每个独特的闭包类型都可以转换std::function<int()>,所以如果你提供return类型,一切正常:

auto f = []() -> std::function<int()> {
    return 1 ? []() { return 1; }
             : []() { return 2; };
};

或者,作为一个简单的函数:

std::function<int()> f() {
    return 1 ? []() { return 1; }
             : []() { return 2; };
}

每个 lambda 都有自己独特的类型:

The lambda expression constructs an unnamed prvalue temporary object of unique unnamed non-union non-aggregate type[...].

来自here,强调我的。

此外,lambdas 与 std::function 无关,那是另一种不同的类型。特别是,

[] { return 1; }

[] { return 2; }

有不同的类型。这就是推导失败的原因。

这些类型相同。每个 lambda 都是一个唯一的、未命名类型的实例。 std::function 是一个模板,可以从适当的可调用对象(包括 lambda)隐式转换为模板,但 std::function 的实例化不是任何 lambda 的类型或父类型,因此无法推导它。

但是,您可以告诉编译器您希望它 return std::function 它会工作:

auto f = []() -> std::function<int()> {
    if (1) return [] { return 1; };
    else return [] { return 2; };
}