c++模板之萃取
阿新 • • 發佈:2019-01-25
假如,我們要設計一個_Copy的模板函式。我們為了提高效率採用memcpy,可以這樣寫:
template<typename T>
T* _Copy(T* dest, T* src, size_t n)
{
memcpy(dest, src, sizeof(T)*n);
return dest;
}
我們知道一般的型別(比如int,float,double,char等)進行復制的時候採用memcpy效率會高一些;而像string或者是其他的一些自定義型別(並且成員有指標型別的話),繼續用mencpy將出現錯誤,採用for迴圈進行一個一個複製(賦值運算子過載)才是正確的方法。
自定義型別for迴圈程式碼:
template<typename T>
T* _Copy(T* dest, T* src, size_t n)
{
for (size_t i = 0; i < n; i++)
{
dest[i] = src[i]; //相當與呼叫string的賦值運算子過載
}
return dest;
}
但是採用for迴圈拷貝效率明顯不如memcpy函式高,如何才能讓程式在執行內建型別時呼叫memcpy,而拷貝自定義型別時防止錯誤呼叫for迴圈拷貝,兩者兼顧呢??
為了進行不同的型別呼叫不同的方式進行拷貝,我們可以利用模板及模板的特化,在特化中返回它的型別進而進行判斷要進行那種方式的拷貝。為了統一,也可在模板即特化中重新命名它的型別,當所給的型別與所有特化有匹配時,執行一種方式進行拷貝;當所給的型別與所有特化沒有匹配時,執行另一種方式進行拷貝。
以下是原始碼:
#include <iostream>
using namespace std;
#include <string>
struct _TureType
{
bool get()
{
return true;
}
};
struct _FalseType
{
bool get()
{
return false;
}
};
//型別萃取
template<typename T>
struct TypeTraits
{
typedef _FalseType _IsPodType;
};
//特化TypeTraits進行型別判斷(由於內建型別已經確定,而自定義型別不確定,因此經常特化內建型別)
template<>
struct TypeTraits<int>
{
typedef _TureType _IsPodType;
};
template<>
struct TypeTraits<unsigned int>
{
typedef _TureType _IsPodType;
};
template<>
struct TypeTraits<double>
{
typedef _TureType _IsPodType;
};
template<>
struct TypeTraits<float>
{
typedef _TureType _IsPodType;
};
template<>
struct TypeTraits<char>
{
typedef _TureType _IsPodType;
};
template<>
struct TypeTraits<unsigned char>
{
typedef _TureType _IsPodType;
};
template<>
struct TypeTraits<short>
{
typedef _TureType _IsPodType;
};
template<>
struct TypeTraits<long>
{
typedef _TureType _IsPodType;
};
template<>
struct TypeTraits<long long>
{
typedef _TureType _IsPodType;
};
/*根據需要繼續特化.................*/
template<typename T>
T* _Copy(T* dest, T* src, size_t n, _TureType)
{
memcpy(dest, src, sizeof(T)*n);
return dest;
}
template<typename T>
T* _Copy(T* dest, T* src, size_t n, _FalseType)
{
for (size_t i = 0; i < n; i++)
{
dest[i] = src[i]; //相當與呼叫string的賦值運算子過載
}
return dest;
}
template<typename T>
T* _Copy(T*dest, T* src, size_t n)
{
return _Copy(dest, src, n, TypeTraits<T>::_IsPodType());
}
//測試普通型別
void test1()
{
int a[10] = { 2, 2, 3, 4, 5, 6, 7, 8, 8 };
int b[10] = { 1, 1, 1, 1, 1, 1, 1, 1, 1 };
_Copy(a, b, 5);
}
//特化自定義型別
void test2()
{
string a[5] = { "abc", "def", "ghi", "123", "456" };
string b[4] = {"111111111111111111111111111111111111111", "222222", "333333", "44444444"};
_Copy(a, b, 3);
}
int main()
{
//test1();
test2();
system("pause");
return 0;
}