首页
Web开发
Windows程序
编程语言
数据库
移动开发
系统相关
微信
其他好文
会员
首页
>
其他好文
> 详细
模板函数的特化
时间:
2014-08-14 16:48:39
阅读:
340
评论:
0
收藏:
0
[点我收藏+]
标签:
模板
特化
模板特化:就是在实例化模板时,对特定类型的实参进行特殊处理,即实例化一个特殊的实例版本,
当以特化定义时的形参使用模板时,将调用特化版本,模板特化分为全特化和偏特化;
1. 函数模板的特化,只能全特化;
//泛型版本
template
<
class
T>
int
compare(
const
T &v1,
const
T &v2)
{
if
(v1 < v2)
return
-1;
if
(v2 > v1)
return
1;
return
0;
}
对于该函数模板,当实参为两个
char
指针时,比较的是指针的大小,而不是指针指向内容的大小,此时就需要为该函数模板定义一个特化版本,即特殊处理的版本:
//为实参类型 const char * 提供特化版本
template
<>
int
compare<
const
char
*>(
const
char
*
const
&v1,
const
char
*
const
&v2)
{
return
strcmp(v1, v2);
}
a:
template
<>
//空模板形参表
b: compare<
const
char
*>
//模板名字后指定特化时的模板形参即const char *类型,就是说在以实参类型 const char * 调用函数时,将产生该模板的特化版本,而不是泛型版本,也可以为其他指针类型定义特化版本如int *.
c: (
const
char
*
const
&v1,
const
char
*
const
&v2)
//可以理解为: const char * const &v1, 去掉const修饰符,实际类型是:char *&v1,也就是v1是一个引用,一个指向char型指针的引用,即指针的引用,加上const修饰符,v1就是一个指向const char 型指针的 const引用,对v1的操作就是对指针本身的操作,操作方式与指针一致,比如*v1,是正确的;//注意这里的const char *, 由于形参是一个指向指针的const引用,所以调用特化版本时的实参指针类型(并非存储的数据的类型)可以为const也可以为非const,但是由于这里形参指针指向的数据类型为const char *(强调存储的数据是const),所以实参指针所指向的数据类型也必须为const,否则类型不匹配;
//特化版本 (int *)
template
<>
int
compare<
const
int
*>(
const
int
*
const
&v1,
const
int
*
const
&v2)
//v1 和 v2 是指向const 整形变量的const引用;
{
if
(*v1 < *v2)
return
-1;
//像指针一样操作,可以理解v1,v2就是指针,因为它是指针的引用;
if
(*v2 > *v1)
return
1;
}
2. 与其他函数声明一样,应该在一个头文件中包含模板特化的声明,在使用特化模板的源文件中包含该头文件;
注意,函数模板调用时的实参与模板形参不进行常规转换,特化与泛型版本都不进行常规转换,类型必须完全一致,非函数模板在实参调用时进行常规转换;普通函数和函数模板调用时的实参与模板形参都进行两种转换:
(1).
const
转换:接受
const
引用或者
const
指针的函数,可以分别以非
const
对象的引用或者指针来调用,无需产生新实例,如果函数接受非引用类型或者非指针类型,形参类型和实参类型忽略
const
,无论传递
const
还是非
const
对象给非引用类型的函数,都使用相同的实例;
(2). 数组或函数指针的转换:如果模板形参不是引用类型,则对数组或函数类型的实参应用常规转换,数组转换为指向实参第一个元素的指针,函数实参当做指向函数类型的指针;注意:函数模板中,模板形参表中的非类型形参遵循常规转换原则。
//例子:
//16.6.1.h
#include <stdio.h>
#include <string.h>
#include <iostream>
//泛型版本
template
<
typename
T>
int
compare(
const
T &v1,
const
T &v2)
{
std::cout <<
"template <typename T>"
<< std::endl;
if
(v1 < v2)
return
-1;
if
(v2 < v1)
return
1;
return
0;
}
//为实参类型 const char * 提供特化版本
//template <> int compare(const char * const &v1, const char * const &v2) //省略了函数名后边的显示模板实参,因为可以从函数形参表推断出来,本定义与下边的定义都是正确的;
template
<>
int
compare<
const
char
*>(
const
char
*
const
&v1,
const
char
*
const
&v2)
{
std::cout <<
"template <> int compare<const char *>"
<< std::endl;
return
strcmp(v1, v2);
}
//为实参类型 char * 提供特化版本
//template <> int compare(char * const &v1, char * const &v2)
template
<>
int
compare<
char
*>(
char
*
const
&v1,
char
*
const
&v2)
{
std::cout <<
"template <> int compare<char *>"
<< std::endl;
return
strcmp(v1, v2);
}
//16.6.1.cpp
#include <iostream>
#include "16.6.1.h"
using
namespace
std;
int
main()
{
cout << compare(1, 2) << endl;
//根据实参类型进行实参推断,将为该调用实例化int compare(int, int)
char
a[] = {
"abc"
};
//一个普通字符数组,不是指针,形参为引用时,数组大小成为形参的一部分,数组不转换为指针,类型不匹配;
const
char
b[] = {
"abc"
};
//一个常量字符数组,不是指针,类型不匹配;
char
*p =
"ddd"
;
//一个非const指针,指向非const数据,但是特化版本的形参类型是一个指向const数据的const引用,强调了指针指向的数据类型是const,也就是说实参指针指向的数据类型必须是const即指针存储的数据必须是const的,但这里不是因此类型不匹配;
char
*
const
pc =
"ddd"
;
//一个const指针,指向非const数据,类型不匹配,原因同上,和指针是否是const没关系,和指针存储的数据类型有关;
const
char
*
const
pc =
"ddd"
;
//一个const指针,指向const数据,满足特化版本的形参(一指向const数据的const引用),类型匹配;
const
char
* pc =
"ddd"
;
//一个非const指针,指向const数据,类型匹配,原因同上;
//为实参类型 const char * 提供特化版本
const
char
*pa =
"abc"
;
// 或者 const char * const pa = "abc"; 与指针指向数据类型是const还是非const有关,而与指针是const还是非const没关系,因为,特化版本的形参类型是一个指向指针的cosnt引用,因此不会改变指针的值,所以指针本身是const还是非cosnt没有关系,但是由于特化版本形参的引用指向的指针所指向的数据类型是const,所以不能使用一个指向非const数据的指针调用特化版本,因为数据类型不匹配;
const
char
*pb =
"bbd"
;
cout << compare(pa, pb) << endl;
// 根据实参类型为该调用实例化特化版本int compare(const * const &v1, const * const &v2), 函数模板调用时的实参与模板形参不进行常规转换;由于编译器对特化版本不进行实参与形参的常规转换,所以调用的实参类型必须与特化版本的声明完全一致,否则将从泛型版本进行实例化,或者函数匹配错误;由于compare声明的形参都是const char *即char *型指针存储的是const数据,所以不能传递一个存储了非const数据的char *型指针(尽管此时的cosnt char *形参不会改变实参指针指向的值),也不能传递一个const数组名字(此时数组名不会转换为指针),必须传递一个指向const数据的指针,即代码中的 const char *pa,类型必须完全匹配;
//为实参类型 char * 提供特化版本
char
*pc =
"ccc"
;
char
*pd =
"ddd"
;
cout << compare(pc, pd) << endl;
return
0;
//char * 与 const char * 是两个不同的数据类型(前者存储的数据是常量与后者存储的数据是非常量),虽然可以将类型 char * 通过常规转换,转换成 const char *,但是作为模板实参,在模板实参推断时,不会把函数调用时的实参类型 char * 转换为模板形参类型const char *,所以必须提供两个特化版本。
}
运行结果:
template
<
typename
T>
-1
template
<>
int
compare<
const
char
*>
-1
template
<>
int
compare<
char
*>
-1
模板函数的特化,布布扣,bubuko.com
模板函数的特化
标签:
模板
特化
原文地址:http://blog.csdn.net/nyist327/article/details/38559287
踩
(
0
)
赞
(
0
)
举报
评论
一句话评论(
0
)
登录后才能评论!
分享档案
更多>
2021年07月29日 (22)
2021年07月28日 (40)
2021年07月27日 (32)
2021年07月26日 (79)
2021年07月23日 (29)
2021年07月22日 (30)
2021年07月21日 (42)
2021年07月20日 (16)
2021年07月19日 (90)
2021年07月16日 (35)
周排行
更多
分布式事务
2021-07-29
OpenStack云平台命令行登录账户
2021-07-29
getLastRowNum()与getLastCellNum()/getPhysicalNumberOfRows()与getPhysicalNumberOfCells()
2021-07-29
【K8s概念】CSI 卷克隆
2021-07-29
vue3.0使用ant-design-vue进行按需加载原来这么简单
2021-07-29
stack栈
2021-07-29
抽奖动画 - 大转盘抽奖
2021-07-29
PPT写作技巧
2021-07-29
003-核心技术-IO模型-NIO-基于NIO群聊示例
2021-07-29
Bootstrap组件2
2021-07-29
友情链接
兰亭集智
国之画
百度统计
站长统计
阿里云
chrome插件
新版天听网
关于我们
-
联系我们
-
留言反馈
© 2014
mamicode.com
版权所有 联系我们:gaon5@hotmail.com
迷上了代码!