尾置返回类型
尾置返回类型(trailing return type)是C++11中新增的特性,任何函数的定义都可以使用尾置返回类型,但是尾置返回类型更适合用于返回类型比较复杂的场景,如返回一个数组指针。下面的例子是返回一个指向维度为10的数组指针的函数定义方法:
1 | int (*func(int i))[10] |
下面逐层理解上述例子的含义:
- func(int i)表示调用函数时,需要一个int类型的参数;
- (*func(int i))表示对调用func的结果执行解引用的操作;
- (*func(int i))[10]表示解引用之后得到一个维度为10的数组;
- int (*func(int i))[10]表示数组的数据类型为int;
若使用尾置返回类型,上述函数的定义可以写成:
1 | auto func(int i)->int (*)[10] |
使用尾置返回类型之后,函数的定义更加清晰易懂;同时注意到,尾置类型通常要和auto结合使用。
尾置lambda的返回类型
默认情况下,如果一个lambda中包含一个return之外的任何语句,编译器将假定此lambda的返回void。如下面的例子将vector中的负数转成正数:
1 | std::vector<int> v {1, -9, 8, -3, 5}; |
上面的例子可以正常编译通过,若修改成if/else的形式这编译无法通过:
1 | std::vector<int> v {1, -9, 8, -3, 5}; |
下面的这段描述来自 《C++ Primer》(第5版),我分别在gcc4.8.5和gcc5.4.0的环境上测试了,都无编译错误,也许高版本的编译器对此有优化。感谢boringcat的指正。
此时lambda表达式默认返回类型为void,而return了一个int,因此无法编译通过。上述的例子可以通过尾置返回类型来指定具体的返回类型,如:
1 | std::vector<int> v {1, -9, 8, -3, 5}; |
尾置模板的返回类型
模板函数定义和调用如下:
1 | template<typename R, typename T, typename U> |
问题:add函数的返回类型能否通过decltype获取呢?
1 | template<typename R, typename T, typename U> |
上述在使用decltype(t+u)时,t、u尚未定义,编译失败;
问题:能否通过decltype(T()+U())推导呢?不一定可以,因为T、U可能不包含无参数的构造函数。但可以按照下面方式修改:
decltype( (*(T*)0) + (*(U*)0) )
虽然上述方式可以解决问题,但是写法很晦涩,通过auto、decltype和尾置返回类型,可以清晰的写出上述的逻辑。
1 | template<typename R, typename T, typename U> |
一个函数wrapper
1 | int& func(int& i ); |
尾置返回类型和auto、decltype的结合,可以有效的解决函数返回类型依赖于参数推导来确定的问题。