【乾貨】C++經過模板特化實現類型萃取實例--實現區分基本類型與自定義類型的memcpy

    類型萃取是一種經常使用的編程技巧,其目的是實現不一樣類型數據面對同一函數實現不一樣的操做,如STL中cout的實現,它與類封裝的區別是,咱們並不用知道咱們所調用的對象是什麼類型,類型萃取是編譯器後知道類型,先實現,而類的封裝則是先定義類型,後實現方法。在這裏咱們能夠用模板的特化實現其編程思想。編程

    咱們以memcpy爲例,當咱們拷貝的是基本類型時,只用拷貝所傳遞指針上的數據,若是是string類型呢,咱們則須要在堆上開闢空間,所傳遞的指針若是被直接複製,則有可能(vs下的string類型的實現原理是若字符串不長則以數組保存,若字符串過長,則經過指針在堆上開闢空間進行保存)出現同一地址,析構兩次這樣的常見錯誤。
數組

    在這裏咱們須要在一個頭文件中定義兩個類,用來區分是不是基本類型,代碼以下:
ide

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

    若有不足,但願批評指正。
指針

相關文章
相關標籤/搜索