4.4 追踪返回类型

类别:库作者

4.4.1 追踪返回类型的引入

如我们在4.2节与4.3节中反复提到的,追踪返回类型配合auto与decltype会真正释放C++11中泛型编程的能力。

在C++98中,如果一个函数模板的返回类型依赖于实际的入口参数类型,那么该返回类型在模板实例化之前可能都无法确定,这样的话我们在定义该函数模板时就会遇到麻烦。可以回想一下代码清单4-9的例子,由于Sum模板函数的两个参数t1与t2的类型没有确定,所以我们只能简单地设置结果s为double类型并返回。这就限制了Sum的使用范围(大概只能用于数值不算太大的算术运算)。而在代码清单4-20中,我们改进了Sum模板函数,通过增加decltype(t1+t2)的参数的方式来返回泛型的值。这样做虽然扩大了Sum的适用范围,但改变了Sum的使用方式,在一些情况下,也是不可以接受的。而且由于程序员必须预先知道返回的类型,其使用上的灵活性也就打了一些折扣。

那么,最为直观的解决方式就是对返回类型进行类型推导。而最为直观的书写方式如下所示:


template<typename T1,typename T2>

decltype(t1+t2)Sum(T1&t1,T2&t2){

return t1+t2;

}


这样的写法虽然看似不错,不过对编译器来说有些小问题。编译器在推导decltype(t1+t2)时的,表达式中的t1和t2都未声明(虽然它们近在咫尺,编译器却只会从左往右地读入符号)。按照C/C++编译器的规则,变量使用前必须已经声明,因此,为了解决这个问题,C++11引入新语法——追踪返回类型,来声明和定义这样的函数。


template<typename T1,typename T2>

auto Sum(T1&t1,T2&t2)->decltype(t1+t2){

return t1+t2;

}


如上面的写法所示,我们把函数的返回值移至参数声明之后,复合符号->decltype(t1+t2)被称为追踪返回类型。而原本函数返回值的位置由auto关键字占据。这样,我们就可以让编译器来推导Sum函数模板的返回类型了。而auto占位符和->return_type也就是构成追踪返回类型函数的两个基本元素。