c++ 型別萃取
阿新 • • 發佈:2019-01-13
型別萃取
型別萃取是基於c++中的模板特化來實現的,是對於模板特化的應用。
關於c++的模板特化
當我們寫一個同用的拷貝函式時,我們可以使用mymcpy進行拷貝,但是mymcpy是一個淺拷貝,對於一些基本型別的拷貝效率很高。但是對於要深拷貝的型別來說就不適用了,對於深拷貝我們可以使用for迴圈的方式來進行。
所以將兩者進行結合,當基本型別進行拷貝時使用mymcpy,當自定義型別進行拷貝時使用for迴圈的方式。
使用函式的方式進行實現
#include <iostream> #include <cstring> #include <typeinfo> #include <string> using namespace std; /* *使用函式進行通用拷貝的實現,但時在基本型別的確定時需要迴圈,仍然造成一些效率問題 * * */ template<class T> bool IsBasicType(const T* Type){ const char* type_arr[] = { "int" , "char" , "float" , "double" , "long" , "short" , "long long" }; //這裡僅列舉了部分的基本型別 for(int i = 0 ; i < sizeof(type_arr)/sizeof(type_arr[0]); ++i) { if(strcmp(type_arr[i] , Type) == 0) return true; return false; } } template<class T> void Copy(T* dest , T* src, size_t size){ if(IsBasicType(typeid(T).name())) memcpy(dest,src,size*sizeof(T)); else{ for(int i = 0; i < size; i++) { dest[i] = src[i]; } } } int main() { // string s1[] = {"www" , "eee" , "rrr"}; // string s2[3]; float s1[] = {11.1,33.2,33.4}; float s2[3]; Copy<float>(s2,s1,3); for(int i = 0; i < sizeof(s2)/sizeof(s2[0]); ++i) cout << s2[i] << endl; return 0; }
以上的函式雖然可以區分基本型別和自定義型別,但是在判斷是否為自定義型別時需要,迴圈並且需要strcmp進行字串比較,所以效率較大。
如果我們要想讓函式能夠自動識別是基本型別還是自定義的型別,這時我們就需要用到型別萃取了。
型別萃取實質上就是對於模板特化的應用,通過將基本型別每個都特化一次,在識別時就可以直接確定出所傳入的引數的型別。
- 在對基本型別特化時,必需要將所有的型別都特化一變,包括有符號和無符號的型別
#include <iostream> #include <string> #include <cstring> using namespace std; /*使用型別萃取 *使用模板的特化,將所有的模板進行特化,使其能夠自動識別,從而少了之前 * 迴圈判斷型別 */ //先定義兩個型別的類,其中包含一個靜態的方法用於返回判斷條件所需的真假 //標識基本型別 struct BasicType{ static bool Get(){ return true; } }; //標識自定義型別 struct DefineType{ static bool Get(){ return false; } }; /*建立一個模板類用於識別是基本型別還是自定義型別 由於基本型別都被特化了,所以呼叫基礎模板函式的就是自定義型別 使用一個IsBsicType 來進行型別的重定義,以便呼叫Get() */ template<class T> struct Type_recog{ typedef DefineType IsBasicType; }; //這裡只列舉了部分的基本型別 template<> struct Type_recog<int>{ typedef BasicType IsBasicType; }; template<> struct Type_recog<char>{ typedef BasicType IsBasicType; }; template<> struct Type_recog<short>{ typedef BasicType IsBasicType; }; template<> struct Type_recog<float>{ typedef BasicType IsBasicType; }; template<> struct Type_recog<double>{ typedef BasicType IsBasicType; }; template<> struct Type_recog<long>{ typedef BasicType IsBasicType; }; template<> struct Type_recog<long long>{ typedef BasicType IsBasicType; }; template<class T> void Copy(T* dest, T* src ,size_t size){ if(Type_recog<T>::IsBasicType::Get()) memcpy(dest,src,size*sizeof(T)); else { for(int i = 0; i < size; i++) dest[i] = src[i]; } } int main(){ // string s1[] = {"www","eee","rrr"}; // string s2[3]; int s1[] = {1,2,3}; int s2[3]; Copy<int>(s2,s1,3); for(int i = 0; i < sizeof(s2)/sizeof(s2[0]); ++i) cout << s2[i] << endl; return 0; }