【乾貨】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

發佈了64 篇原創文章 · 獲贊 11 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章