🥬模板特例化
2022-6-15
| 2023-8-2
0  |  阅读时长 0 分钟
type
status
date
slug
summary
tags
category
icon
password
Property
 
 
一个模板并不总是能满足可以所有使其实例化的模板实参的要求。在某些情况下,通用的模板定义还可能是错误的:通用的定义可能无法编译或者做错误的事情。在某些情况下,可以利用特定类型的知识来写出更加有针对性且高效的代码(至少比从模板中实例化更加高效)。当不想或者不能使用模板版本时,可以定义一个类或函数模板的特例化版本。如:
以上两个函数,(2) 函数只能对数组或字符串字面量进行调用,如果传入了字符指针,那么总是 (1) 函数被调用。
为了处理字符指针的清醒,需要给 (1) 模板定义特例(template specialization)。特例是模板的另外一个定义,其中一个或多个目标那参数具有特定的类型。
 
 
定义函数模板特例
当定义函数模板特例时,需要给原模板中所有的模板参数提供实参。为了表示特例化一个模板,需要使用关键字 template后跟随一个空的尖括号<> ,空的尖括号表示给原模板中的所有模板参数都提供了实参:
这里最难理解的部分就是特例中的函数参数类型必须与模板中的对应类型一样,这里对应的是 (1) 函数,与类型别名一样,当模板参数类型与指针、const 混杂在一起时也会变得复杂。此处 T 的类型时 const char* 即指向 const 对象的指针。
 
 
函数重载 vs 模板特例
当定义函数模板特例时,就是在抢编译器的工作。就是说我们给原始模板的特定实例提供我们自己的定义。这里特别需要留意的是特例是一个实例;它不是重载;由于特例实例化一个模板;它不重载这个模板,因而,特例不会影响函数匹配过程。
如果将模板特例定义为独立的非模板函数将会影响函数匹配。如 compare("hi", "mom") 如果在将 (3) 定义为模板特例时,选择的依然是 (2) 函数,原因是它更加的特化(specialized)而 (3) 是不参与函数匹配的,而如果将 (3) 定义为接受指针的非模板函数,此时 (3) 将参与函数匹配并且将选择 (3) ,原因是非模板函数是最特化的版本。
为了定义个模板的特例,原始模板必须被声明在作用域内。并且,在任何使用模板实例的代码之前必须特例的声明必须在作用域内,如果不这么做的话就很可能会从模板中实例化出一个与要求不符合的函数,这种错误通常是很难定位的。
模板和它的特例应该定义在同一个头文件中,而且同一个名字的所有模板都应该出现在前面,后面跟随这些模板的特例。
 
 
类模板特例
hash<Sales_data> 以 template<> 开始用于表示我们定义一个完全的模板特例。在特例中只需要定义需要另行定义的成员函数,可以将特例的成员函数定义在类内或者类外。
 
 
类模板部分特例
与函数模板不同的是,类模板特例不用必须提供所有的模板参数实参。可以指定其中一些但不是全部的模板参数(或者参数的某个方面,如:左值引用或右值引用性质)。一个类模板的部分特例(partial specialization)本身是一个模板。用户必须给特例没有固定的模板参数提供实参。
只能部分特化一个类模板,但不能部分特化函数模板。
部分特化的一个很好的例子是 remove_reference 类,实现如下:
该模板的第一个定义是最通用的一个版本,可以实例化任何一个类型。它使用模板实参作为成员类型 type 的类型。后面的两个类是原始模板的部分特例。由于部分特例也是一个模板,所以需要先定义模板参数,与别的特例一样,部分特例具有与其进行特化的模板一样的名字,特例的模板参数列表包含所有类型没有完全固定的模板参数,在类名之后的尖括号中是特例所指定的模板实参,这些实参与原始模板中的参数在位置上一一对应。
部分特例的模板参数列表是原始模板参数列表的一个子集,在此例中,特例具有与原始模板相同数目的模板参数,然而,特例中的参数类型却与原始模板不一样,特例分别使用了左值引用或右值引用类型。以下是一些使用场景:
 
仅仅特化成员而不是整个类
相比于特化整个模板,可以只特化特定的成员函数。如:
 
此例中仅特化一个 Foo<int> 的一个成员 BarFoo<int> 的其他成员将由Foo模板提供:
当将 Foo 运用于任何类型而不是 int 时,成员照旧进行实例化,而当将 Foo 运用 int 时,除了 Bar 之外的成员照旧进行实例化,只有 Bar 将会使用特化的版本。
 
 

全特化和半特化

全特化:全特化即是将模板参数列表中所有的参数都确定化。
 
半特化(又称偏特化):将部分参数类表中的一部分参数特化。
半特化还有一种表现方式,半特化可以用来对参数进行更进一步的限制。
 
限制两个参数都是引用
  • C++
  • 可变参数模板tuple类型
    目录