模板編程中如果要特化或偏特化(局部特化)一個類模板,需要特化該類模板的所有成員函數。類模板中大多數成員函數的功能可能是一模一樣的,特化時我們可能只需要重新實現1、2個成員函數即可。在這種情況下,如果全部重寫該模板類的所有成員函數,不但會增加工作量,也不利於代碼的維護。
例如下面的類模板A,只有在模板參數是char*時才需要特化成員函數func(),但其他的成員函數都不需要特化:
1 template <typename _Ty> 2 struct A 3 { 4 // 其他成員函數a 5 // 其他成員函數b 6 // ...... 7 void func() 8 { 9 std::cout << "common type." << std::endl; 10 } 11 }; 12 13 int main() 14 { 15 A<int> i; 16 i.func(); 17 18 A<char*> c; 19 c.func(); 20 21 return 0; 22 }
方法一:通過運行時類型識別,這個方法最簡單
1 template <typename _Ty> 2 struct A 3 { 4 // 其他成員函數a 5 // 其他成員函數b 6 // ...... 7 void func() 8 { 9 if (typeid(_Ty) == typeid(char*)) 10 std::cout << "common type." << std::endl; 11 else 12 std::cout << "special type." << std::endl; 13 } 14 };
方法二:通過類的成員函數模板特化來實現,這個方法也比較簡單
1 template <typename _Ty> 2 struct A 3 { 4 // 其他成員函數a 5 // 其他成員函數b 6 // ...... 7 template <typename __Ty> 8 void funcImpl() 9 { 10 std::cout << "common type." << std::endl; 11 } 12 13 template <> 14 void funcImpl<char*>() 15 { 16 std::cout << "special type." << std::endl; 17 } 18 19 void func() 20 { 21 funcImpl<_Ty>(); 22 } 23 };
方法三:通過一個嵌套模板類的特化來實現
1 template <typename _Ty> 2 struct A 3 { 4 // 其他成員函數a 5 // 其他成員函數b 6 // ...... 7 template <typename __Ty> 8 struct IsCharPType 9 { 10 const static bool b = false; 11 }; 12 13 template<> 14 struct IsCharPType<char*> 15 { 16 const static bool b = true; 17 }; 18 19 void func() 20 { 21 if (IsCharPType<_Ty>::b) 22 std::cout << "special type." << std::endl; 23 else 24 std::cout << "common type." << std::endl; 25 } 26 };
方法四:先定義一個嵌套的類模板,通過重載函數實現(函數的參數類型不同)
1 template <typename _Ty> 2 struct A 3 { 4 // 其他成員函數a 5 // 其他成員函數b 6 // ...... 7 template <typename __Ty> 8 struct TypeClass 9 { 10 }; 11 12 template <typename __Ty> 13 void funcImpl(const TypeClass<__Ty>&) 14 { 15 std::cout << "common type." << std::endl; 16 } 17 18 void funcImpl(const TypeClass<char*>&) 19 { 20 std::cout << "special type." << std::endl; 21 } 22 23 void func() 24 { 25 funcImpl(TypeClass<_Ty>()); 26 } 27 };