干货C++通过模板特化实现类型萃取实例--实现区分基本类型与自定义类型的memcpy

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了干货C++通过模板特化实现类型萃取实例--实现区分基本类型与自定义类型的memcpy相关的知识,希望对你有一定的参考价值。

    类型萃取是一种常用的编程技巧,其目的是实现不同类型数据面对同一函数实现不同的操作,如STL中cout的实现,它与类封装的区别是,我们并不用知道我们所调用的对象是什么类型,类型萃取是编译器后知道类型,先实现,而类的封装则是先定义类型,后实现方法。在这里我们可以用模板的特化实现其编程思想。

    我们以memcpy为例,当我们拷贝的是基本类型时,只用拷贝所传递指针上的数据,如果是string类型呢,我们则需要在堆上开辟空间,所传递的指针如果被直接复制,则有可能(vs下的string类型的实现原理是若字符串不长则以数组保存,若字符串过长,则通过指针在堆上开辟空间进行保存)出现同一地址,析构两次这样的常见错误。

    在这里我们需要在一个头文件中定义两个类,用来区分是否是基本类型,代码如下:

struct __TrueType//基本类型
{
	bool Get()
	{
		return true;
	}
};

struct __FalseType//非基本类型
{
	bool Get()
	{
		return false;
	}
};

    其次定义类模板,使基本类型特化,非基本类型则不需用特化:

template <class _Tp>//非基本类型不特化
struct TypeTraits
{
	typedef __FalseType   __IsPODType;
};

template <>//基本类型的全特化
struct TypeTraits< bool>
{
	typedef __TrueType     __IsPODType;
};

template <>
struct TypeTraits< char>
{
	typedef __TrueType     __IsPODType;
};

template <>
struct TypeTraits< unsigned char >
{
	typedef __TrueType     __IsPODType;
};

template <>
struct TypeTraits< short>
{
	typedef __TrueType     __IsPODType;
};

template <>
struct TypeTraits< unsigned short >
{
	typedef __TrueType     __IsPODType;
};

template <>
struct TypeTraits< int>
{
	typedef __TrueType     __IsPODType;
};

template <>
struct TypeTraits< unsigned int >
{
	typedef __TrueType     __IsPODType;
};

template <>
struct TypeTraits< long>
{
	typedef __TrueType     __IsPODType;
};

template <>
struct TypeTraits< unsigned long >
{
	typedef __TrueType     __IsPODType;
};

template <>
struct TypeTraits< long long >
{
	typedef __TrueType     __IsPODType;
};

template <>
struct TypeTraits< unsigned long long>
{
	typedef __TrueType     __IsPODType;
};

template <>
struct TypeTraits< float>
{
	typedef __TrueType     __IsPODType;
};

template <>
struct TypeTraits< double>
{
	typedef __TrueType     __IsPODType;
};

template <>
struct TypeTraits< long double >
{
	typedef __TrueType     __IsPODType;
};

template <class _Tp>
struct TypeTraits< _Tp*>//指针类型的偏特化
{
	typedef __TrueType     __IsPODType;
};

    做完这些我们还需要memcpy的实现:

template <class T>
void Copy(const T* src, T* dst, size_t size)
{
	//cout << "__TrueType:" << typeid(T).name() << endl;//测试用

	if (TypeTraits <T>::__IsPODType().Get())//返回值为真(是基本类型)则调用memcpy
	{
		memcpy(dst, src, size*sizeof (T));
	}
	else
	{
		for (size_t i = 0; i < size; ++i)/*不是基本类型,则用赋值运算符的重载实现memcpy*/
		{
			dst[i] = src[i];
		}
	}
}

    如有不足,希望批评指正。

本文出自 “pawnsir的IT之路” 博客,请务必保留此出处http://10743407.blog.51cto.com/10733407/1751557

以上是关于干货C++通过模板特化实现类型萃取实例--实现区分基本类型与自定义类型的memcpy的主要内容,如果未能解决你的问题,请参考以下文章

C++模板进阶

C++模板进阶

第17课 类型萃取_基本的type_traits

C++模板详解:泛型编程模板原理非类型模板参数模板特化分离编译

C++模板详解:泛型编程模板原理非类型模板参数模板特化分离编译

[C/C++]详解C++中的模板