模板的特化和萃取

模板的特化可以分为全特化和偏特化,全特化是全部参数进行特化,但是偏特化的话是部分参数,或者某些模板参数的进一步限制。

首先来看模板全特化的例子:

#include<iostream>
using namespace std;
template <class T>
class Seqlist
{
public:
	Seqlist()
	{
		cout << "Seqlist<T>->memcpy" << endl;
	}
};
template<>
class Seqlist<string>
{
public:
	Seqlist()
	{
		cout << "Seqlist<string>->for()" << endl;
	}
};
int main()
{
	Seqlist<int>s1;
	Seqlist<string>s2;
	return 0;
}

其输出结果为:

写一个偏特化的例子:

#include<iostream>
using namespace std;
template < class T1, class T2>
class Data
{
public:
	Data()
	{
		cout << "Data<T1,T2>" << endl;
	}
protected:
	T1 a1;
	T2 a2;
};
template<class T2>
class Data<int, T2>
{
public:
	Data()
	{
		cout << "Data<int,T2>" << endl;
	}
protected:
	int a1;
	T2 a2;
};
我们了解了全特化和偏特化,来看看特化的作用,来看下面的例子:

#include<iostream>
using namespace std;
template<class T>
T* Copy(T* dst, T* src, size_t n)
{
	return (T*)memcpy(dst,src, sizeof(T)*n);
}
int main()
{
	int a1[5] = { 1, 2, 3 };
	int a2[5] = { 0 };
 	Copy(a2, a1, 5);//把a1中的值拷贝到a2中,拷了10个对象
	string s1[5] = { "10", "20", "30" };
	string s2[5] = {};
	Copy(s2, s1, 5);
	return 0;
}
我们打开监视可以看到:

但是上面这个程序会出现错误,比如把string中s1“10”改为“11111111111111111111111111”程序就会出现崩溃,因为此时拷贝为浅拷贝,而当s1当中的字符串比较短时就存在于s1中的buffer中,但是当字符串比较长时,该字符串不存在于buffer中,而是在堆上动态开辟了一段空间,当析构时会把这段空间析构两次,所以就会出现错误,而为了避免这种错误我们可以特例话string,并且为它单独写一份析构函数,而另一种简单的方法就是进行萃取,其实萃取就是特化,萃取的目的就是为了提高效率。

创建一个萃取的头文件:

struct _TrueType
{};
struct _FalseType
{};
template<class T>
struct TypeTraits
{
	//内嵌定义类型(在类中定义类)
	//POD:plain old data,平凡类型
	typedef _FalseType IsPodType;
};
template<>
struct TypeTraits<int>
{
	//内嵌定义类型(在类中定义类)
	//POD:plain old data,平凡类型
	typedef _TrueType IsPodType;
};
然后在元文件中:

#include<iostream>
#include"TypeTraits.h"
using namespace std;
template<class T>
T* _Copy(T* dst, T* src, size_t n,_TrueType)
{
	return (T*)memcpy(dst,src, sizeof(T)*n);//如果是内置类型就调用memcpy
}
template<class T>
T* _Copy(T* dst, T* src, size_t n,_FalseType)
{
	for (size_t i = 0; i < n; ++i)//如果是自定义类型就调用for循环
	{
		dst[i] = src[i];
	}
	return dst;
}
template<class T>
T* _Copy(T* dst, T* src, size_t n)
{
	return _Copy(dst, src, n, TypeTraits<T>::IsPodType());
}
int main()
{
	int a1[5] = { 1, 2, 3 };
	int a2[5] = { 0 };
 	_Copy(a2, a1, 5);//把a1中的值拷贝到a2中,拷了10个对象
	string s1[5] = { "10", "20", "30" };
	string s2[5] = {};
	_Copy(s2, s1, 5);
	return 0;
}
我们来分析这个程序的走向:当程序运行到_Copy(a2,a1,10)时首先判断是不是平凡类型,判断是,则运行memcpy;当程序运行到_Copy(s2,s1,10)时判断出不是平凡类型,则运行for循环。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值