C++类型萃取

一.问题的引入

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

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


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

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

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

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值