模板特化
这里只针对函数模板讨论一下模板匹配的问题。
参考链接:
一下的代码如果没有说明,都是从以上连接里面拷贝过来的。
#include
using namespace std;
//base
template
void func (const T &v1, const T &v2) {
cout<<"template"< }
//A
template <>
void func (char* const &v1, char* const &v2) {
cout<<"Specialization: char*"< }
//B
template <>
void func (const char* const &v1, const char* const &v2) {
cout<<"Specialization: const char*"< }
//C
template <>
void func ( char const (&v1)[6], char const (&v2)[6]) {
cout<<"Specialization: const char[6]"< }
//D
template <>
void func ( char const (&v1)[6], char const (&v2)[6]) {
cout<<"Specialization: char[6]"< }
int main()
{
char *p1 = "hello";
char *p2 = "world";
func(p1, p2); //Specialization: char* (1)
char * const p3 = "hello";
char * const p4 = "world";
func(p3, p4); //Specialization: char* (2)
const char *p5 = "hello";
const char *p6 = "world";
func(p5, p6); //Specialization: const char* (3)
const char * const p7 = "hello";
const char * const p8 = "world";
func(p7, p8); //Specialization: const char* (4)
char a1[6] = "hello";
char a2[6] = "world";
func(a1, a2); //Specialization: char[6] (5)
const char a3[6] = "hello";
const char a4[6] = "world";
func(a3, a4); //Specialization: char[6] (6)
return 0;
}
解释:
1.首先A,B,C,D都是模板base的特化版本,而且特化版本需要再base之后声明。有一点base是基类,特别模板是派生类的感觉。
2.A,B,D都可以看做是base中的T替换掉特换版本中的type得来,但是C却不是,原因见注1。
3. 推导应该使用的特化版本时,将采用最精确的版本。
(1)是匹配A而来,其实这还不是最精确匹配,只是char* 可以匹配const char*而已,如果再加一个模板base2和特别版本如下:
//base2
template
void func (T &v1, T &v2) {
cout<<"template"< }
//A2
template <>
void func (char* &v1, char* &v2) {
cout<<"Specialization: char*"< }
此时,(1)将匹配到A2,而不是A,因为A2更精确。
另外,如果只是加一个A2,而不加base2是不正确的,因为从base1不能推导出A2。
注1:一点模板参数推导规则
推导规则1:“The top-level cv-qualifiers on the template-parameter are ignored when determining its type.” 指
toplevel限定符再模板参数推导的时候会被忽略掉,const char arr[]中,const就是top-level限定符;const char* const pValue
中,第二个const才是top-level限定符。他们再模板参数推导的时候都会被忽略掉。
推导规则2:“const转换:接受const引用或const指针的函数可以分别用非const对象的引用或指针来调用,而无须产生新的实例化。
”
4.(2)通过模板规则1后,变得和(1)情况一样。
5.(3)类型为const char*正好匹配B。
6.(4)模板规则1
7.(5)类型为char [6],匹配D
8.(6)模板规则1
//另一段代码
#include
using namespace std;
template
void func (T &v1, T &v2) {
cout<<"template"< }
template <>
void func (const char* &v1, const char* &v2) {
cout<<"Specialization: const char*"< }
template <>
void func (char (&v1)[6], char (&v2)[6]) {
cout<<"Specialization: char[6]"< }
int main()
{
const char * p1 = "hello";
const char * p2 = "world";
func(p1, p2); //Specialization: const char*
const char * const p3 = "hello";
const char * const p4 = "world";
func(p3, p4); //template
char a1[6] = "hello";
char a2[6] = "world";
func(a1, a2); //Specialization: char[6]
const char a3[6] = "hello";
const char a4[6] = "world";
func(a3, a4); //template
return 0;
}
(whyglinux 的)解释:
模板参数推导的前提条件是首先函数的签名特征要符合。在上面给出的第一个例子中,p1、p2、a1、a2 等变量都不是 const 限定的
,而 a3、a4、p3、p4 都是 const 限定的(这样的 const 就是一个 top-level 限定符);而你给出的两个特化函数的参数不是
const 引用的形式,所以如果用 a3、a4 或者 p3、p4 等 const 限定的变量来作为函数参数的话是不可能与这两个特化函数相匹配
的,所以对这两个特化函数进行模板参数推导也就没有必要了。
阅读(1022) | 评论(0) | 转发(0) |