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

模板与泛型编程

--模板特化[续]

三、特化成员而不特化类

除了特化整个模板之外,还可以只特化push和pop成员。我们将特化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*> 将从通用类模板定义实例化而来,而push和pop函数例外。调用Queue<constchar*> 对象的push或 pop函数时,将调用特化版本;调用任意其他成员时,将从类模板为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>
{
    //...
};

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

使用类模板的部分特化

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

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

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

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

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

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

时间: 2024-10-13 10:48:44

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

C++ Primer 学习笔记_5_变量和基本类型(续2)

 变量和基本类型 七.枚举 枚举不但定义了整数常量集,并且还把它们聚集成组. 枚举与简单的const常量相比孰优孰劣, 通过以下一段代码. 一看便知: [cpp] view plaincopyprint? enum {input, output, append}; const int input = 0; const int output = 1; const int append = 2; enum {input, output, append}; const int input = 0;

C++ Primer 学习笔记_4_变量和基本类型(续1)

 变量和基本类型 四.const限定符 [cpp] view plaincopyprint? #include <iostream> int main() { //for循环语句存在两个问题 for (int index = 0;index != 512; ++index) { //... } return 0; } /* *1.程序的可读性:存在魔数512[魔数:他的意义在上下文中并没有体现出来,好像这个数是魔术般变出来的] *2.程序的可维护性... */ #include <i

C++ Primer 学习笔记_77_模板与泛型编程 --实例化

模板与泛型编程 --实例化 引言: 模板是一个蓝图,它本身不是类或函数.编译器使用模板产生指定的类或函数的特定版本号.产生模板的特定类型实例的过程称为实例化. 模板在使用时将进行实例化,类模板在引用实际模板类型时实例化,函数模板在调用它或用它对函数指针进行初始化或赋值时实例化. 1.类的实例化 当编写Queue<int>qi时,编译器自己主动创建名为Queue<int>的类.实际上,编译器通过又一次编写Queue模板,用类型int取代模板形參的每次出现而创建Queue<int

C++ Primer 学习笔记_81_模板与泛型编程 --类模板成员[续1]

模板与泛型编程 --类模板成员[续1] 二.非类型形参的模板实参 template <int hi,int wid> class Screen { public: Screen():screen(hi * wid,'#'), cursor(hi * wid),height(hi),width(wid) {} //.. private: std::string screen; std::string::size_type cursor; std::string::size_type height

C++ Primer 学习笔记_82_模板与泛型编程 --类模板成员[续2]

模板与泛型编程 --类模板成员[续2] 六.完整的Queue类 Queue的完整定义: template <typename Type> class Queue; template <typename Type> ostream &operator<<(ostream &,const Queue<Type> &); template <typename Type> class QueueItem { friend clas

C++ Primer 学习笔记_75_模板与泛型编程 --模板定义

模板与泛型编程 --模板定义 引言: 所谓泛型程序就是以独立于不论什么特定类型的方式编写代码.使用泛型程序时,我们须要提供详细程序实例所操作的类型或值. 模板是泛型编程的基础.使用模板时能够无须了解模板的定义. 泛型编程与面向对象编程一样,都依赖于某种形式的多态性.面向对象编程中的多态性在执行时应用于存在继承关系的类.我们能够编写使用这些类的代码,忽略基类与派生类之间类型上的差异.仅仅要使用基类的引用或指针,基类类型或派生类类型的对象就能够使用同样的代码. 在泛型编程中,我们所编写的类和函数能够

C++ Primer 学习笔记_84_模板与泛型编程 --模板特化

模板与泛型编程 --模板特化 引言: 我们并不总是能够写出对全部可能被实例化的类型都最合适的模板.某些情况下,通用模板定义对于某个类型可能是全然错误的,通用模板定义或许不能编译或者做错误的事情;另外一些情况下,能够利用关于类型的一些特殊知识,编写比从模板实例化来的函数更有效率的函数. compare函数和 Queue类都是这一问题的好样例:与C风格字符串一起使用进,它们都不能正确工作. compare函数模板: template <typename Type> int compare(cons

C++ Primer 学习笔记_83_模板与泛型编程 --一个泛型句柄类

模板与泛型编程 --一个泛型句柄类 引言: [小心地雷] 这个例子体现了C++相当复杂的语言应用,理解它需要很好地理解继承和模板.在熟悉了这些特性之后再研究这个例子也许会帮助.另一方面,这个例子还能很好地测试你对这些特性的理解程度. 前面示例的Sales_item和Query两个类的使用计数的实现是相同的.这类问题非常适合于泛型编程:可以定义类模板管理指针和进行使用计数.原本不相关的Sales_item类型和 Query类型,可通过使用该模板进行公共的使用计数工作而得以简化.至于是公开还是隐藏下

C++ Primer 学习笔记_79_模板与泛型编程 --模板编译模型

模板与泛型编程 --模板编译模型 引言: 当编译器看到模板定义的时候,它不立即产生代码.只有在用到模板时,如果调用了函数模板或定义了模板的对象的时候,编译器才产生特定类型的模板实例. 一般而言,当调用函数时[不是模板],编译器只需看到函数的声明.类似的,定义类类型的对象时,类定义必须可用,但成员函数的定义不是必须存在的.因此,应该将类定义和函数声明放在头文件中,而普通函数和类成员函数的定义放在源文件中. 模板则不同:要进行实例化,编译器必须能够访问定义模板的源代码.当调用函数模板或类模板的成员函