C++类型萃取

来源:互联网 发布:优化发展环境讲话 编辑:程序博客网 时间:2024/06/06 18:41

一.问题的引入

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

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)//为自定义类型返回truereturn 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)//为自定义类型返回truereturn 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;}
下面给出内定类型的执行过程,因为自定义类型和内置类型的执行过程和原理一样,下面可以自己去测试


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

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

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;}

原创粉丝点击