C++ 模板妙用
程序员文章站
2022-05-27 22:40:18
...
一. 模板全特化
有时当通用模板无法处理特定类型,需要对模板参数进行特殊处理,即为特化。
// 通用模板 template<class T> struct A { int x; }; // 特化T=double,模板为空 template<> struct A<double> { int y; };
模板偏特化,即对模板部分参数进行特化。
// 通用模板 template<class T, class P> void foo(T t, P p){} // 偏特化,第二个参数指定int template<class T> void foo(T t, int p)
二. 类型过滤
实现接口只支持某些类型参数,可很简单通过模板特化实现。
// 未实现 template<class T> struct Support; // 特化int template<> struct Support<int>{}; // 调用 Support<int> a; // ok Support<char> b; // error
三. 类型萃取
重构旧系统时,发现某个函数有多个冗余实现,只是参数类型不同,可考虑用模板进行提炼。
// 原有代码 void foo(int); void foo(A const&); // 模板层 template<class T> void foo(T const&);
调用:foo(1) 时会编译出错,因为该模板无法处理传值类型。如何用一个模板函数同时支持传值或引用方式呢?
这就要用到Type Traits技术了,简言之提取“被传进的对象”对应的返回类型,让同一个接口实现对应的功能。
// 主版本 template<class T> struct TypeMapping { typedef T const &type; }; // 特化类型 template<> struct TypeMapping<int> { typedef int type; }; // 接口层 template<class T> void foo(TypeMapping<T>::type v) { }
四. 插入继承链
已知类继承关系:
A --> A1 --> B
A --> A2 --> C
A/B/C类均实现了foo()虚函数,现要为B和C的foo()添加一段相同的功能。在不修改父类A1、A2的前提下,如何实现?
我们可通过插入模板层来实现,该技巧也常用来模拟虚函数调用(虚函数调用会查询虚表,有性能损耗)。
// 模板层 template<class Base> class X : public Base { virtual void foo() { xxx; // 新增功能代码 Base::foo(); } }; // B继承模板 class B: public X<A1> { typedef X<A1> base_class; virtual void foo() { xxx; base_class::foo(); } }; // C继承模板 class C: public X<A2> { typedef X<A2> base_class; virtual void foo() { xxx; base_class::foo(); } };
B/C只需要继承同一个模板层,常用来对库进行封装。
上一篇: c++11 chrono
下一篇: std::move与forward