Lambda的返回类型可以通过返回值来推断,那么为什么函数不能呢?


75
#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';
}

错误:“函数”函数使用“自动”类型说明符,而没有尾随返回类型


5
在VS2013 Nov CTP中已经可用。这是已经可用的C ++ 14功能。对于具有混乱返回类型的模板化函数,这是一个了不起的帮助。
CodeAngry 2013年

Answers:


77

C ++ 14具有此功能。您可以通过设置-std=c++1y标志,使用新版本的GCC或clang进行测试。

现场例子

除此之外,在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中非常令人沮丧且容易出错。


3
为什么decltype(auto)而不仅仅是auto
2016年

25

这仅是语言创建和发展方式的限制。在即将到来的C ++ 14标准中,可以在某些情况下推断出函数的返回类型,尽管并非全部。当有多个return语句时,会很复杂。

此外,推导的返回类型还有其他问题,例如,模板函数的返回类型不能在SFINAE上下文中使用,因为要能够推导该类型,编译器必须实例化函数模板,该模板替换发生。最终结果是,尽管该功能将在不久的将来推出,但如果您可以自己提供该类型,我会避免使用它。


5
“这只是该语言的创建和发展的局限性。” -当然是,仅此一项即可。
Christian Rau

10

这是c ++ 14中的版本。请参阅以下建议



5

我的猜测是,这可能是因为类型推断的lambda不能递归

为什么这么重要?因为如果类型推断的lambda可以递归(通过“类型推断”,我的意思是变量的名称为type auto),则其返回类型可能会依赖于自身-尽管有时可以解决,但它可能比“简单”类型推断更难实现。我什至不确定它是否总是可以解决的(一般情况下可以决定吗?)。但是,如果函数支持类型推断,则必须解决此问题,因此很可能由于这个原因它们只是将它们排除在外。


1
你能解释更多吗?
布赖恩·陈

1
这不是lambda和函数定义之间的区别。甚至普通对象也可以指定循环依赖性auto x = x * 2;。在所有情况下,都完全禁止这样做。
Potatoswatter 2013年

1
@Mehrdad禁止。与自指代lambda相同。这就是我的意思。
Potatoswatter

2
Lambda和函数可以递归,变量初始化可以是自引用的,但是auto如果存在循环依赖关系,则格式不正确。
Potatoswatter 2013年

2
您在此答案中的断言是,与结合使用时,递归可能会带来问题auto。我的回答是正确的,但是他们已经通过简单地禁止您做错事情来解决了这个问题。没有理由应该使函数与lambda有所不同,在C ++ 14中它们也不会有所不同。
Potatoswatter 2013年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.