【问题标题】: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 特性已经可用。对于返回类型混乱的模板化函数来说,这是一个很棒的帮助。

标签: c++ function c++11 lambda auto


【解决方案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 中则不会。
      猜你喜欢
      • 2021-07-17
      • 1970-01-01
      • 2020-10-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-06-27
      • 2014-11-22
      相关资源
      最近更新 更多