C++模板实战4:模板特化

2014-11-24 07:27:27 · 作者: · 浏览: 0

模板设计的目的就是为了通用,但是某些情形下也有特殊情形独立于通用规则,因此模板需要针对特殊情形进行特化。

1 类模板的特化,在模板类名自后<>内写上特化的类型名,其中<>这部分叫做匹配式,如下:

template
  
   //通用模板
void show();

template<>//特化模板的模板参数,这里不再需要参数故为空,<>不能省略
void show
   
    ();//特化模板,其中
    
     叫匹配式
    
   
  
特化规则如下:

1) 匹配式写在模板类名之后,用<>包住,即使模板特化没有引入新的类型参数,<>也不能省略

2) 匹配式内用逗号隔开的项目列表,如前面的 ,且项目数目必须和通用模板参数个数一致,也就是这里通用模板参数是T、N,所以特化时不能类似于show

3) 匹配式中各项目类型须与通用模板参数类型一致

4) 匹配式项目可以是具体的模板参数值,也可以是特化成具体的类型

5) 当匹配式项目是类型模板参数时,与函数变量类似,模板参数也可以用*、&、const、volatile等修饰

实例如下:

//用于模板型模板参数的模板
template
  
    struct S1;

//模板通例,有三个模板参数,分别是类型参数,非类型参数及模板型参数
template
   
     class SP>//通用模板 struct S; //特例1,可匹配S
    
      template
     
       class SP> struct S
      
       ; //特例2,可匹配S<任意有const修饰的类型, 任意整数, S1> template
       
         class SP> struct S
        
         ; //特例3,完全特例,只能匹配S
         
           template<>//此例是完全特化,其余是部分特化 struct S
          
           ; //特例4,以模板实例作为类型参数值。匹配S
           
            , 10, S1> template
            
              struct S
             
              , 10, S1>; //特例5,错误!匹配式项目数与通例参数数不一致 // template
              
                class SP, typename TT> // struct S
               
                ; //特例6,错误!匹配式项目类型与通例参数类型不同 // template
                
                  // struct S
                 
                  ; //特例7,错误!模板型参数SP与通例中SP类型不一致 // template
                  
                    class SP> // struct S
                   
                    ;
                   
                  
                 
                
               
              
             
            
           
          
         
        
       
      
     
    
   
  

2 类模板匹配按照最佳匹配原则进行匹配,实例如下:

#include 
  
   

template
   
     struct S { std::string id() {return "General";} }; //特例1,约束第三参数必须为char template
    
      struct S
     
       { std::string id() {return "Specialization #1";} }; //特例2,约束第二、第三参数必须均为char template
      
        struct S
       
         { std::string id() {return "Specialization #2";} }; //特例3,约束第一参数必须为int,且第二、第三参数相同 template
        
          struct S
         
           { std::string id() {return "Specialization #3";} }; int main() { using namespace std; cout << S
          
           ().id() << endl; //General cout << S
           
            ().id() << endl; //Specialization #3 cout << S
            
             ().id() << endl; //Specialization #1 cout << S
             
              ().id() << endl; //Specialization #2 //cout << S
              
               ().id() << endl; //可匹配2、3,有歧义 }
              
             
            
           
          
         
        
       
      
     
    
   
  

3 函数模板特化与重载函数,当函数模板完全特例化后和重载函数类似,但是模板实例化代码是编译器在编译期展开的所以是内联的。多个模板实例或用相同类型的普通函数混合在一起的时候函数的匹配规则如下:

1) 最佳匹配原则,按照实参和形参的匹配程度最优选择

2) 普通函数优先于模板实例

3) 模板实例间特化程度高的优先级高

实例如下:

#include
  
   
using namespace std;
template
   
     void fun(T x,N y){ cout<<"#1 "<
    
      void fun(T x,int y){ cout<<"#2 "<
     
      //函数模板不允许部分特化,只能完全特化 //void fun
      
       (T x,char y){ // cout<<"#3 "<<<
       
         void fun
        
         (char x,char y){//完全特化 cout<<"#4 "<
         
           void fun(double x,double y){ cout<<"#5 "<
          
           (1,2);//通用模板 fun
           
            (1,'a');//通用模板 fun<>('a','b');//指定了使用特化版本fun
            
              fun('a','b');//普通函数fun(char x,char y),当没有这个普通函数时调用完全特化版本 fun(3.14,3.14156);//完全特化版本 fun(true);//普通函数fun(bool x) return 0; }
            
           
          
         
        
       
      
     
    
   
  
程序输出:

#1 1 2
#1 1 a
#4 a b
#7 a b
#5 3.14 3.14156
#6 1

4 模板特化用于编译期条件判断,实例如下:

#include 
  
   

template
   
     void print() { print
    
     (); std::cout << i << std::endl; } //特例,终止递归。 template<> void print<1>() { std::cout << 1 << std::endl; } int main() { print<100>();//在编译期展开相当于100条输出语句 }
    
   
  
程序输出:

1

2

....

100