C++模板之函数模板实例化和具体化
模板声明 template<typename/class T>, typename比class最近后添加到C++标准。
常规模板,具体化模板,非模板函数的优先调用顺序。
非模板函数(普通函数)> 具体化模板函数 > 常规模板
显示具体化:
具体化表示为某一特定的类型重写函数模板,声明的含义是使用独立的,专门的函数定义显示地为 特定类型生成函数定义。
为什么要有显示具体化?处理模板函数所不能处理的特殊情况。显式具体化显式具体化也是基于函数模板的,只不过在函数模板的基础上,添加一个专门针对特定类型的、实现方式不同的具体化函数。
显示具体化声明在关键字template后包含<>.
如:
- template<> void swap<job>(job &j1, job &j2);
vs2013不支持:
- void swap(Any &a, Any &b);
- struct job
- {
- char name[40];
- double salary;
- int floor;
- };
- template<> void swap<job>(job &j1, job &j2);
- void Show(job &j);
- int main(){
- using namespace std;
- template void swap<job>(job &, job &);
- int i = 10, j = 20;
- swap(i, j);
- return 0;
- }
- template<typename Any>
- void swap(Any &a, Any &b){
- Any temp;
- temp = a;
- a = b;
- b = temp;
- }
- template<> void swap<job>(job &j1, job &j2){
- double temp_sal;
- temp_sal = j1.salary;
- j1.salary = j2.salary;
- j2.salary = temp_sal;
- }
隐式实例化
在发生函数模板的调用时,不显示给出模板参数而经过参数推演,称之为函数模板的隐式模板实参调用(隐式调用)。如:
template <typename T> void func(T t)
{
cout<<t<<endl;
}
func(5);//隐式模板实参调用
显示实例化:
实例:如函数调用swap(i,j)会导致编译器生成swap()的一个实例,该实例使用 int 类型。
句法:声明所需的种类用<>符号指示类型,并在声明前加上关键字template:
为什么要有显示实例化?事实上,编译器只在要调用函数的时候才使用到函数,如果不使用显示实例化,每次调用函数时,模板都会消耗性能去推导使用的是哪个类型的函数,增加了程序运行时的负担;使用了显示实例化,则在编译时就已经处理了函数选择。
- template [函数返回类型] [函数模板名]<实际类型列表>(函数参数列表)
实例化示例:
- template void swap<int>(int, int);
注意:试图在同一个文件(或转换单元)中使用同一种类型的显示实例化和显示具体化声明,会出错。
推荐:可以用在函数调用时,直接显示实例化,而不使用显示实例化声明。
如:
template <typename T>
T add(T x,T y)
{
return x+y;
}
int main()
{
int i1=2,i2=3;
add<int>(i1,i2);
template int add<int>(i1,i2);//尽量用上面一行的写法代替本行
return 0;
}
模范代码:
///**********************************************
/// @file templetAdd.cc
/// @author alex(AlexCthon@qq.com)
/// @date 2018-06-19 21:42:20
///**********************************************/ #include <string.h>
#include <iostream>
using std::cout;
using std::endl;
//模板-->类型参数化-->代码生成器 // 实例化(模板参数推导)
//函数模板 --> 模板函数 //< > 模板参数列表
//1、使用class 或者typename设置类型参数
//2、非类型参数、常量表达式(整型数据)
template <class T>
T add(T x,T y)
{
return x + y;
}
#if 0
template int add<int>(int x,int y)//
{
cout<<"template 显示实例化"<<endl;
return x+y;
}
#endif
template<> int add<int>(int x,int y)//等价于template<>int add(int x,int y)
{
cout<<"template 显示具体化"<<endl;
return x+y;
}
//模板的特化版本,不能独立用于通用版本
//针对特殊情形,但一定要在通用版本存在时才能用
template<>//把这行注释掉也是可以的,那表明下面的这个方法是重载了模板函数
const char* add(const char*lhs,const char* rhs)
{
char*tmp = new char[strlen(lhs)+strlen(rhs)+1]();
strcpy(tmp,lhs);
strcat(tmp,rhs);
return tmp;
}
#if 0
//普通函数与函数模板可以重载
//普通函数优先级高于模板函数
int add(int x,int y)//可以重载,因为形参类型不一样
{
return x + y;
}
#endif
//函数模板与函数模板之间也可以重载
//函数模板的声明
template <typename T>
T add(T x,T y,T z); //c++11的特性
//c++11以前的版本对于函数模板而言,非类型参数不能设置默认值
//非类型参数必须是整形类数据(bool、char、int、long、long long)
template <typename T,int num=10>
int func(T x,T y)
{
return x*y*num;
}
int main()
{
int a=3,b=4;
double c1=1.2,c2=2.3,c3=4.9;
char ch1='a',ch2=2;
//template char add<char>(char x,char y);//试图在同一个文件(或转换单元)中使用同一种类型的显示实例化和显示具体化声明,会出错
func(ch1,ch2);
const char *p1="hello";
const char *p2="good"; cout << "int + int = " << add(a,b) << endl;//隐式实例化
cout << "double + double = " << add<int>(c1,c2) << endl;//显示实例化
cout << "char + char = " << add(ch1,ch2) << endl;
cout << "double + double = " << add(c1,c2,c3) << endl;
cout << "int + int = " << func<double,8>(a,b) << endl;//常量传递的方式
//cout << "a+d1=" << add(a,c1) << endl;//error,模板参数必须严格一致 cout << add(p1,p2) << endl;
return 0;
}
//函数模板的实现
template <class T>
T add(T x,T y,T z)
{
return x +y + z;
}
总结:
隐式实例化指的是:在使用模板之前,编译器不生成模板的声明和定义实例。只有当使用模板时,编译器才根据模板定义生成相应类型的实例。如:int i=0, j=1;swap(i, j); //编译器根据参数i,j的类型隐式地生成swap<int>(int &a, int &b)的函数定义。Array<int> arVal;//编译器根据类型参数隐式地生成Array<int>类声明和类函数定义。
显式实例化:当显式实例化模板时,在使用模板之前,编译器根据显式实例化指定的类型生成模板实例。如前面显示实例化(explicit instantiation)模板函数和模板类。其格式为:template typename function<typename>(argulist);template class classname<typename>;显式实例化只需声明,不需要重新定义。编译器根据模板实现实例声明和实例定义。
显示具体化:对于某些特殊类型,可能不适合模板实现,需要重新定义实现,此时可以使用显示具体化(explicite specialization)。显示实例化需重新定义。格式为:template<> typename function<typename>(argu_list){...};template<> class classname<typename>{...};
C++模板之函数模板实例化和具体化的更多相关文章
- C++—模板(1)模板与函数模板
1.引入 如何编写一个通用加法函数?第一个方法是使用函数重载, 针对每个所需相同行为的不同类型重新实现这个函数.C++的这种编程机制给编程者极大的方便,不需要为功能相似.参数不同的函数选用不同的函数名 ...
- C++ 函数重载,函数模板和函数模板重载,选择哪一个?
重载解析 在C++中,对于函数重载.函数模板和函数模板重载,C++需要有一个良好的策略,去选择调用哪一个函数定义(尤其是多个参数时),这个过程称为重载解析. (这个过程将会非常复杂,但愿不要遇到一定要 ...
- C++入门经典-例9.1-函数模板,函数模板的作用,使用数组作为模板参数
1:函数模板不是一个实在的函数,因此编译器不能为其生成可执行的代码.定义函数模板只是一个对函数功能框架的描述,在具体执行时,将根据传递的实际参数决定其功能. 2:函数模板定义的一般形式如下: temp ...
- C++ 模板学习 函数模板、类模板、迭代器模板
使用模板能够极大到使得代码可重用. 记录一下,方便后续使用. 1. 函数模板,支持多种类型参数 #include <stdio.h> #include <math.h> //函 ...
- C++面向对象编程之类模板、函数模板等一些补充
1.static数据 和 static函数: 对于 非static函数 在内存中只有一份,当类对象调用时,其实会有该对象的this pointer传进去,那个函数就知道要对那个对象进行操作: stat ...
- C++_进阶之函数模板_类模板
C++_进阶之函数模板_类模板 第一部分 前言 c++提供了函数模板(function template.)所谓函数模板,实际上是建立一个通用函数,其函数类型和形参类型不具体制定,用一个虚拟的类型来 ...
- C++模板之隐式实例化、显示实例化、隐式调用、显示调用和模板特化详解
模板的实例化指函数模板(类模板)生成模板函数(模板类)的过程.对于函数模板而言,模板实例化之后,会生成一个真正的函数.而类模板经过实例化之后,只是完成了类的定义,模板类的成员函数需要到调用时才会被初始 ...
- C++基础--函数模板
函数模板是通用的函数描述,其使用泛型来定义函数.其实就是有些操作,如果撇开具体的变量的数据类型,其操作是一样的如果我们将这些操作写成一个模板,在调用不同变量的时候就设定好变量类型就可了,后续的操作基本 ...
- C++进阶-1-模板基础(函数模板、类模板)
C++进阶 模板 1.1 函数模板 1 #include<iostream> 2 using namespace std; 3 4 // 模板 5 6 // 模板的简单实例 7 // 要求 ...
随机推荐
- DVBS/S2在数字电视系统中的应用 三 (LNB介绍)
DVBS/S2在数字电视系统中的应用 三 (LNB介绍) 老谢在前面两篇文章中(例如以下).都有提到LNB这一概念. DVBS/S2在数字电视系统中的应用 一 (DVBS/S2接收系统Block Di ...
- Google Chrome浏览器之删除Goolge搜索结果重定向插件Remove Google Redirects
https://chrome.google.com/webstore/detail/remove-google-redirects/ccenmflbeofaceccfhhggbagkblihpoh?h ...
- ARP协议(1)什么是ARP协议
这是最近在看<TCP/IP具体解释>系列书总结出来的,之后会陆续把其它协议部分分享出来. 我尽量以简单易读.易懂的方式呈现出来,可是,因为文笔和水平有限.有些地方或许存在描写叙述上的不足或 ...
- 斯坦福公开课:Developing IOS 8 App with Swift(1-3)心得体会
最近开始学习Swift开发移动程序.跟随斯坦福大学的公开课进行自学. 这真是一个美好的时代,虽然不能在斯坦福求学,但是可以观看录制的授课录像.讲义,好似老师在给我们上课一样! 心得: 1.每节课信息量 ...
- EC2的维护更新
2014年9月28日 近期几天.我们收到了一些客户关于我们即将进行维护更新的问题.下面是AWS全球Blog网站对这个问题的说明,供客户參照. 我们已经開始通知那些受影响的客户,关于我们即将实施的 ...
- 前端-DDoS攻击
下面的脚本(略有修改)就会向受害网站发送大量的请求: function imgflood() { var TARGET = 'example.com' var URI = '/index.php?' ...
- git操作演示
阶段一: git init git config --global user.email "you@example.com" git config --global user.na ...
- qemu-kvm编译错误
今天编译了下qemu-kvm,死活编不过,错误信息如下: CC block/qcow2-snapshot.oIn file included from ./qemu-common.h:6:0, ...
- bb=Discuz与 Discuz! X ,Discuz!NT区别
没加x的,仅仅是单独的论坛. 加了x的,模块加了很多了,门户,家园,排行榜,群组,都是Discuz! X上的,而Discuz!上没有,所以说Discuz! X更加适用于建设门户网 Discuz! X ...
- Greenplum使用简明手册
GP服务启停 su - gpadmin gpstart #正常启动 gpstop #正常关闭 gpstop -M fast #快速关闭 gpstop –r #重启 gpstop –u #重新加载配置文 ...