Traits编程技法之type_trait

STL对于性能的要求非常的严格,任何一点无意义的操作都会严重影响其中容器或算法的性能,即使只是一条语句。在高频率的使用下,这种浪费将会无限扩大。type_traits的作用之一就是提高性能。

当我们在进行对象的析构(destroy)操作时,如果对象为内置对象(如int,char,float,pointer)或其数据成员包含内置对象,因为其析构操作由编译器内置执行,所以我们对其进行析构函数的调用是毫无意义的。

试想,我们创造一个容器,其中包含的对象皆是内置类型的对象,若我们对如此多的对象逐一调用一个无关痛痒的destroy操作,那此容器的效率将会大大降低。

所以我们需要一种手段,将那些有着无意义析构函数(trivial destructor)的类型挑选出来进行特殊处理:他们的析构操作我们什么也不需要做,交由编译器处理吧。这种手段就是type_traits,其将所有对象类型分为两类,一种的析构函数有意义,另一种的析构函数没有意义。这样我们就能分门别类的析构他们。

下面我们一起探讨下如何实现type_traits。

首先我们需要的是一个可以在函数间传递的"信息"。这个信息应该准确告诉我们,我们应该调用析构操作的哪个重载版本。众所周知,在函数间传递信息的方式有两种:参数或返回值。最简单直接的方式就是参数传递。但传递参数实质是对象或对象的拷贝的传递,所以,我们先创建两个对象,这两个对象什么也不干,唯一的作用就是帮助我们区分,待析构对象到底属于两类中的哪一类。

这两个对象长这样:

struct _true_type{};//无意义的析构函数
struct _false_type{};//有意义的析构函数
说什么也不干,就什么也不干!这两个对象里什么也没有,即使频繁的作为参数传递也不会引起太多浪费(比起大量无意义的析构函数来说确实是九牛一毛)。

那我们如何利用这两个对象呢?

这时我们就需要利用模板特例化来分而治之:

我们先创建一个基础类模板,先将所有类型都标为_false_type:

template
struct type_traits
{

	typedef _false_type has_trivial_default_constructor;//默认构造函数是否有意义?
	typedef _false_type has_trivial_copy_constructor;//拷贝构造函数是否有意义?
	typedef _false_type has_trivial_assgignment_constructor;//拷贝赋值操作是否有意义?
	typedef _false_type has_trivial_destructor;//析构函数是否有意义?
	/*POD意指Plain Old Data,也就是标量型别或传统的C struct(传统的C struct只能
	包含数据成员,不能包含函数成员。也就是所谓的聚合类。POD型别必然包含无意义
	的ctor/dtor/copy/assignment函数。
	*/
	typedef _false_type is_POD_type;//是否为Plain Old Data?
};

然后,我们再为每个内置类型对象实现其特例化:


#ifndef _STL_TEMPLATE_NULL
#define _STL_TEMPLATE_NULL template<>
#endif
_STL_TEMPLATE_NULL
struct type_traits 
{
	typedef _true_type has_trivial_default_constructor;
	typedef _true_type has_trivial_copy_constructor;
	typedef _true_type has_trivial_assgignment_constructor;
	typedef _true_type has_trivial_destructor;
	typedef _true_type is_POD_type;
};

_STL_TEMPLATE_NULL
struct type_traits 
{
	typedef _true_type has_trivial_default_constructor;
	typedef _true_type has_trivial_copy_constructor;
	typedef _true_type has_trivial_assgignment_constructor;
	typedef _true_type has_trivial_destructor;
	typedef _true_type is_POD_type;
};
_STL_TEMPLATE_NULL
struct type_traits 
{
	typedef _true_type has_trivial_default_constructor;
	typedef _true_type has_trivial_copy_constructor;
	typedef _true_type has_trivial_assgignment_constructor;
	typedef _true_type has_trivial_destructor;
	typedef _true_type is_POD_type;
};
_STL_TEMPLATE_NULL
struct type_traits 
{
	typedef _true_type has_trivial_default_constructor;
	typedef _true_type has_trivial_copy_constructor;
	typedef _true_type has_trivial_assgignment_constructor;
	typedef _true_type has_trivial_destructor;
	typedef _true_type is_POD_type;
};
_STL_TEMPLATE_NULL
struct type_traits 
{
	typedef _true_type has_trivial_default_constructor;
	typedef _true_type has_trivial_copy_constructor;
	typedef _true_type has_trivial_assgignment_constructor;
	typedef _true_type has_trivial_destructor;
	typedef _true_type is_POD_type;
};
_STL_TEMPLATE_NULL
struct type_traits 
{
	typedef _true_type has_trivial_default_constructor;
	typedef _true_type has_trivial_copy_constructor;
	typedef _true_type has_trivial_assgignment_constructor;
	typedef _true_type has_trivial_destructor;
	typedef _true_type is_POD_type;
};
_STL_TEMPLATE_NULL
struct type_traits 
{
	typedef _true_type has_trivial_default_constructor;
	typedef _true_type has_trivial_copy_constructor;
	typedef _true_type has_trivial_assgignment_constructor;
	typedef _true_type has_trivial_destructor;
	typedef _true_type is_POD_type;
};
_STL_TEMPLATE_NULL
struct type_traits 
{
	typedef _true_type has_trivial_default_constructor;
	typedef _true_type has_trivial_copy_constructor;
	typedef _true_type has_trivial_assgignment_constructor;
	typedef _true_type has_trivial_destructor;
	typedef _true_type is_POD_type;
};
_STL_TEMPLATE_NULL
struct type_traits 
{
	typedef _true_type has_trivial_default_constructor;
	typedef _true_type has_trivial_copy_constructor;
	typedef _true_type has_trivial_assgignment_constructor;
	typedef _true_type has_trivial_destructor;
	typedef _true_type is_POD_type;
};
_STL_TEMPLATE_NULL
struct type_traits 
{
	typedef _true_type has_trivial_default_constructor;
	typedef _true_type has_trivial_copy_constructor;
	typedef _true_type has_trivial_assgignment_constructor;
	typedef _true_type has_trivial_destructor;
	typedef _true_type is_POD_type;
};
template
struct type_traits 
{
	typedef _true_type has_trivial_default_constructor;
	typedef _true_type has_trivial_copy_constructor;
	typedef _true_type has_trivial_assgignment_constructor;
	typedef _true_type has_trivial_destructor;
	typedef _true_type is_POD_type;
};

当我们使用他们,例如进行析构操作时,我们可以实现两个重载函数,用_true_type对象或_false_type对象来区分他们:

void _destroy(Iterator first, T value)
{
	typedef typename type_traits::has_trivial_destructor trivial_destructor;
	_destroy_aux(first, trivial_destructor());
}
template
void _destroy_aux(Iterator first, _false_type)
{
	destroy_main(&*first);//有意义的析构函数,析构他!
}
template
void _destroy_aux(Iterator first, _true_type){}//无意义的析构函数,那就不管我的事咯~

有了_type_traits后,我们就可以实现更有效率的拷贝、赋值、析构操作了!

你可能感兴趣的:(STL源码)