浅谈萃取技术
2016-04-24 21:23
309 查看
在STL中,以泛型技术为中心的设计贯穿着整个设计,模板类的运用,使得代码的复用率大大提高。萃取技术是在模板的基础上,采用相同的方式,却可以将不同的东西提取出来。
为什么要有萃取技术?
模板实现了程序的泛型化,但当有非模板类型传递时,我们就不能只套用模板,还需要对模板的参数进行加设。
代码中不同的参数调用不同的模板,编译器根据参数列表进行最优匹配。通过模板参数的推导机制,我们实现了指针所指不同的参数的类型。
但是,我们如果需要不同的返回值时,问题就出现了,同参不同返回值的模板在程序中是不能编译通过的(类似函数的重载,不同返回值的相同函数会导致二义性)。
解决这个问题可以对指向对象类型的制定一个别名。
通过typedef我们返回了ptr和iter两种不同的指针,但这个方法是有很大缺陷的。我们返回的指针都是定义的,但对于原生指针如int *,func是不能接受的。
template partial specialization 偏特化
偏特化的设计思想是加一个中间层,将智能指针和原生指针统统封装起来。
我们将int 型和 float 型分别封装,注意:封装的名字一样哦
这样我们只需调用input_type和result_type.就可以萃取出不同类型int ,float的函数返回值了。
总结下,我们之所以要萃取迭代器相关的类型,无非是要把迭代器相关的类型用于声明局部变量,用作函数的返回值等行为。对于原声指针和其他类型的指针,采用了模板偏特化技术对其的特殊处理,从而达到萃取的目的。
为什么要有萃取技术?
模板实现了程序的泛型化,但当有非模板类型传递时,我们就不能只套用模板,还需要对模板的参数进行加设。
template<class T1, class T2> class MyClass { public: MyClass() { cout<<"MyClass<T1, T2>"<<endl; } }; template<class T> class MyClass<T,T> { public: MyClass() { cout<<"MyClass<T,T>"<<endl; } }; template<class T> class MyClass<T*,T*> { public: MyClass() { cout<<"MyClass<T*,T*>"<<endl; } }; int main() { MyClass<int,int> mc; MyClass<int,double> mc1; MyClass<int*,int*>mc2; return 0; }
代码中不同的参数调用不同的模板,编译器根据参数列表进行最优匹配。通过模板参数的推导机制,我们实现了指针所指不同的参数的类型。
但是,我们如果需要不同的返回值时,问题就出现了,同参不同返回值的模板在程序中是不能编译通过的(类似函数的重载,不同返回值的相同函数会导致二义性)。
解决这个问题可以对指向对象类型的制定一个别名。
template <class T> class A { typedef T value_type; T *ptr; A(T *p = 0):ptr(p){} T& operator*()const {return *ptr;} }; template <class I> { typename I::value_type func(iter) {return *iter} };
通过typedef我们返回了ptr和iter两种不同的指针,但这个方法是有很大缺陷的。我们返回的指针都是定义的,但对于原生指针如int *,func是不能接受的。
template partial specialization 偏特化
偏特化的设计思想是加一个中间层,将智能指针和原生指针统统封装起来。
class CIntArray { public: CIntArray() { for(int i=0; i<10; ++i) { a[i] = i+1; } } int GetSum(int n) { int sum = 0; for(int i=0;i<10; ++i) { sum += a[i]; } return sum ; } private: int a[10]; }; class CFloatArray { public: CFloatArray() { for(int i=0; i<10; ++i) { f[i] = i+1.11f; } } float GetSum(float n) { float sum = 0.0f; for(int i=0;i<10; ++i) { sum += f[i]; } return sum ; } private: float f[10]; }; template<class T> class NumTraits {}; template<> class NumTraits<CIntArray> { public: typedef int result_type; typedef int input_type; }; template<> class NumTraits<CFloatArray> { public: typedef float result_type; typedef float input_type; }; template<class T> class CApply { public: typename NumTraits<T>::result_type GetSum(T &t, typename NumTraits<T>::input_type n ) { cout<<typeid(typename NumTraits<T>::result_type).name()<<endl; return t.GetSum(n); } };
我们将int 型和 float 型分别封装,注意:封装的名字一样哦
这样我们只需调用input_type和result_type.就可以萃取出不同类型int ,float的函数返回值了。
总结下,我们之所以要萃取迭代器相关的类型,无非是要把迭代器相关的类型用于声明局部变量,用作函数的返回值等行为。对于原声指针和其他类型的指针,采用了模板偏特化技术对其的特殊处理,从而达到萃取的目的。
相关文章推荐
- Android触摸事件分发机制详解
- 方便好使的java.util.Properties类
- Haproxy+Keepalived搭建Weblogic高可用负载均衡集群
- c++第四次实验
- window 2003 配置FTP +防火墙设置
- where T : class泛型类型约束
- 整数划分问题
- DayDayUP_linux运维学习_lrzsz安装过程
- opencv中打开摄像头显示黑屏
- word2013设置无格式粘贴快捷方式
- 个人报告06
- 20145331 《Java程序设计》第8周学习总结
- HTML中的表单
- HDOJ4277USACO ORZ【dfs+剪枝】
- R-CNN学习笔记
- org.apache.commons.dbutils学习总结(2)
- CI框架,多域名实现
- HTML
- 学习进度(第八周)
- LeetCode 171. Excel Sheet Column Number C语言