`
tcspecial
  • 浏览: 896514 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

C++ 模板妙用

阅读更多

 

一. 模板全特化

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

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

 

 

 

 

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics