C++泛型編程
1. 基本概念
1.1 泛型編程(Generic Programming)
泛型編程是C++中一種重要的編程范式,它通過 參數化類型 來實現代碼的通用性和復用性。
1.2 模板(Templates)
模板 是泛型編程的基礎,允許編寫與數據類型無關的代碼。
模板分類:
-
函數模板:參數化函數的參數類型。
-
類模板:參數化類的成員類型。
-
使用
template
關鍵字聲明模板,typename
或class
聲明模板類型,代表一個占位符類型,將在實例化時被具體類型替換。
template<typename T1 , typename T2 , ...>
2. 函數模板
2.1 函數模板語法
template<typename T>
void function( T arg1, T arg2 ) {// ...
}
2.2 函數模板的實例化
函數模板的實例化分為隱式實例化和顯示實例化。
-
隱式實例化:編譯器根據形參推演模板參數的實際類型。
-
顯示實例化:在函數名后<>中指定模板參數的實際類型。
template<typename T>
T add(const T& x , const T& y) {return x + y;
}int main () {add(10 , 20); // 隱式實例化 T為intadd(1.1 , 2.2); // 隱式實例化 T為double// add(10 , 1.1); // 編譯不通過,因為無法確定T為 int 還是 double 類型add<int>(10 , 1.1); // 通過顯示實例化解決return 0;
}
注意:對于非模板函數和同名函數模板,如果其他條件都相同,會優先調用非模板函數。
3. 類模板
3.1 類模板語法
template<typename T1 , typename T2 , ...>
class ClassName {// ...
};
3.2 類模板的實例化
類模板必須顯示實例化。
template<typename T>
class vector {// ...private:T* start = nullptr;T* finish = nullptr;T* end_of_storage = nullptr;
};int main () {// 顯示實例化vector<int> v1; vector<double> v1; return 0;
}
4. 非類型模板參數
非類型模板參數是C++模板中一種特殊的參數類型,它允許在編譯時傳遞值而不是類型作為模板參數。
非類型模板參數可以是以下類型之一
-
整型
-
指針或引用類型
-
C++20起支持浮點類型作為模板參數
-
C++20起支持類類型作為模板參數
template<typename T, size_t N = 10>
class Array {// ...T arr[N];
};int main () {Array<> arr1; // 使用缺省值的寫法Array<5> arr2;Array<15> arr3; return 0;
}
5. 模板的特化
模板特化是C++中為特定類型提供的模板定制。它允許我們為特定類型提供優化的或不同的實現,同時保留通用模板的靈活性。
5.1 函數模板的特化
函數模板也可以特化,但通常更推薦使用函數重載。
函數模板特化步驟
-
特化必須聲明在主模板之后。
-
關鍵字template后面接一對空的尖括號<>。
-
函數名后跟一對尖括號,尖括號中指定需要特化的類型。
-
特化模板的函數形參必須要和基礎模板的函數形參完全相同。
template<typename T>
bool less(T left , T right) {return left < right;
}// 對 int* 特殊化處理
template<>
bool less<int*>(int* left , int* right) {return *left < *right;
}// 更推薦使用函數重載
bool less (int* left , int* right) {return *left < *right;
}
注意:函數模板不能偏特化,但可以通過函數重載實現。
5.2 類模板的特化
類模板特化分為全特化和偏特化兩種形式。
-
全特化:為模板的所有參數指定具體類型或值,完全特化整個模板。
-
偏特化:只特化部分模板參數,或者對模板參數施加某種模式或約束。
5.2.1 全特化
// 主模板定義
template <typename T1, typename T2>
class MyClass {// 通用實現
};// 全特化
template <>
class MyClass<int, double> {// 針對<int, double>的特化實現
};
5.2.2 偏特化(特化部分模板參數)
// 主模板定義
template <typename T1, typename T2>
class MyClass {// 通用實現
};// 偏特化/半特化
template <typename T1>
class MyClass<T1, double> {// 針對<T1, double>的特化實現
};
注意:全特化和偏特化都存在時,全特化版本比偏特化版本具有更高的優先級。
5.2.3 偏特化(對模板參數施加某種約束)
// 主模板定義
template <typename T1, typename T2>
class MyClass {// 通用實現
};// 偏特化/半特化
template <typename T1 , typename T2>
class MyClass<T1*, T2*> {// 針對<T1*, T2*>的特化實現
};// 偏特化/半特化
template <typename T1 , typename T2>
class MyClass<T1&, T2&> {// 針對<T1&, T2&>的特化實現
};