为什么对于具有多个 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; };
}
我有以下代码:
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; };
}