函数模板注意事项

一、模板重载

①和常规重载一样,被重载的模板的函数特征标必须不同。

②并非所有的模板参数都必须是模板参数类型。例如:

template<class T>

void swap(T& a,T& b);

template<class T>

void swap(T* a,T* b,int n);//第三个参数类型为具体类型int,而不是通用类型

二、显示具体化

对于某些类型的参数,我们的算法可能略有不同,比如:对于一个结构体,虽然将一个结构体赋给另一个结构体是允许的,但是,如果我们只想交换一部分成员,那我们需要使用不同的代码,因此我们无法使用模板重载来提供其他的代码。此时,我们可以提供一个具体化函数定义,即显示具体化,其中包含所需的代码。当编译器找到与函数调用匹配的具体化定义时,将使用该定义,而不再寻找模板。

①对于给定的函数名,可以有非模板函数、模板函数和显示具体化模板函数以及它们的重载版本。

②显示具体化的原型和定义应以template<>打头,并通过名称来指出类型。

③具体化将覆盖常规模板,而非模板函数将覆盖具体化和常规模板。例如:

void swap(int&,int&);//非模板函数原型

template<class T>

void swap(T&,T&);//模板原型

template<> void swap<int>(int&,int&);//为int类型显示具体化

如果有多个原型,编译器在选择原型时,非模板版本将优先于显示具体化和模板版本,而显示具体化将优先于使用模板生成的版本。

三、实例化和具体化

记住,在代码中包含函数模板本身并不会生成函数定义,它只是一个用于生成函数定义的方案。编译器使用模板为特定类型函数生成定义时,得到的是模板实例。模板并非函数定义,但使用具体类型的模板实例是函数定义。这种实例化方式被称为隐式实例化,因为编译器之所以知道需要进行定义,是由于程序调用函数时提供了具体类型参数。

最初,编译器只能通过隐式实例化,来使用模板生成函数定义,不过现在C++还允许显示实例化。这意味着可以直接命令编译器创建特定的实例。其句法是,声明所需的种类---用<>符号指示类型,并在声明前加上关键字template:

template void swap<int>(int,int);//显示实例化

实现了这种特性的编译器看到上述声明后,将使用模板生成一个使用int类型的实例。

与显示实例化不同的是,显示具体化使用下面两个等价的声明之一:

template <> void swap<int> (int&,int&);//显示具体化

template <> void swap(int&,int&);//显示具体化

区别在于,这些声明的意思是“不要使用swap()模板来生成函数定义,而应使用独立的、专门的函数定义显示地为int类型函数定义”。这些原型必须有自己的函数定义。显示具体化声明在关键字template后包含<>,而显示实例化没有。

警告:试图在同一个编译单元中使用同一种类型的显示实例化和显示具体化将出错。

隐式实例化、显示实例化和显示具体化统称为具体化。他们的不同之处在于,它们表示的都是使用具体类型的函数定义,而不是通用描述。

四、编译器将使用哪个函数版本

对于函数重载、函数模板和函数模板重载,C++需要一个定义良好的策略,来决定为函数调用使用哪一个函数定义,尤其是有多个参数时。这个过程称为重载解析。过程如下:

①创建候选函数列表。其中包含于被调用函数的名称相同的函数和模板函数。

②使用候选函数列表创建可行函数列表。这些都是参数数目正确地函数,为此有一个隐式转换序列,其中包括实参类型与相应的形参类型完全匹配的情况。

③确定是否有最佳的可行函数。

编译器必须确定哪个可行函数时最佳的。它查看为使函数调用参数与可行的候选函数的参数匹配所需要进行的转换。通常,从最佳到最差的顺序如下:

①完全匹配,但常规函数优先于模板函数。

②提升转换(例如,char和short自动转换为int,float自动转换为double)

③标准转换(例如,int转换为char,long转换为double)

④用户定义的转换,如类声明中定义的转换。

注意:const和非const之间的区别只适用于指针和引用指向的数据。即下面的两个定义将出现二义性错误:

void fun(int);

void fun(const int);

函数模板注意事项

时间: 2024-10-02 20:38:38

函数模板注意事项的相关文章

第57课 深入理解函数模板

1. 函数模板深入理解 (1)编译器从函数模板通过具体类型产生不同的函数 (2)编译器会对函数模板进行两次编译 ①对模板代码本身进行编译 ②对参数替换后的代码进行编译(编译时机:可能发生在定义对象或函数调用时) (3)注意事项 ①函数模板本身不允许隐式类型转换 ②自动推导类型时,必须严格匹配 ③显式类型指定时,能够进行隐式类型转换 [编程实验]函数模板的本质 #include <iostream> #include <string> using namespace std; cla

函数模板 类模板

摘要:学习函数模板的定义,使用:学习类模板的定义和使用. 函数模板: template <typename 类型参数> 返回类型 函数名(模板形参表) { 函数体 } 特点:1.函数模板可以重载(比如形参数量不同的情况). 2.定义的时候,template <typename 类型参数>到下面一个语句之间不允许插入其他语句! 3.如果程序中有和函数模板名称相同的非函数模板函数,则优先调用它. 例子: #include<iostream> using namespace

类模板、模板类、函数模板、模板函数

一:什么是类模板 一个类模板允许用户为类定义一种模式,使得类中的某些数据成员.默认成员函数的参数.某些成员函数的返回值,能够取任意类型(包括系统预定义的和用户自定义的) 如果一个类中数据成员的数据类型不能确定.或者是某个成员函数的参数或返回值的类型不能确定,就必须将此类声明为模板,它的存在不是代表一个具体的.实际的类,而是代表一类类. 二:类模板定义及注意事项 template<class 模板参数表> 或者template<typename 模板参数表> class 类名 { /

函数模板在c++动态顺序表中的大作用

函数模板提供了一种机制通过它我们可以保留函数定义和函数调用的语义在一个程序位置上封装了一段代码确保在函数调用之前实参只被计算一次. 函数模板提供一个种用来自动生成各种类型函数实例的算法程序员对于函数接口参数和返回类型中的全部或者部分类型进行参数化(parameterize)而函数体保持不变. 函数模板使用注意事项: 1.每个函数模板前边都需要添加模板声明例如:template<typename T> 2.在模板类的使用时,注意其类型改变,例如: template<typename T&g

C++解析(26):函数模板与类模板

0.目录 1.函数模板 1.1 函数模板与泛型编程 1.2 多参数函数模板 1.3 函数重载遇上函数模板 2.类模板 2.1 类模板 2.2 多参数类模板与特化 2.3 特化的深度分析 3.小结 1.函数模板 1.1 函数模板与泛型编程 C++中有几种交换变量的方法? 交换变量的方法--定义宏代码块 vs 定义函数: 定义宏代码块 优点:代码复用,适合所有的类型 缺点:编译器不知道宏的存在,缺少类型检查 定义函数 优点:真正的函数调用,编译器对类型进行检查 缺点:根据类型重复定义函数,无法代码复

C++ 函数模板用法

泛型编程概念:不考虑具体数据类型的编程方式: 函数模板: 1.提供一种特殊的函数可用不同类型进行调用: 2.与普通函数很相似,区别是类型可被参数化: template <typename T> //template关键字用于声明开始进行泛型编程 void Swap(T &a, T &b) //typename关键字用于声明泛指类型 { T tmp = a; a = b; b = tmp; } 函数模板的应用: 1.自动类型推导调用: 2.具体类型显示调用: int a = 3;

C++--模板的概念和意义、深入理解函数模板、类模板的概念和意义

一.模板的概念与意义 Q:C++中有几种交换变量的方法?定义宏代码与定义函数A.定义宏代码优点:代码复用,适合所有的类型缺点:编译器不知道宏的存在,缺少类型检查B.定义函数优点:真正的函数调用,编译器对类型进行检查缺点:根据类型重复定义函数,无法代码复用 C.泛型编程--不考虑具体数据类型的编程方式Swap泛型写法中的T不是一个具体的数据类型,而是泛指任意的数据类型C++中的泛型编程函数模板--一种特殊的函数可用不同类型进行调用,看起来和普通函数很相似,区别是类型可被参数化函数模板的语法规则1.

c++知识点总结--函数模板

通用函数可变参模板 用于处理不限定参数的函数 showall(){//空函数,接口,最后结束递归 } template<typename T,typename... Args> void showall(T value,Args ...args){ cout<<value<<endl; showall(args); } template<typename T,typename ...Args> void showall(const T &value,

函数模板特化

#include <iostream> template <typename T> T max(T x, T y) { return x > y ? x : y; } //函数模板特化 template <> const char* max(const char* x, const char* y){ return strcmp(x, y) > 0 ? x : y; } int main(){ std::cout << max(1, 2); st