一个 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 使用模板类型推导 - 在调用函数模板时使用相同,这意味着它会剥离 &amp; 之类的装饰 - 参考。 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 的返回类型可以通过返回值来推断,那么为啥不能是一个函数呢?的主要内容,如果未能解决你的问题,请参考以下文章

lambdas了解

仅对lambda表达式的隐式类型推断?为什么?困惑!

C# 10 Lambda 语法的改进

KotlinKotlin 函数总结 ( 具名函数 | 匿名函数 | Lambda 表达式 | 闭包 | 内联函数 | 函数引用 )

KotlinKotlin 函数总结 ( 具名函数 | 匿名函数 | Lambda 表达式 | 闭包 | 内联函数 | 函数引用 )

请教关于java的泛型方法