跳转至

返回类型后置

引言

考虑下面这个场景:

template<typename R, typename T, typename U>
R add(T t, U u) {
    return t+u;
}

int a = 1; float b = 2.0;
auto c = add<decltype(a+b)>(a,b);
我们并不关心a+b的类型是什么,因此,可以使用decltype来获得返回值类型。但这样有问题

  1. 这样使用很不方便
  2. 况且,你也不知道add内部具体做了什么操作,也不能确定类型就是decltype(a+b)这个吧

改进:在add函数中使用decltype

template<typename T, typename U>
decltype(t + u) add(T t, U u) {
    return t+u;
}
这样是编译不过的。tu在参数列表中,而C++的返回值是前置语法,在返回值定义的时候参数变量还不存在。

这样是对的

template<typename T, typename U>
decltype(T() + U()) add(T t, U u){
    return t+u;
}

考虑到TU可能是没有无参构造函数的类,所以正确的写法应该是这样

template<typename T, typename U>
decltype( (*(T*)0) + (*(U*)0) ) add(T t, U u) {
    return t+u;
}
虽然成功地使用decltype完成了返回值的推导,但写法过于晦涩,会加强使用难度并降低代码的可读性。

改进:auto+decltype(返回类型后置)

在C++11中增加了 返回类型后置(trailing-return-type,又称跟踪返回类型) 语法,将decltypeauto结合起来完成返回值类型的推导。

template<typename T, typename U>
auto add(T t, U u) -> decltype(t + u) {
    return t + u;
}

更复杂的例子

int& foo(int& i);
float foo(float& f);

template<typename T>
auto func(T& val) -> decltype(foo(val)) {
    return foo(val);
}
这个例子使用C++98/03就不可能完成了。

返回类型后置

返回值类型后置语法,是为了解决函数返回值类型依赖于参数而导致难以确定返回值类型的问题。

有了这个语法以后,对返回值类型的推导就可以用清晰的方式(直接通过参数做运算)描述出来,而不需要像C++98/03那样使用晦涩难懂的写法。

参考文章

  1. 参考书籍《深入应用C++11》