Trailing Return Type 后置返回类型
在C++中,尤其是使用模版的时候,经常会看到如下形式的代码
template <typename T>
auto add(T a, T b) -> T {
return a + b;
}
有些同学可能会对第二行中auto add(T a, T b) -> T {
的这个 ->
产生疑惑,这个是什么东西?
这里的 ->
是用来显式声明函数的返回类型。具体来说:
auto
的作用:在C++11及更高版本中,auto
可以用于函数返回类型,表示“自动推断返回类型”。但当返回类型依赖于模板参数时,直接使用auto
可能会导致编译器无法准确推断返回类型。->
的作用:通过->
,你可以显式地指定函数的返回类型,即使它依赖于模板参数。这种方式称为“后置返回类型”(trailing return type)。
引入背景
在C++11之前,函数的返回类型必须写在函数名之前,例如:
ReturnType functionName(Parameters);
然而,当返回类型依赖于模板参数时,这种写法可能会变得非常复杂,甚至无法直接表达。C++11引入了后置返回类型,允许将返回类型写在函数参数列表之后,使用 ->
来分隔。
语法
后置返回类型的语法如下:
auto functionName(Parameters) -> ReturnType;
auto
表示返回类型将在后面声明。->
是后置返回类型的分隔符。ReturnType
是函数的实际返回类型。
通过上述讲解大致应该看的懂啥意思了吧,其实就是一个函数的返回类型。有同学说,不对啊,为什么我们公司写的代码也是使用模版为什么没有使用后置返回类型?还有同学说,这个写法看起来很奇怪,更喜欢返回类型在函数名字前面。不用担心,在C++14中,如果函数的返回类型可以通过 auto
推导出来,那么可以省略后置返回类型,当然你要是喜欢带后置返回类型的写法c++14也支持的,所以上述代码可以用c++14书写成:
template <typename T>
auto add(T a, T b) { // 省略 -> 后置返回类型
return a + b;
}
如果函数的返回类型可以通过 auto
推导出来,那么可以省略后置返回类型,这句话一定要注意,还有很多是推导不出来的。限制如下:
c++14限制
- 存在多个不一致的
return
语句,也就是一个函数中多个return语句,但是返回类型不同,那么会编译错误。 - 依赖模板参数的返回类型,如果函数的返回类型依赖于模板参数的类型,而这些类型在函数体中才被确定,编译器可能无法推导出返回类型。
- 返回类型推导依赖于函数体中的复杂表达式,如果
return
语句中的表达式非常复杂,或者依赖于其他函数的返回类型推导,编译器可能无法推导出返回类型 - 返回类型推导依赖于
decltype
或std::declval
,如果return
语句中的表达式使用了decltype
或std::declval
,编译器可能无法推导出返回类型,特别是在涉及未完全定义的类型或模板参数时 - 返回类型推导依赖于未完全定义的类型
后续版本虽然也大大增加了auto的推导能力,但是依旧无法推导全部,所以在写模版函数的时候,最好写->
,同时也需要注意,使用后置返回类型的时候函数名前面必须加上auto,官方原文:
Trailing return type declaration. The decl-specifier-seq in this case must contain the keyword auto.