C++】模板特化的應用---類型萃取

在C++中,內置類型的遍歷,我們只需要進行淺拷貝就可以,但自定義類型就不一定了。比如之前類與對象中,如果類中對象涉及到資源,我們使用深拷貝的方式進行拷貝構造等操作,如果不涉及資源,則使用簡單的淺拷貝,在模擬實現string類\vector等中也遇到。這樣雖然可以,但代碼效率低。
所以,爲了將內置類型與自定義類型區分開,就有了類型萃取,它是類模板特化的應用。那麼我們先來了解類模板特化以及非類型模板參數
非類型模板參數

模板參數分爲類型形參與非類型形參
在這裏插入圖片描述
注意:

  • 浮點數,類對象以及字符串是不允許作爲非類型模板參數的
  • 非類型模板參數必須在編譯期就能確認結果

模板的特化

有時我們使用模板實現一些與類型無關的代碼,但對於一些特殊類型的可能會得到一些錯誤的結果,看下面代碼
代碼1

template<class T>
T MAX(T left, T right)
{
 return left > right ? left : right;
}
int main()
{
 char* p1 = "world";
 char* p2 = "hello";
 cout << MAX(p1, p2) << endl;

比較字符串大小時,這裏面比較的是指針類型,因此不管p1、p2是什麼字符串,打印的都是p2,所以如果不直接將函數直接給出,用模板的話,就要將模板特化了
代碼2

//格式就是這樣
template<>
char* MAX<char*>(char*& left, char*& right)//函數形參表必須要和模板函數的基礎參數類型完全相同
{
 if (strcmp(left, right) > 0)
  return left;
 return right;
}

代碼2則是對代碼1 函數模板的特化,上面一般情況函數模板遇到不能處理或者處理有誤的類型,爲了簡單通常都是將該函數直接給出。
關於模板特化,主要是闡述下類模板特化

類模板特化

分爲全特化和偏特化
全特化就是將模板擦書類表中所有的參數都確定化
偏特化就是針對模板參數進一步進行條件限制,其中,部分特化是將模板參數中的一部分參數特化;參數更進一步的限制是針對模板參數更進一步的條件限制所設計出來的一個特化版本
在實例化時,調用對應的版本,如果沒有,就調用普通的類模板,看代碼就理解了
代碼3

template<class T1,class T2>
class Data
{
public:
 Data(){cout << "Data<T1,T2>" << endl;}
private:
 T1 _d1;
 T2 _d2;
};
template<>
class Data<int, char>//全特化,將所有參數都確定話
{
public:
 Data(){ cout << "Data<int,char>" << endl; }
private:
 int _d1;
 char _d2;
};
template<class T1>
class Data<T1, int>//部分特化  第一個參數任意類型都可以
{
public:
 Data(){ cout << "Data<int,char>" << endl; }
private:
 T1 _d1;
 char _d2;
};
int main()
{
 Data<int, double> d1;//調用基礎版本
 Data<int, char> d2;//調用全特化版本
 Data<char, int> d3;//調用部分特化
 return 0;
}

類型萃取—類模板特化的應用

可以將內置類型與自定義類型區分開
我們將用TrueType代表內置類型,FalseType代表自定義類型,定義TypeTraits,給類型都取別名IsPODType,如果是內置類型則調用對應的類模板特化,如果是自定義得得到F進行淺拷貝Type,通過循環進行賦值深拷貝。代碼如下:

//代表內置類型/////////////////////////////////////////////////////
struct TrueType
{
 static bool Get(){return true;}
};
//代表自定義類型
struct FalseType
{
 static bool Get(){return false;}
};
//用戶對類模板進行實例化,T可以是任意類型////////////////////////////
template<class T>//自定義類型特化
struct TypeTraits
{
 typedef FalseType IsPODType;//定義別名
};
/////////////////////////////////////////////////////////////////////
template<>//內置類型特化
struct TypeTraits<char>
{
 typedef TrueType IsPODType;
};
template<>
struct TypeTraits<short>
{
 typedef TrueType IsPODType;
};
template<>
struct TypeTraits<int>
{
 typedef TrueType IsPODType;
};
template<>
struct TypeTraits<long>
{
 typedef TrueType IsPODType;
};
//所有內置類型都特化一下...
//////拷貝函數/////////////////////////////////////////////////////
template<class T>
void Copy(T* dst, const T* src, size_t size)
{
 if (TypeTraits<T>::IsPODType::Get())//識別出類型
  memcpy(dst, src, sizeof(T)*size);
 else//如果不是上述類型
 {
  for (size_t i = 0; i < size; ++i)
   dst[i] = src[i];
 }
}
/////test///////////////////////////////////////////////////////
int main()
{
 int a1[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
 int a2[10];
 Copy(a2, a1, 10);//內置類型就調用內置類型的版本  淺拷貝
 string s1[] = { "1111", "2222", "3333", "4444" };
 string s2[4];
 Copy(s2, s1, 4);//自定義就調用自定義類型   深拷貝
 return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章