首页 > 代码库 > C++ Primer 学习笔记_85_模板与泛型编程 --模板特化[续]

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

模板与泛型编程

--模板特化[]



三、特化成员而不特化类

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

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

    QueueItem<const char *> *pt = new QueueItem<const char *>(new_item);

    if(empty())
    {
        head = tail = pt;
    }
    else
    {
        tail -> next = pt;
        tail = pt;
    }
}

template<>
void Queue<const char *>::pop()
{
    QueueItem<const char *> *p = head;
    delete head -> item;
    head = head -> next;
    delete p;
}

类类型Queue<constchar*> 将从通用类模板定义实例化而来,pushpop函数例外。调用Queue<constchar*> 对象的pushpop函数时,将调用特化版本号;调用随意其它成员时,将从类模板为constchar* 实例化一个通用版本号



特化声明

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

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

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



四、类模板的部分特化

假设类模板有一个以上的模板形參,我们或许想要特化某些模板形參而非所有。使用类模板的部分特化能够实现这一点:

template <class T1,class T2>
class some_templates
{
    //...
};

template <class T1>
class some_templates<T1,int>
{
    //...
};

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



使用类模板的部分特化

类模板的名字后面必须接着模板实參列表,前面样例中,模板实參列表是<T1,int>。由于第一个模板形參的实參值未知,实參列表使用模板形參名T1作为占位符,还有一个实參是类型int,int而部分特化模板。

像不论什么其它类模板一样,部分特化是在程序中使用时隐式实例化:

    some_templates<int,string> foo;	//使用泛型版本号
    some_templates<string,int> bar;	//使用特化版本号

注意第二个变量的类型,形參为stringintsome_template,既能够从普通类模板定义实例化,也能够从部分特化实例化。为什么选择部分特化来实例化该模板呢?当声明了部分特化的时候,编译器将为实例化选择最特化的模板定义,当没有部分特化能够使用的时候,就使用通用模板定义foo的实例化类型与提供的部分特化不匹配,因此,foo的类型必定从通用类模板实例化。部分特化仅仅用于实例化第二个类型为intsome_template类型。

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