欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

C++类型萃取

程序员文章站 2022-06-10 13:50:29
...

一.问题的引入

首先我们如果要写一个拷贝函数,代码如下:

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

但是这个代码拷贝内置类型的没有问题,但是如果是自定义类型的,就牵扯到深浅拷贝问题,就行不通了,所以我们需要做的就是在代码内部判断传过来的数据类型,从而进行不同的操作。代码如下

template<class T>
void Copy(T *dst, T *src, size_t size)
{
	if (内置类型)
	{
		memcpy(dst, src, sizeof(T)*size);
	}
	else//自定义类型
	{
		for (size_t i = 0; i < size; ++i)
			dst[i] = src[i];
	}
}
但是怎么进行类型判断呢?代码如下:

bool IsPOD(const char *TypeName)
{
	static char *p[] = { "int", "double", "float" };
	int len = sizeof(p) / sizeof(*p);
	for (int i = 0; i < len; ++i)
	{
		if (strcmp(p[i], TypeName) == 0)//为自定义类型返回true
			return true;
	}
	return false;
}
这样的话我们只需要在Copy的函数if语句中调用这个IsPOD函数就可以区分自定义类型和内置类型了,从而解决了之前类型不同的问题。

完整的代码如下:

bool IsPOD(const char *TypeName)
{
	static char *p[] = { "int", "double", "float" };
	int len = sizeof(p) / sizeof(*p);
	for (int i = 0; i < len; ++i)
	{
		if (strcmp(p[i], TypeName) == 0)//为自定义类型返回true
			return true;
	}
	return false;
}
template<class T>
void Copy(T *dst, T *src, size_t size)
{
	if (IsPOD(typeid(T).name()))
	{
		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 };
	int a2[5];
	string s1[] = { "1111", "2222", "3333", "4444" };
	string s2[4];

	Copy(a2, a1, sizeof(a1) / sizeof(*a1));
	Copy(s2, s1, sizeof(s1) / sizeof(s1[0]));
	system("pause");
	return 0;
}
二.类型萃取

类型萃取的功能和上述代码一样,就是用来提取代码类型的,不过具体的实现步骤是什么样的呢,我们继续往下看

首先给出如下代码

struct TrueType
{
	static bool IsPODType()
	{
		return true;
	}
};
struct FalseType//对应自定义类型的处理
{
	static bool IsPODType()
	{
		return false;
	}
};
//什么类型都可以处理
template<class T>//所有的类型都扔进去处理
struct TypeTraits
{
	typedef FalseType PODtype;//将数据类型看成自定义的类型来处理不会出错
};
相信这段代码有一定基础的同学一定可以看懂,接下来看Copy中如何使用上面的模版

template<class T>
void Copy(T *dst, T *src, size_t size)
{
	if (TypeTraits<T>::PODtype::IsPODType())
	{
		memcpy(dst, src, sizeof(T)*size);
	}
	else
	{
		for (size_t i = 0; i < size; ++i)
			dst[i] = src[i];
	}
}
但是这样无法识别自定义类型和内置类型,因为无论扔过去什么都会返回false,怎么解决这个问题呢,这就要用到模版的特化

代码如下:

//什么类型都可以处理
template<class T>//所有的类型都扔进去处理
struct TypeTraits
{
	typedef FalseType PODtype;//将数据类型看成自定义的类型来处理不会出错
};
template<>
struct TypeTraits<int>
{
	typedef TrueType PODtype;
};
template<>
struct TypeTraits<char>
{
	typedef TrueType PODtype;
};
template<>
struct TypeTraits<double>
{
	typedef TrueType PODtype;
};
这样的话就可以处理不同的类型的

下面给出完整的代码包括测试代码:

struct TrueType
{
	static bool IsPODType()
	{
		return true;
	}
};
struct FalseType//对应自定义类型的处理
{
	static bool IsPODType()
	{
		return false;
	}
};
//什么类型都可以处理
template<class T>//所有的类型都扔进去处理
struct TypeTraits
{
	typedef FalseType PODtype;//将数据类型看成自定义的类型来处理不会出错
};
template<>
struct TypeTraits<int>
{
	typedef TrueType PODtype;
};
template<>
struct TypeTraits<char>
{
	typedef TrueType PODtype;
};
template<>
struct TypeTraits<double>
{
	typedef TrueType PODtype;
};
template<class T>
void Copy(T *dst, T *src, size_t size)
{
	if (TypeTraits<T>::PODtype::IsPODType())
	{
		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 };
	int a2[5];
	string s1[] = { "1111", "2222", "3333", "4444" };
	string s2[4];

	Copy(a2, a1, sizeof(a1) / sizeof(*a1));
	Copy(s2, s1, sizeof(s1) / sizeof(s1[0]));
	system("pause");
	return 0;
}
下面给出内定类型的执行过程,因为自定义类型和内置类型的执行过程和原理一样,下面可以自己去测试

C++类型萃取

以上就是类型萃取,其实就是模版的特化的应用!

其实上面的完整类型萃取也可以写成如下的方式,代码如下:

struct TrueType
{};
struct FalseType//对应自定义类型的处理
{};
//什么类型都可以处理
template<class T>//所有的类型都扔进去处理
struct TypeTraits
{
	typedef FalseType PODtype;//将数据类型看成自定义的类型来处理不会出错
};
template<>
struct TypeTraits<int>
{
	typedef TrueType PODtype;
};
template<>
struct TypeTraits<char>
{
	typedef TrueType PODtype;
};
template<>
struct TypeTraits<double>
{
	typedef TrueType PODtype;
};
template<class T>
void Copy(T *dst, T *src, size_t size, TrueType)
{
	memcpy(dst, src, sizeof(T)*size);
}
template<class T>
void Copy(T *dst, T *src, size_t size, FalseType)
{
	for (size_t i = 0; i < size; ++i)
		dst[i] = src[i];
}
template<class T>
void Copy(T *dst, T *src, size_t size)
{
	Copy(dst, src, size, TypeTraits<T>::PODtype());
}
int main()
{
	int a1[] = { 1, 2, 3, 4, 5 };
	int a2[5];
	string s1[] = { "1111", "2222", "3333", "4444" };
	string s2[4];

	Copy(a2, a1, sizeof(a1) / sizeof(*a1));
	Copy(s2, s1, sizeof(s1) / sizeof(s1[0]));
	system("pause");
	return 0;
}

相关标签: 类型萃取