C++特化的应用——类型萃取

  • 提出问题:如何实现一个对于拷贝内置类型和自定义类型通用的拷贝函数?

1、拷贝内置类型

对于内置类型我们可以用memcpy进行拷贝,因为memcpy属于浅拷贝,内置类型不涉及资源管理的问题。

2、拷贝自定义类型

拷贝自定义类型时有可能会涉及到深拷贝(如string)涉及到了资源管理,就不能使用memcpy。

所以给出了一种方法:赋值

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

int main()
{
	std::string strarr1[3] = { "11", "22", "33" };   
	std::string strarr2[3];   
	Copy(strarr2, strarr1, 3);
	return 0;
}

我们使用循环赋值的方式来进行拷贝,但发现这样做效率很低。

 


  • 那能否将上述两种方法结合起来,遇到内置类型就用memcpy来拷贝,遇到自定义类型就用赋值方式来做呢?

 

改进一  我们增加一个bool类型区分 内置类型 与 自定义类型 。

true就是内置类型,false就是自定义类型。 

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

但发现这样做,用户就需要手动的添加最后一个参数,易出错。

那能否让一个函数自动去识别所拷贝类型是内置类型或者自定义类型呢?

改进二  使用函数区分内置于自定义类型

bool IsPODType(const char* strType)
{
    // 此处只是举例,只列出个别类型 
	const char *arrType[] = { "char", "short", "int", "long", "long long", "float", "double", "long double" };        

	for (auto e : arrType)
	{
		if (strcmp(e, strType) == 0)
			return true;
	}
	return false;
}

template
void Copy(T* dst, const T* src, size_t size)
{
	if(IsPODType(typeid(T).name())            //typeid来确认所拷贝对象的实际类型
		memcpy(dst, src, sizeof(T)*size);
	else
	{
		for (size_t i = 0; i < size; ++i)
		{
			dst[i] = src[i];
		}
	}
}

但这样做需要将所有的类型遍历一遍,且每次比较都是字符串的比较,效率较低。

改进三  类型萃取

为了将内置类型与自定义类型区分开,给出以下两个类分别代表内置类型与自定义类型。

//代表内置类型
struct TrueType {
	static bool Get()
	{
		return true;
	}
};
//代表自定义类型
struct FalseType {
	static bool Get()
	{
		return false;
	}
};

再给出类模板,用户可以按照任意类型实例化该模板

通过将基本类型每个都特化一次,在识别时就可以直接确定出所传入的参数的类型。

在对基本类型特化时,必需要将所有的类型都特化一变,包括有符号和无符号的类型。这里只给出了几种。

//给出模板
template 
struct TypeTraits 
{ 
	typedef FalseType IsPODType;
};

//对上述的类模板进行以下方式的实例化
template<> 
struct TypeTraits
{ 
	typedef TrueType IsPODType;
};
template<> 
struct TypeTraits 
{ 
	typedef TrueType IsPODType;
};
template<> 
struct TypeTraits 
{ 
	typedef TrueType IsPODType; 
};
template<> 
struct TypeTraits 
{ 
	typedef TrueType IsPODType; 
};

 

类型萃取总代码:

#include 
#include 

//代表内置类型
struct TrueType {
	static bool Get()
	{
		return true;
	}
};
//代表自定义类型
struct FalseType {
	static bool Get()
	{
		return false;
	}
};

//给出模板
template 
struct TypeTraits 
{ 
	typedef FalseType IsPODType;
};
//对上述的类模板进行以下方式的实例化
template<> 
struct TypeTraits
{ 
	typedef TrueType IsPODType;
};
template<> 
struct TypeTraits 
{ 
	typedef TrueType IsPODType;
};
template<> 
struct TypeTraits 
{ 
	typedef TrueType IsPODType; 
};
template<> 
struct TypeTraits 
{ 
	typedef TrueType IsPODType; 
};

template
void Copy(T* dst, const T* src, size_t size)
{
    //通过对TypeTraits类模板,来确认所拷贝对象的实际类型
	if(TypeTraits::IsPODType::Get())
		memcpy(dst, src, sizeof(T)*size);
	else
	{
		for (size_t i = 0; i < size; ++i)
		{
			dst[i] = src[i];
		}
	}
}

int main()
{
	int a1[] = { 1,2,3,4,5,6,7,8,9,0 };   
	int a2[10];   
	Copy(a2, a1, 10);  //内置类型调用特化 int

	std::string strarr1[3] = { "11", "22", "33" };   
	std::string strarr2[3];   
	Copy(strarr2, strarr1, 3); //自定义类型调用模板
	return 0;
}

 

 

 

 

 

 

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