模板声明 template<typename/class T>,  typename比class最近后添加到C++标准。

常规模板,具体化模板,非模板函数的优先调用顺序。

非模板函数(普通函数)> 具体化模板函数 > 常规模板

显示具体化:

具体化表示为某一特定的类型重写函数模板,声明的含义是使用独立的,专门的函数定义显示地为 特定类型生成函数定义。

为什么要有显示具体化?处理模板函数所不能处理的特殊情况。显式具体化显式具体化也是基于函数模板的,只不过在函数模板的基础上,添加一个专门针对特定类型的、实现方式不同的具体化函数。

显示具体化声明在关键字template后包含<>.

如:

  1. template<> void swap<job>(job &j1, job &j2);

vs2013不支持:

  1. void swap(Any &a, Any &b);
  2. struct job
  3. {
  4. char name[40];
  5. double salary;
  6. int floor;
  7. };
  8. template<> void swap<job>(job &j1, job &j2);
  9. void Show(job &j);
  10. int main(){
  11. using namespace std;
  12. template void swap<job>(job &, job &);
  13. int i = 10, j = 20;
  14. swap(i, j);
  15. return 0;
  16. }
  17. template<typename Any>
  18. void swap(Any &a, Any &b){
  19. Any temp;
  20. temp = a;
  21. a = b;
  22. b = temp;
  23. }
  24. template<> void swap<job>(job &j1, job &j2){
  25. double temp_sal;
  26. temp_sal = j1.salary;
  27. j1.salary = j2.salary;
  28. j2.salary = temp_sal;
  29. }

隐式实例化

在发生函数模板的调用时,不显示给出模板参数而经过参数推演,称之为函数模板的隐式模板实参调用(隐式调用)。如:

template <typename T> void func(T t)
{
cout<<t<<endl;
}
func(5);//隐式模板实参调用

  

显示实例化:

实例:如函数调用swap(i,j)会导致编译器生成swap()的一个实例,该实例使用 int 类型。

句法:声明所需的种类用<>符号指示类型,并在声明前加上关键字template:

为什么要有显示实例化?事实上,编译器只在要调用函数的时候才使用到函数,如果不使用显示实例化,每次调用函数时,模板都会消耗性能去推导使用的是哪个类型的函数,增加了程序运行时的负担;使用了显示实例化,则在编译时就已经处理了函数选择。

  1. template [函数返回类型] [函数模板名]<实际类型列表>(函数参数列表)

实例化示例:

    1. 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++模板之函数模板实例化和具体化的更多相关文章

  1. C++—模板(1)模板与函数模板

    1.引入 如何编写一个通用加法函数?第一个方法是使用函数重载, 针对每个所需相同行为的不同类型重新实现这个函数.C++的这种编程机制给编程者极大的方便,不需要为功能相似.参数不同的函数选用不同的函数名 ...

  2. C++ 函数重载,函数模板和函数模板重载,选择哪一个?

    重载解析 在C++中,对于函数重载.函数模板和函数模板重载,C++需要有一个良好的策略,去选择调用哪一个函数定义(尤其是多个参数时),这个过程称为重载解析. (这个过程将会非常复杂,但愿不要遇到一定要 ...

  3. C++入门经典-例9.1-函数模板,函数模板的作用,使用数组作为模板参数

    1:函数模板不是一个实在的函数,因此编译器不能为其生成可执行的代码.定义函数模板只是一个对函数功能框架的描述,在具体执行时,将根据传递的实际参数决定其功能. 2:函数模板定义的一般形式如下: temp ...

  4. C++ 模板学习 函数模板、类模板、迭代器模板

    使用模板能够极大到使得代码可重用. 记录一下,方便后续使用. 1. 函数模板,支持多种类型参数 #include <stdio.h> #include <math.h> //函 ...

  5. C++面向对象编程之类模板、函数模板等一些补充

    1.static数据 和 static函数: 对于 非static函数 在内存中只有一份,当类对象调用时,其实会有该对象的this pointer传进去,那个函数就知道要对那个对象进行操作: stat ...

  6. C++_进阶之函数模板_类模板

     C++_进阶之函数模板_类模板 第一部分 前言 c++提供了函数模板(function template.)所谓函数模板,实际上是建立一个通用函数,其函数类型和形参类型不具体制定,用一个虚拟的类型来 ...

  7. C++模板之隐式实例化、显示实例化、隐式调用、显示调用和模板特化详解

    模板的实例化指函数模板(类模板)生成模板函数(模板类)的过程.对于函数模板而言,模板实例化之后,会生成一个真正的函数.而类模板经过实例化之后,只是完成了类的定义,模板类的成员函数需要到调用时才会被初始 ...

  8. C++基础--函数模板

    函数模板是通用的函数描述,其使用泛型来定义函数.其实就是有些操作,如果撇开具体的变量的数据类型,其操作是一样的如果我们将这些操作写成一个模板,在调用不同变量的时候就设定好变量类型就可了,后续的操作基本 ...

  9. C++进阶-1-模板基础(函数模板、类模板)

    C++进阶 模板 1.1 函数模板 1 #include<iostream> 2 using namespace std; 3 4 // 模板 5 6 // 模板的简单实例 7 // 要求 ...

随机推荐

  1. DVBS/S2在数字电视系统中的应用 三 (LNB介绍)

    DVBS/S2在数字电视系统中的应用 三 (LNB介绍) 老谢在前面两篇文章中(例如以下).都有提到LNB这一概念. DVBS/S2在数字电视系统中的应用 一 (DVBS/S2接收系统Block Di ...

  2. Google Chrome浏览器之删除Goolge搜索结果重定向插件Remove Google Redirects

    https://chrome.google.com/webstore/detail/remove-google-redirects/ccenmflbeofaceccfhhggbagkblihpoh?h ...

  3. ARP协议(1)什么是ARP协议

    这是最近在看<TCP/IP具体解释>系列书总结出来的,之后会陆续把其它协议部分分享出来. 我尽量以简单易读.易懂的方式呈现出来,可是,因为文笔和水平有限.有些地方或许存在描写叙述上的不足或 ...

  4. 斯坦福公开课:Developing IOS 8 App with Swift(1-3)心得体会

    最近开始学习Swift开发移动程序.跟随斯坦福大学的公开课进行自学. 这真是一个美好的时代,虽然不能在斯坦福求学,但是可以观看录制的授课录像.讲义,好似老师在给我们上课一样! 心得: 1.每节课信息量 ...

  5. EC2的维护更新

     2014年9月28日 近期几天.我们收到了一些客户关于我们即将进行维护更新的问题.下面是AWS全球Blog网站对这个问题的说明,供客户參照. 我们已经開始通知那些受影响的客户,关于我们即将实施的 ...

  6. 前端-DDoS攻击

    下面的脚本(略有修改)就会向受害网站发送大量的请求: function imgflood() { var TARGET = 'example.com' var URI = '/index.php?' ...

  7. git操作演示

    阶段一: git init git config --global user.email "you@example.com" git config --global user.na ...

  8. qemu-kvm编译错误

    今天编译了下qemu-kvm,死活编不过,错误信息如下: CC    block/qcow2-snapshot.oIn file included from ./qemu-common.h:6:0,  ...

  9. bb=Discuz与 Discuz! X ,Discuz!NT区别

    没加x的,仅仅是单独的论坛. 加了x的,模块加了很多了,门户,家园,排行榜,群组,都是Discuz! X上的,而Discuz!上没有,所以说Discuz! X更加适用于建设门户网 Discuz! X ...

  10. Greenplum使用简明手册

    GP服务启停 su - gpadmin gpstart #正常启动 gpstop #正常关闭 gpstop -M fast #快速关闭 gpstop –r #重启 gpstop –u #重新加载配置文 ...