C++ Primer 学习笔记_85_模板与泛型编程 --模板特化[续]

2014-11-24 13:23:14 · 作者: · 浏览: 28

模板与泛型编程

--模板特化[续]



三、特化成员而不特化类

除了特化整个模板之外,还可以只特化push和pop成员。我们将特化push成员以复制字符数组,并且特化pop成员以释放该副本使用的内存:

template<>
void Queue
  
   ::push(const char *const &val)
{
    char *new_item = new char[sizeof(val) + 1];
    strncpy(new_item,val,sizeof(val)+1);

    QueueItem
   
     *pt = new QueueItem
    
     (new_item); if(empty()) { head = tail = pt; } else { tail -> next = pt; tail = pt; } } template<> void Queue
     
      ::pop() { QueueItem
      
        *p = head; delete head -> item; head = head -> next; delete p; } 
      
     
    
   
  

类类型Queue 将从通用类模板定义实例化而来,而push和pop函数例外。调用Queue 对象的push或 pop函数时,将调用特化版本;调用任意其他成员时,将从类模板为constchar* 实例化一个通用版本。



特化声明

成员特化的声明与其他函数模板特化一样,必须以空的模板形参表开头:

template <>
void Queue
  
   ::push(const char *const &);
template <>
void Queue
   
    ::pop(); 
   
  

这些声明应放在Queue类的头文件中。



四、类模板的部分特化

如果类模板有一个以上的模板形参,我们也许想要特化某些模板形参而非全部。使用类模板的部分特化可以实现这一点:

template 
  
   
class some_templates
{
    //...
};

template 
   
     class some_templates
    
      { //... }; 
    
   
  

类模板的部分特化本身也是模板。部分特化的定义看来像模板定义,这种定义以关键字template开头,接着是由尖括号(<>)括住的模板形参表。部分特化的模板形参表是对应的类模板定义形参表的子集。some_template的部分特化只有一个名为T1的模板类型形参,第二个模板形参T2的实参已知为int。部分特化的模板形参表只列出未知模板实参的那些形参



使用类模板的部分特化

类模板的名字后面必须接着模板实参列表,前面例子中,模板实参列表是 。因为第一个模板形参的实参值未知,实参列表使用 模板形参名 T1 作为占位符,另一个实参是类型int,为int而部分特化模板。

像任何其他类模板一样,部分特化是在程序中使用时隐式实例化:

    some_templates
  
    foo;	//使用泛型版本
    some_templates
   
     bar; //使用特化版本 
   
  

注意第二个变量的类型,形参为string和 int的some_template,既可以从普通类模板定义实例化,也可以从部分特化实例化。为什么选择部分特化来实例化该模板呢 当声明了部分特化的时候,编译器将为实例化选择最特化的模板定义,当没有部分特化可以使用的时候,就使用通用模板定义。foo的实例化类型与提供的部分特化不匹配,因此,foo的类型必然从通用类模板实例化。部分特化只用于实例化第二个类型为int的some_template类型。

部分特化的定义与通用模板的定义完全不会冲突。部分特化可以具有与通用类模板完全不同的成员集合。类模板成员的通用定义永远不会用来实例化类模板部分特化的成员