模板编程

2019-04-13 17:03发布

模板

模板是C++中泛型编程的基础。一个模板就是一个创建类或函数的蓝图或公式,在使用模板时,我们提供足够的信息将模板转换为特定的类或函数。这种转换发生在编译时。

函数模板

考虑这样一个功能的实现:交换两个静态类型相同的变量的值,编写一个swap函数。 void swap(int &a, int &b) { int temp = a; a = b; b = temp; } 上面的swap函数只能接受两个整型实参并交换它们,如果要实现更多类型变量的值交换,我们要写出很多个重载函数:swap(double &a, double &b) swap(char &a, char &b)…… 在这里运用函数重载显然效率低下,我们希望定义一个通用的swap函数,能够接受多种类型的实参。用函数模板可以做到这一点: template void swap(T &t1, T &t2) { T temp = t1; t1 = t2; t2 = temp; } 如上,函数模板就是一个公式,可用来生成针对特定类型的函数版本。编译器(通常)根据函数实参的类型来为我们推断模板实参,并生成相对应类型的swap版本。这极大减少了代码编写的工作量,提高了开发效率。

非类型模板参数

上面的swap模板中,T属于模板类型参数。一般来说,我们可以将类型参数看作类型说明符,就像内置类型或类类型来使用:指定返回类型或函数的参数类型,以及函数体内的变量声明或类型转换等。 除了定义类型参数,还可以在模板中定义非类型参数(nontype parameter)。一个非类型参数表示一个值而非一个类型。我们通过一个特定的类型名而非关键字class或typename来指定非类型参数。 例如,编写一个处理字符串字面常量的大小比较函数。 template int compare(const char (&p1)[N], const char (&p2)[M]) { return strcmp(p1, p2); } 当我们调用compare时:compare("hi", "mom") 编译器会使用字面常量的大小来代替N和M,从而实例化模板。因此编译器会实例化出如下版本: int compare(const char (&p1)[3], const char (&p2)[4])//在字面值常量末尾自动添加空字符'