C++类型萃取

类型萃取

类型萃取指的是当泛型编程时,根据一个模板类(我这里就用类来说了,当然模板函数也可以)的模板类型,使用一个traits来获取其类型,获取其类型,通过类型调用不同的函数,比如拷贝函数 ,如果普通类型int、double之类的则调用较快的内存拷贝(memcpy),而需要申请空间的如string、vector等,则使用for循环赋值拷贝。

C++中为了提高代码执行的效率,往往即使需要增加代码的复杂程度,也在所不惜,《STL源码剖析》中称之为无所用其极,其中最典型的例子之一就是类型萃取。
C++类型萃取_第1张图片

为什么用类型萃取而不用偏特化

偏特化指的是对模板类(或模板函数)的针对某些类型特殊化,通过偏特化可以实现不同类型调用不同函数,同样可以达到int型拷贝时用memmove(或memcpy),用string等作为类型时拷贝用for循环赋值拷贝。

但是这里有个问题,类型那么多,我们每个都需要偏特化,如果一个函数代码是10行,偏特化这个函数,假如有10个类需要偏特化,那么我们就会有100行代码,而且不光有拷贝函数需要偏特化,很多功能函数都需要偏特化,如果有10个函数需要偏特化,那么1000行代码,量还是很大的。

类型萃取就不一样了,我们只需要萃取出类型,就能很轻松地调用对应函数。还是以拷贝函数为例,比如我们把所有类型分为两类,一类是__true_type则使用memcpy拷贝,一类是__false_type使用for循环赋值拷贝,对string类等一些类型则是不做特化处理,我们自己创建的类型也属于这一类型,进来则被判断为__false_type,对于另一类int、double、char一类的则做偏特化处理,处理成__true_type,这样我们的拷贝函数则只要分两种情况就能处理了。

类型萃取也用到了偏特化,但他对类型偏特化处理的代码(1个类型3行,10个类型30行)远远少于直接对函数偏特化(100行),减少了大量的冗余代码,而且也实现了不同类型不同处理方法,效率上有了明显提升,冗余代码量也减少,这种编程技巧,相比于直接偏特化好处太多了,何乐而不为?
C++类型萃取_第2张图片

代码

struct __true_type
{
	static bool get()
	{
		return true;
	}
};

struct __false_type
{
	static bool get()
	{
		return false;
	}
};

template <class T>
struct __my__type_traits
{
	typedef __false_type is_POD_type;
};

//对int进行偏特化萃取
template <>
struct __my__type_traits<int>
{
	typedef __true_type is_POD_type;
};

//对double进行偏特化萃取
template <>
struct __my__type_traits<double>
{
	typedef __true_type is_POD_type;
};

//先调类型萃取然后进行判断
template<class T>
T* __my_copy(T* dst, const T* src, size_t size)
{
	if (dst == src || dst == nullptr || src == nullptr)
		return dst;
	if (__my_type_traits<T>::is_POD_type::get() == true)
	{
		cout << typeid(T).name() << "copy by memcpy" << endl;
		memcpy(dst, src, sizeof(T) * size);
	}
	else
	{
		cout << typeid(T).name() << "copy by for" << endl;
		for (int i = 0; i < size; i++)
		{
			*(dst + i) = *(src + i);
		}
	}
	return dst;
}

template<class T>
T* __my_move(T* dst, const T* src, size_t size)
{
	if (dst == src || dst == nullptr || src == nullptr)
		return dst;
	if (__my_type_traits<T>::is_POD_type::get() == true)
	{
		memmove(dst, src, sizeof(T) * size);
	}
	else
	{
		if (src < dst && src + size > dst)
		{
			for (int i = 0; i < size; i++)
			{
				*(dst + size - i - 1) = *(src + size - i - 1);
			}
		}
		else
		{
			for (int i = 0; i < size; i++)
			{
				*(dst + i) = *(src + i);
			}
		}
	}
	return dst;
}

C++类型萃取_第3张图片

测试代码

测试一下上面类型萃取的拷贝管不管用

void test()
{
	string src_string[5] = { "1111", "2222", "3333", "4444", "5555" };
	string dst_string[5];
	cout << "test string copy" << endl;
	__my_copy(dst_string, src_string, 5);
	for (int i = 0; i < 5; i++)
		cout << dst_string[i] << endl;
	cout << endl;
	int src_int[5] = { 1,2,3,4,5 };
	int dst_int[5] = { 0 };
	cout << "test int copy" << endl;
	__my_copy(dst_int, src_int, 5);
	for (int i = 0; i < 5; i++)
		cout << dst_int[i] << endl;
}

C++类型萃取_第4张图片

你可能感兴趣的:(C++)