C++之函数模板

文章目录

函数模板的定义

cpp 复制代码
template <typename T1, typename T2, ....>
    返回类型 函数名(参数表){
    ... ...
}
  • template是模板定义的关键字; 写在<>中的T1 T2,...是模板参数,其中的typename表示其后的参数可以是任意类型的
cpp 复制代码
#include <iostream>
using namespace std;
#if 0
int Min(int a, int b){
    return a<b?a:b;
}
float Min(float a, float b){
    return a<b?a:b;
}
double Min(double a, double b){
    return a<b?a:b;
}
char Min(char a, char b){
    return a<b?a:b;
}
#endif

template <typename T>
T Min(T a, T b){
    return a<b?a:b;
}
int main(void){
    int m=9, n=3;
    double d1=1.8, d2=3.4;
    cout << Min(m,n) << endl;
    cout << Min(d1, d2) << endl;
    return 0;
}

函数模板的实例化

  • 当编译器遇到关键字template和跟随其后的参数定义时,它只是简单地知道这个函数模板在后面的程序代码中可能会用到。除此之外,编译器并不会做额外的工作。在这个阶段函数模板本身并不能使编译器产生任何代码,因为编译器此时并不知道函数模板要处理的具体数据类型,根本无法生成任何函数代码
  • 当编译器遇到程序中对函数模板的调用时,它才会根据调用语句中实参的具体类型,确定模板参数的数据类型,并用此类型替换函数模板的模板参数,生成能够处理该类型的函数代码,即模板函数
  • 可以执行以下命令观察
bash 复制代码
nm a.out | grep a.out

模板参数

模板参数的匹配问题

  • C++在实例化函数模板的过程中,只是简单地将模板参数替换为实参的类型,并以此生成模板函数,不会进行参数类型的任何转换。这种方式与普通函数的参数处理有着极大的区别,以前在普通函数的调用过程中,会进行参数的自动类型转换
  • 以上程序能够正确执行。现在使用函数模板来实现通用的功能,如下所示
cpp 复制代码
#include <iostream>

using namespace std;

template <typename T>
T Max(T a, T b){
    return a>b?a:b;
}
int main(void){
    double a = 2, b = 3.4;
    float c = 1.1, d = 2.2;
    cout << "2, 3.4 的最大值是: " << Max(a,b) << endl;
    cout << "a, c的最大值是: " << Max(a,c) << endl;
    cout << "a, 100的最大值是: " << Max(a,100) << endl;
    return 0;
}
  • 编译以上程序,产生模板参数不匹配的错误。产生这个错误的原因是模板实例化过程中不会进行任何的参数类型转换。编译器在翻译Max(a,c)时,由于实参类型为double和float,而Max函数模板只有一个形参类型T,总不能让T同时取double和float两种类型吧?要知道模板实例化过程中,C++不会进行任何形式的隐式类型转换,于是产生了上述编译错误

解决参数的匹配问题的方法

  • 在模板调用时进行参数类型的强制转换
cpp 复制代码
cout << "a, c的最大值是: " << Max(a,double(c)) << endl;
  • 显示指定函数模板实例化的类型参数
cpp 复制代码
#include <iostream>
using namespace std;

template <typename T>
T Max(T a, T b){
    return a>b?a:b;
}
int main(void){
    double a = 2, b = 3.4;
    float c = 1.1, d = 2.2;
    cout << "2, 3.4 的最大值是: " << Max(a,b) << endl;
    cout << "a, c的最大值是: " << Max<double>(a,c) << endl;
    cout << "a, 100的最大值是: " << Max<double>(a,100) << end;
    return 0;
}
  • 指定多个模板参数
    • 在模板函数的调用过程中,为了避免出现一个模板参数与多个调用实参的类型冲突问题,可以为函数模板指定多个不同的类型参数
cpp 复制代码
#include <iostream>
using namespace std;
template <typename T1, typename T2>
T1 Max(T1 a, T2 b){
    return a>b?a:b;
}
int main(void){
    double a = 2, b = 3.4;
    float c = 1.1, d = 2.2;
    cout << "2, 3.4 的最大值是: " << Max(a,b) << endl;
    cout << "a, c的最大值是: " << Max(a,c) << endl;
    cout << "a, 100的最大值是: " << Max(a,100) << endl;
    return 0;
}

模板函数的形参表

  • 不要误以为函数模板中的参数只能是类型形参,它也可以包括普通类型的参数
cpp 复制代码
#include <iostream>
using namespace std;

// 函数模板:包含类型形参 T + 普通类型参数 n(数组长度)
template <typename T>
void display(T &arr, unsigned int n){
    for(int i=0; i<n; i++){
        cout << arr[i] << "\t" ;
    }
    cout << endl;
}
int main(void){
    int a[] = {12,34,56,78,11,10,999};
    char b[] = {'x', 'y', 'z', 'n'};
    display(a, sizeof(a)/sizeof(a[0]));
    display(b, sizeof(b)/sizeof(b[0]));
    return 0;
}

函数模板的特化

  • 在某些情况下,函数模板并不能生成处理特定数据类型的模板函数。上面例子中的Max函数模板可以计算int 或者 char类型数据的最大值,但对于字符串类型却是无能为力的
  • 解决这类问题的方法就是对函数模板进行特化。所谓特化,就是针对模板不能处理的特殊数据类型,编写与模板同名的特殊函数专门处理这些数据类型。语法格式如下所示
cpp 复制代码
template<>
返回类型 函数名<特化的数据类型>(参数表){
    ....
}
cpp 复制代码
#include <iostream>
#include <cstring>
using namespace std;
template <typename T>
T Min(T a, T b){
    return a < b ? a : b;
}
template <>
const char *Min(const char *a, const char *b){
    cout << "Min(const char *, const char *)" << endl;
    return (strcmp(a,b) > 0) ? b : a;
}
int main(void){
    int m=9, n=3;
    double d1=1.8, d2=3.4;
    cout << Min(m,n) << endl;
    cout << Min(d1, d2) << endl;
    cout << Min('a', 'b') << endl;
    cout << Min("aaa", "bbb") << endl;
    return 0;
}
相关推荐
寻寻觅觅☆6 小时前
东华OJ-基础题-106-大整数相加(C++)
开发语言·c++·算法
fpcc7 小时前
并行编程实战——CUDA编程的Parallel Task类型
c++·cuda
ceclar1238 小时前
C++使用format
开发语言·c++·算法
lanhuazui108 小时前
C++ 中什么时候用::(作用域解析运算符)
c++
charlee448 小时前
从零实现一个生产级 RAG 语义搜索系统:C++ + ONNX + FAISS 实战
c++·faiss·onnx·rag·语义搜索
老约家的可汗9 小时前
初识C++
开发语言·c++
crescent_悦9 小时前
C++:Product of Polynomials
开发语言·c++
小坏坏的大世界9 小时前
CMakeList.txt模板与 Visual Studio IDE 操作对比表
c++·visual studio
乐观勇敢坚强的老彭9 小时前
c++寒假营day03
java·开发语言·c++
愚者游世10 小时前
brace-or-equal initializers(花括号或等号初始化器)各版本异同
开发语言·c++·程序人生·面试·visual studio