欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

C++ 模板妙用

程序员文章站 2022-05-21 08:02:10
...

 

一. 模板全特化

有时当通用模板无法处理特定类型,需要对模板参数进行特殊处理,即为特化。

// 通用模板
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只需要继承同一个模板层,常用来对库进行封装。

 

 

 

 

 

相关标签: 模板 类型萃取