第3课 类型推导_追踪返回类型
Posted 浅墨浓香
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了第3课 类型推导_追踪返回类型相关的知识,希望对你有一定的参考价值。
1. 追踪返回类型的引入
(1)经典问题:泛型编程中的返回值类型(被迫引入了返回值类型R作为模板参数)
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); //不能自动推导函数的返回值。为了获得返回值的类型,该函数的使用者需要知道add函数的内部实现(如:a+b)
(2)decltype的尴尬
template<typename R, typename T, typename U> decltype(t + u) add(T t, U u) //编译出错,因为编译器是从左向右读入符号,而返回值是前置语法,定义返回值时t、u参数尚未定义。 { return t + u; }
(3)不完美的解决方案——写法过于晦涩难懂。
template<typename R, typename T, typename U> decltype((*(T*)0) + (*(U*)0)) add(T t, U u) //技巧:利用0地址进行类型转换 { return t + u; }
2. 返回类型后置(trailing-return-type, 又称为追踪返回类型)
(1)利用追踪返回类型声明进行的等价函数声明
①函数指针的等价:如,auto (*fp)() -> int 与int (*fp)()的等价;
②函数引用的等价:如,auto (&fr)() -> int 与 int (&fr)()的等价
(2)利用auto + decltype的结合进行追踪返回类型
template<typename R, typename T, typename U> auto add(T t, U u) -> decltype(t + u) //返回类型后置 { return t + u; }
【实例分析】使用追踪返回类型的函数
//3.1.cpp
#include <iostream> using namespace std; //1. 追踪返回值类型 template<typename T1, typename T2> auto Add(const T1& t1, const T2& t2) ->decltype(t1 + t2) { return t1 + t2; } template<typename T1, typename T2> auto Mul(const T1& t1, const T2& t2) ->decltype(t1 * t2) { return t1 * t2; } //2. 晦涩的面试题 int (*(*pf())())(){ return nullptr; } //pf1是个函数,无参,返回值类型是auto(*)() ->int (*)() //而auto(*)() ->int (*)表示是一个函数指针(具体类型可按同样的 //方法从右向左解析出来) auto pf1() -> auto(*)() -> int (*)(){ return nullptr; } //函数转发 double foo(int a){ return (double)a + 0.1; } int foo(double b){ return (int)b; } template<typename T> auto Forward(T t) -> decltype(foo(t)){ //根据实际调用的foo(t)追踪其返回值类型 return foo(t); } int main() { //////////////////////////////////////////////////// //1. 追踪返回值类型(该例比较特殊,没有指明任何的具体类型) // 更像是动态类型语言的代码,而不像严格静态类型的C++代码 auto a = 3; auto b = 4L; auto pi = 3.14; auto c = Mul(Add(a, b), pi); cout << c << endl; //21.98 //////////////////////////////////////////////////// //2. 简化函数定义 cout << is_same<decltype(pf), decltype(pf1)>::value<< endl; //1,pf和pf1函数的类型完全相同! //3. 转发函数 cout << foo(2) << endl; cout << foo(0.5) << endl; cout << Forward(2) << endl; cout << Forward(0.5) << endl; return 0; }
以上是关于第3课 类型推导_追踪返回类型的主要内容,如果未能解决你的问题,请参考以下文章