We know that in C ++ template programming, If we specialize in or partial to a template class, we need to rewrite all the functions in the entire template class, but these codes are usually very similar, in some cases, only one or two functions may be different. Other functions are the same. In this case, there are multiple identical codes at the same time, which is very unfavorable for us to maintain these codes. We 'd better simply specialize in the different functions. For example, the following template class: template <typename T, unsigned B> struct Base {// other function //.... void Func () {cout <"primary function" <endl ;}}; void test1 () {Base <int, 1> a;. func (); Base <int, 16> B; B. func () ;}int main () {test1 () ;}only when B is equal to 16, Func needs to be special, but other functions are the same in any case. Below are some possible solutions: Method 1: template <typename T> struct Base <T, 16> {// other function //.... void Func () {cout <"specialization function" <endl ;}}; comments: If this function is implemented with special features, you need to override all class member methods. Method 2: template <typename T, unsigned B> struct Base {// other function //.... void Func () {if (B = 16) {cout <"primary function" <endl ;} else {cout <"specialization function" <endl ;}}; comments: it is easy to understand, but relatively inefficient, through runtime judgment. Method 3: template <typename T, unsigned B> struct Base {// other function //... void Func () {# if B! = 16 cout <"primary function" <endl; # else cout <"specialization function" <endl; # endif}; Comments: It is implemented by pre-compilation, however, this method is incorrect. C ++ template compilation includes pre-compilation, syntax check, template instantiation, and other stages. In the pre-compilation stage, the template parameters are not instantiated yet. Method 4: template <typename T, unsigned B> struct Base {// other function //.... template <unsigned S> struct FuncObj {void operator () {cout <"primary function" <endl ;}}; template <> struct FuncObj <16> {void operator () {cout <"specialization function" <endl ;}; FuncObj <B> Func ;}; comments: the member classes are added to prevent special functions. Method 5: template <typename T, unsigned B> struct Base {// other function //.... template <unsigned N> void FuncImpl () {cout <"primary function" <endl ;}template <> void FuncImpl <16> () {cout <"specialization function" <endl ;}void Func () {FuncImpl <B> () ;}}; comment: the class member template function is specially implemented. Method 6: template <typename T, unsigned B> struct Base {// other function //.... template <unsigned N> class Int2Type {enum {value = N };}; template <unsigned V> void FuncImpl (const Int2Type <V>) {cout <"primary function" <endl;} void FuncImpl (const Int2Type <16>) {cout <"specialization function" <endl;} void Func () {FuncImpl (Int2Type <B> () ;}}; comment: Convert int to different types based on different values, and then implement it through function overload. Method 7: namespace {template <bool, typename T, typename> struct conditional {typedef T type ;}; template <typename T, typename U> struct conditional <false, T, U >{typedef U type ;};}template <class T, unsigned B> struct Base {// other function //.... void Func () {typedef typename: conditional <B! = 16, primary_t, spec_t >:: type; Func_impl (type ();} private: struct primary_t {}; struct spec_t {}; void Func_impl (primary_t) {std:: cout <"primary function" <std: endl;} void Func_impl (spec_t) {std: cout <"specialization function" <std :: endl ;}}; comment: similar to Method 6, Implementation Method 8 through function overload: namespace {template <bool, typename T = void> struct enable_if {typedef T type ;}; template <typename T> struc T enable_if <true, T >{};} template <class T, unsigned B> struct Base {// other function //.... template <unsigned N> typename: enable_if <16! = N >:: type FuncImpl () {std: cout <"primary function" <std: endl;} template <unsigned N> typename :: enable_if <16 = N >:: type FuncImpl () {std: cout <"specialization function" <std: endl;} void Func () {FuncImpl <B> () ;}}; comment: Use SFINAE to enable_if. We can see that according to the int value of the template parameter during compilation, the methods for rewriting a member function of the template class are diverse. In response to the above situation, I personally recommend method 2. We do not need to complicate the simple problem. Next, let's consider another requirement. When a parameter of the template class is of a certain type, we need to specifically define a member function: template <typename T1, typename T2> struct Base {// other function //.... void Func () {cout <"primary function" <endl ;}}; void test2 () {Base <int, int> a;. func (); Base <int, string> B; B. func ();} int main () {test2 ();} requires the template class above. If T2 is of the string type, we need to override Func, other member functions are implemented in the same way in any situation. With the implementation experience of the above example, it is much easier for us to solve this problem. Method 1: template <typename T1, typename T2> struct Base {// other function //.... void Func () {if (typeid (std: string) = typeid (T2) {cout <"specialization function" <endl ;} else {cout <"primary function" <endl ;}}; comments: this feature is implemented by running-time type identification (RTTI). You need to enable relevant compilation options and make it inefficient. Method 2: template <typename T1, typename T2> struct Base {// other function //.... template <typename T> void FuncImpl () {cout <"primary function" <endl ;}template <> void FuncImpl <string> () {cout <"specialization function" <endl ;}void Func () {FuncImpl <T2> () ;}}; comment: method 3 through member function specialization: template <typename T1, typename T2> struct Base {// other function //.... template <typename T> class Type2Type {ty Pedef T type ;}; template <typename T> void FunImpl (const Type2Type <T>) {cout <"primary function" <endl ;} template <typename T> void FunImpl (const Type2Type <string>) {cout <"specialization function" <endl;} void Func () {FunImpl <T2> (Type2Type <T2> () ;}}; comment: Method 4 through function overloading: template <typename T> struct IsString {enum {value = false };}; template <> struct IsString <string> {enum {value = true };}; Template <typename T1, typename T2> struct Base {// other function //.... void Func () {if (IsString <T2 >:: value) {cout <"specialization function" <endl ;} else {cout <"primary function" <endl ;}}; comment: It is implemented by determining the compile-time type. Method 5: template <typename T3, typename T4> struct must_be_same_type {enum {ret = 0 };}; template <> struct must_be_same_type <string, string >{enum {ret = 1 };}; template <typename T1, typename T2> class Base {public: // other function //.... void Func () {if (must_be_same_type <T2, string >:: ret) {cout <"specialization function" <endl ;} else {cout <"primary function" <endl ;}}; comment: similar to Method 4, it is not implemented Type is different. Finally, I will discuss my own problems. We are writing an event delegate class, which is roughly as follows: template <typename return_type, typename first_type, typename second_type> class CEvent {public: // other function //.... return_type operator () (first_type p1, second_type p2) {return_type ret = return_type ();//... // ret = invoker (p1, p2); return ret ;}}; void test3 () {CEvent <int, int, int> e1; e1 (1, 2 ); CEvent <void, int, int> e2; e2 (1, 2);} int main () {tes T3 ();} we can see that when the return_type is void, the above Code fails to be compiled because there is no return value, so we can only specialize in this situation: template <typename first_type, typename second_type> class CEvent <void, first_type, second_type> {public: // other function //.... void operator () (first_type p1, second_type p2 ){//... // invoker (p1, p2); return;}; however, we will find that only this operator () function must be specially treated according to return_type, and other functions will always be the same. The question we have now is how we can only specialize in this function. First, we will think of the following implementation method: template <typename T> struct IsVoid {enum {value = false };}; template <> struct IsVoid <void> {enum {value = true };}; template <typename return_type, typename first_type, typename second_type> class CEvent {public: other function .... return_type operator () (first_type p1, second_type p2) {if (IsVoid <return_type >:: value) {cout <"return type is void" <endl; //... // invoker (p1, p2 );} Else {cout <"return type is not void" <endl; return_type ret = return_type ();//... // ret = invoker (p1, p2); return ret ;}}; but we will soon find that the if statement is compiled in this case, therefore, if the return_type is void, compilation fails. The problem we need to solve is how to convert this if statement into a function overload, so we think of the following implementation: template <typename T> struct IsVoid {enum {value = false };}; template <> struct IsVoid <void> {enum {value = true };}; template <int v> class Int2Type {enum {value = v };}; template <typename return_type, typename first_type, typename second_type> class CEvent {public: // other function //.... return_type InvokerImpl (first_type p1, second_type p2, Int2Type <true>) {cout <"Return type is void" <endl ;//... // invoker (p1, p2);} www.2cto.com return_type InvokerImpl (first_type p1, second_type p2, Int2Type <false>) {cout <"return type is not void" <endl; return_type ret = return_type ();//... // ret = invoker (p1, p2); return ret;} return_type operator () (first_type p1, second_type p2) {return InvokerImpl (p1, p2, int2Type <IsVoid <return_type >:: value> () ;}}; First, the implementation is identified by the type during compilation, and then the corresponding bool value is converted to different types after the recognition, and then implemented by using different types of function overloading. Finally, we can see that C ++ is so complex that it is speechless from the Compilation Time To the runtime, from the object-oriented programming to the general model programming to the template metaprogramming, it is also powerful and speechless, and the C ++ language itself is constantly evolving (C ++ 11). The same problem often has multiple solutions in C ++, these solutions are simple, complex, efficient, and inefficient. Our goal is to use the C ++ tool to find a simple and efficient solution.