一个 lambda 的返回类型可以通过返回值来推断,那么为啥不能是一个函数呢?
Posted
技术标签:
【中文标题】一个 lambda 的返回类型可以通过返回值来推断,那么为啥不能是一个函数呢?【英文标题】:A lambda's return type can be deduced by the return value, so why can't a function's?一个 lambda 的返回类型可以通过返回值来推断,那么为什么不能是一个函数呢? 【发布时间】:2013-12-20 11:16:13 【问题描述】:#include <iostream>
int main()
auto lambda = []
return 7;
;
std::cout << lambda() << '\n';
这个程序编译并打印 7. lambda 的返回类型根据返回值 7 推导出为整数类型。
为什么普通函数不能做到这一点?
#include <iostream>
auto function()
return 42;
int main()
std::cout << function() << '\n';
错误:‘function’函数使用‘auto’类型说明符,没有尾随返回类型
【问题讨论】:
已经在 VS2013 Nov CTP 中可用。这是一个 C++14 特性已经可用。对于返回类型混乱的模板化函数来说,这是一个很棒的帮助。 【参考方案1】:C++14 has this feature。您可以通过设置-std=c++1y
标志使用新版本的 GCC 或 clang 对其进行测试。
Live example
除此之外,在 C++14 中,您还可以使用 decltype(auto)
(将 decltype(auto)
作为变量的镜像)为您的函数使用 decltype
语义推断其返回值。
一个例子是转发功能,decltype(auto)
对此特别有用:
template<typename function_type, typename... arg_types>
decltype(auto) do_nothing_but_forward(function_type func, arg_types&&... args)
return func(std::forward<arg_types>(args)...);
通过使用decltype(auto)
,您可以在使用指定参数调用时模拟func
的实际返回类型。尾随返回类型中不再有重复代码,这在 C++11 中非常令人沮丧且容易出错。
【讨论】:
为什么是decltype(auto)
而不仅仅是auto
?
@dashesy auto
使用模板类型推导 - 在调用函数模板时使用相同,这意味着它会剥离 &
之类的装饰 - 参考。 decltype(auto)
- 使用 decltype 规则进行类型推导 - 这意味着它推断出与传递给它的表达式相同的类型。【参考方案2】:
这只是语言创建和发展方式的限制。在即将到来的 C++14 标准中,函数的返回类型可以在某些上下文中推导出来,尽管不是全部。有多个 return 语句时会出现复杂情况。
另外,推导返回类型还有其他问题,例如模板函数的返回类型不能在SFINAE上下文中使用,为了能够推导类型,编译器必须实例化函数模板,这发生在 替换之后。最终结果是,虽然该功能将在不久的将来出现,但如果您可以自己提供类型,我会避免使用它。
【讨论】:
“这只是语言创建和发展方式的限制。” - 当然是,仅此一项就 +1。【参考方案3】:这是在 c++14 中出现的。请参阅以下proposal。
【讨论】:
【参考方案4】:它还没有……它会在 C++1y/C++14 中……看看这个link of feature
【讨论】:
【参考方案5】:我的猜测是,这可能是因为类型推断的 lambdas 不能递归。
为什么这很重要?因为如果类型推断的 lambda 可以是递归的(通过“类型推断”,我的意思是变量名称的类型为 auto
),那么它的返回类型可能取决于自身——虽然这有时可以解决,它比“简单”类型推断更难实现。我什至不确定它是否总是可解决(在一般情况下是否可以确定?)。但是,如果函数支持类型推断,则必须注意这个问题,因此很可能他们只是出于这个原因将它们排除在外。
【讨论】:
你能解释更多吗? 这不是 lambda 和函数定义之间的区别。即使是普通对象也可以指定循环依赖,auto x = x * 2;
。在所有情况下,它都是被禁止的。
@Mehrdad 这是被禁止的。与自引用 lambda 相同。这就是我的观点。
Lambda 和函数允许递归,变量初始化允许自引用,但如果存在循环依赖,auto
格式不正确。
您在此答案中的断言是递归可能会与auto
一起造成问题。我的回答是,这是真的,但他们已经通过简单地禁止你做错事来解决问题。函数没有理由与 lambda 不同,而在 C++14 中则不会。以上是关于一个 lambda 的返回类型可以通过返回值来推断,那么为啥不能是一个函数呢?的主要内容,如果未能解决你的问题,请参考以下文章
KotlinKotlin 函数总结 ( 具名函数 | 匿名函数 | Lambda 表达式 | 闭包 | 内联函数 | 函数引用 )
KotlinKotlin 函数总结 ( 具名函数 | 匿名函数 | Lambda 表达式 | 闭包 | 内联函数 | 函数引用 )