C++ 自动退货类型何时适用?

C++ 自动退货类型何时适用?,c++,c++14,C++,C++14,在c++1y中允许自动返回类型的规则是什么 #include <iostream> using namespace std; template<typename T1, typename T2> auto f(T1 const& a, T2 const &b) { if (a > b) return a-b; else return a+b; } int main() { cout << f(1, 2.) &

在c++1y中允许自动返回类型的规则是什么

#include <iostream>
using namespace std;

template<typename T1, typename T2>
auto f(T1 const& a, T2 const &b)
{
    if (a > b) return a-b;
    else return a+b;
}

int main() 
{
    cout << f(1, 2.) << endl;
    return 0;
}
#包括
使用名称空间std;
模板
自动f(T1常数和a、T2常数和b)
{
如果(a>b)返回a-b;
否则返回a+b;
}
int main()
{
库特
函数的圈复杂度有限制吗
身体

标准规定的内容(N3797,§7.1.6.4): 设
T
为变量的声明类型或 如果占位符是
auto
类型说明符,则 类型是使用模板参数推断规则确定的。如果 该扣减是针对
return
语句的,初始值设定项是 括号中的init list(8.5.4)表示程序格式不正确。否则, 通过将出现的
auto
替换为新代码,从
T
获取
P
发明类型模板参数
U
或者,如果初始值设定项是 带括号的init list,带有
std::initializer\u list
。为
U
使用从函数调用中推断模板参数的规则 (14.8.2.1),其中
P
为函数模板参数类型,且 初始值设定项是相应的参数。如果演绎失败,则 声明格式不正确。否则,为 通过将推导的
U
替换为
P

因此,tl;dr:返回类型是通过模板参数推断从
return
语句中的表达式推断出来的。有一个虚构的模板,它是用
return
语句中的表达式作为函数参数调用的,推断出的模板参数
U
将替换自动输入占位符返回类型。 现在,如果我们有多个return语句,会发生什么情况?简单:我们为每个
return
语句进行推断,并检查它们是否兼容:

如果函数的声明返回类型包含占位符 类型有多个
return
语句,返回类型为 每个
返回
语句。如果每个 从推论上看,该程序的格式不正确

因此,对于此代码:

template<typename T1, typename T2>
auto f(T1 const& a, T2 const &b)
{
    if (a > b) return a-b;
    else return a+b;
}
同样,如果推导出的
U
s不同,则代码格式不正确

如果您有无返回语句,则根据

如果函数的声明返回类型使用占位符类型 没有
return
语句,返回类型是从 一个
return
语句,在语句的右括号中没有操作数 功能体

递归 如果您想要递归函数,它会变得更加棘手:

auto f( int a, int b )
{
    return a? b + a : f(a-1, b); // This is ill-formed!
}
以下引文解释了该问题:

如果需要具有未减少占位符类型的实体类型 要确定表达式的类型,程序的格式不正确。 但是,一旦在函数中看到
return
语句,则 从该语句推导出的返回类型可用于 函数,包括在其他
return
语句中

所以我们写:

auto f( int a, int b )
{
    if( a )
        return b + a;

    return f(a-1, b);
}
结论:
您可以使用任意复杂的函数,只要
return
语句在演绎过程中都产生相同的类型,并且递归函数在一些非递归的
return
-语句之后具有递归调用。如果需要,可以进行强制转换以获得相同的类型。

简介

有几个简单的规则说明何时可以从函数体推断函数的返回类型,以及何时
auto
可作为返回类型应用

这些规则都在标准()[1]中进行了说明,每一条规则都列在本文剩余部分的相应部分中


[1] 在第7.1.6.4节中,自动说明符
[dcl.type.elab]


使用
auto
作为返回类型是否有无法推断的内容?

[dcl.type.elab]p1
如果演绎是针对
返回
语句的,并且初始值设定项是带括号的初始化列表(8.5.4),则程序格式错误



如果一个函数有多个返回语句,将推断出哪种类型?

[dcl.type.elab]p9
如果具有包含占位符类型的声明返回类型的函数具有多个返回语句,则会为每个返回语句推导返回类型。如果在每个推导中推导的类型不同,则程序的格式不正确



在推导返回类型之前,我可以使用该函数吗?

[dcl.type.elab]p11
如果需要具有未简化占位符类型的实体类型来确定表达式的类型,则程序的格式不正确。但是,一旦在函数中看到返回语句,则从该语句推导出的返回类型可用于函数的其余部分,包括其他返回语句

注意:我们不能将
junc
的地址记录在
foo
中,因为这样做需要了解
junc
的完整类型是什么,在我们提供了返回类型推导的定义之前,我们不知道这一点。(2)因此是合法的,而(1)是不合法的

注意:(3)也是格式不正确的,因为此时我们必须知道
递归
的返回类型,但它是未知的。但是,以相反的顺序使用返回语句是有效的。这样编译器就知道
递归
要重新编译
auto f( int a, int b )
{
    return a? b + a : f(a-1, b); // This is ill-formed!
}
auto f( int a, int b )
{
    if( a )
        return b + a;

    return f(a-1, b);
}
auto func () { return {1,2,3}; } // ill-formed
auto gunc_1 (bool val) { // (1), ill-formed
  if (val) return 123;
  else     return 3.14f;
}
auto gunc_2 (bool val) { // (2), legal
  if (val) return static_cast<float> (123);
  else     return 3.14f;
}
auto hunc () { } // legal, return-type is `void`
auto junc (); // declaration

void foo () { &junc; } // (1), ill-formed

auto junc () { // definition
   return 123;
}

void bar () { &junc; } // (2), legal
auto recursive (int x) {
  if (--x) return x + recursive (x); // (3), ill-formed
  else     return 0;
}