C++模板总结——模板特化与类型萃取

一、模板特化

      在原模板的基础上对特殊类型进行特殊化。分为函数模板特化和类模板特化。

二、函数模板特化

特化步骤:

  (前提要有一个基础的函数模板)
  //1.template后加<>   2.函数名后加<指定type&>  3.形参表要和基础类型一样

//基础模板
template<class T>
bool IsEqual(T& left, T& right)
{
	return left == right;
}
void Test1()
{
	const char* p1 = "hello";
	const char* p2 = "world";
	if (IsEqual(p1, p2))
		cout << p1 << endl;
	else
		cout << p2 << endl;
}

//特化
template<>
bool IsEqual<char*>(char*& left, char*& right)
{
	if (strcmp(left, right) > 0)
		return true;
	return false;
}

三、类模板特化

1.分为全特化和偏特化

2.全特化:将模板参数类表中的参数类型都确定化。

template<typename T1,typename T2>
class Data
{
public:
	Data()
	{
		cout << "Data<T1,T2> "<< endl;
	}
private:
	T1 _data1;
	T2 _data2;
};

template<>
class Data<char,int>
{
public:
	Data()
	{
		cout << "Data<char,int> " << endl;
	}
private:
	char _data1;
	int _data2;
};

void Test()
{
	Data<int, int> d1;
	Data<char, int> d2;//调特化
}

2.偏特化

    1>部分参数特化

template<typename T1, typename T2>
class Data
{
public:
	Data()
	{
		cout << "Data<T1,T2> " << endl;
	}
private:
	T1 _data1;
	T2 _data2;
};

//第二个参数特化为int
template<typename T1>
class Data<T1,int>
{
public:
	Data()
	{
		cout << "Data<T1,int>" << endl;
	}
private:
	T1 _data1;
	int _data2;
};

    2>参数进一步限制:特化为指针,引用

//特化为指针
template<typename T1, typename T2>
class Data<T1* , T2*>
{
public:
	Data()
	{
		cout << "Data<T1*,T2*> " << endl;
	}
private:
	T1 _data1;
	T2 _data2;
};

//特化为引用
template<typename T1, typename T2>
class Data<T1& , T2&>
{
public:
	Data(const T1& d1,const T2& d2)
		:_data1(d1)
		,_data2(d2)
	{
		cout << "Data<T1&,T2&> " << endl;
	}
private:
	const T1& _data1;
	const T2& _data2;
};

调用时如果该类型特化过,就优先调用特化的模板。

四、类型萃取(重点)—实现拷贝函数

1.库函数提供了memcpy函数实现拷贝:是浅拷贝,拷贝自定义类型可能出错。

template<class T>
void Copy(T* dst, const T& src, size_t size)
{
	memcpy(dst, src, sizeof(T)* size);
}

2.for循环一个一个拷贝:是深拷贝,但效率低。

template<class T>
void Copy(T* dst, const T& src, size_t size)
{
	for (size_t i = 0; i < size; i++)
	{
		dst[i] = src[i];
	}
}

3.多传递一个参数ispod判断是不是内置类型,是的话就用浅拷贝,否则用深拷贝。但是这个参数需要用户手动传入,可能出错。

template<class T>
void Copy(T* dst, const T& src, size_t size, bool IsPOD)
{
	if(IsPOD)
		memcpy(dst, src, sizeof(T)*size);
	else
	{
		for (size_t i = 0; i < size; i++)
			dst[i] = src[i];
	}
}

4.将所有内置类型全部枚举出来,通过typeid确定拷贝对象的实际类型,判断是否为内置类型。要在内置类型中比较,效率低。

bool IsPodType(const char* strType)
{
	const char* arrType[] = { "char","short","int","long","long long","float","double","long double" };
	for (size_t i = 0; i < sizeof(arrType) / sizeof(arrType[0]); i++)
	{
		if (strcmp(strType, arrType[i]))
			return true;

		return false;
	}
}
template<class T>
void Copy(T* dst, const T& src, size_t size)
{
	if (IsPodType(typeid(T).name()))
		memcpy(dst, src, sizeof(T)*size);
	else
	{
		for (size_t i = 0; i < size; i++)
			dst[i] = src[i];
	}
}

5.类型萃取:


//类型萃取:两个类区分内置类型和自定义类型
struct TrueType
{
	static bool Get()
	{
		return true;
	}
};
struct FalseType
{
	static bool Get()
	{
		return false;
	}
};

template<class T>
struct TypeTraits
{
	typedef FalseType IsPOD;
};

template<>
struct TypeTraits<bool>
{
	typedef TrueType IsPOD;
};

template<>
struct TypeTraits<int>
{
	typedef TrueType IsPOD;
}; 

template<>
struct TypeTraits<char>
{
	typedef TrueType IsPOD;
}; 

template<>
struct TypeTraits<short>
{
	typedef TrueType IsPOD;
};

template<>
struct TypeTraits<double>
{
	typedef TrueType IsPOD;
};

template<class T>
struct TypeTraits<T*>
{
	typedef TrueType IsPOD;
};
//......

template<class T>
void Copy(T* dst, T* src, size_t size)
{
	if(TypeTraits<T>::IsPOD::Get())
		memcpy(dst, src, sizeof(T)*size);
	else
	{
		for (size_t i = 0; i < size; i++)
			dst[i] = src[i];
	}
}

void Test5()
{
	int a1[] = { 1,2,3,4,5 };
	int a2[5];
	Copy(a2, a1, 5);//程序运行使用特化的int,其中的IsPOD为TrueType,Get函数返回真,调用浅拷贝

	string s1[] = { "111","222","333" };//string类型没有特化,其中的IsPOD为FalseType,Get函数返回假,调用赋值拷贝
	string s2[3];
	Copy(s2, s1, 3);
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值