C++ 泛编程 —— 函数模板(中)
C++ 泛编程 —— 函数模板(中)
- 函数模板的具体化
函数模板的具体化
可以提供一个具体化
的函数定义,当编译器找到与函数调用匹配的具体化定义
时,将使用该定义,不再寻找模板。
具体化(特例化、特化)
的语法:
template<> void 函数模板名<数据类型>(参数列表)
template<> void 函数模板名 (参数列表)
{// 函数体。
}
请看如下示例代码:
#include <iostream>
using namespace std;class Car{
public: string brand_;int speed_;float acceleration_;
};template<typename T>
void change(T& t1, T& t2){T tmp = t1;t1 = t2;t2 = tmp;
}// 现在的需求是:只交换 Car 类对象中的 speed_ 属性值,不交换其他属性值。
// 具体化函数的代码如下
// template<> void change<Car>(Car& c1, Car& c2) // 第一种写法
template<> void change(Car& c1, Car& c2) { // 第二种写法 交换两个Car类对象的speed_属性值int tmp = c1.speed_;c1.speed_ = c2.speed_;c2.speed_ = tmp;
}int main(){int a = 10, b = 20;change<int>(a, b);cout << "a = " << a << ", b = " << b << endl;Car c1 = {"BMW", 20, 3.5};Car c2 = {"Audi", 30, 4.5};change(c1, c2);cout << "c1.brand_ = " << c1.brand_ << ", c2.brand_ = " << c2.brand_ << endl;cout << "c1.speed_ = " << c1.speed_ << ", c2.speed_ = " << c2.speed_ << endl;return 0;
}
编译运行的结果如下:
a = 20, b = 10
c1.brand_ = BMW, c2.brand_ = Audi
c1.speed_ = 30, c2.speed_ = 20
对于具体化
函数来说,不管是函数的声明
还是函数体中
,都是具体
的数据类型,没有
通用的数据类型了。
对于给定的函数名,它可以是普通函数
、函数模板
和具体化的函数模板
,以及它们的重载版本
。如果多种函数都能匹配上,那编译器会使用哪个函数呢?编译器使用各种函数的规则:
具体化
优先于常规模板,普通函数
优先于具体化和常规模板。- 如果希望使用
函数模板
,可以用空模板参数
强制使用函数模板。 - 如果
函数模板
能产生更好的匹配,将优先于普通函数。
对于前两条规则,给出示例代码,大家可以自行选择注释某个版本的函数代码,来测试一下各个版本函数代码的使用规则:
#include <iostream>
using namespace std;// 普通版本函数
void show(int n1, int n2) {cout << "使用普通版本函数" << endl;
}// 常规函数模板
template <typename T>
void show(T n1, T n2) {cout << "使用常规函数模板" << endl;
}// 函数模板的具体化版本
template <>
void show(int n1, int n2) {cout << "使用函数模板的具体化版本" << endl;
}int main() {show(111, 222);show<>(111, 222);return 0;
}
编译运行结果如下:
使用普通版本函数
使用函数模板的具体化版本
对于第三条规则:如果函数模板
能产生更好的匹配,将优先于普通函数,示例代码如下:
#include <iostream>
using namespace std;// 普通版本函数
void show(int n1, int n2) {cout << "使用普通版本函数" << endl;
}// 常规函数模板
// template <typename T>
// void show(T n1, T n2) {
// cout << "使用常规函数模板" << endl;
// }int main() {show('a', 'b'); // 字符可以转换成整数return 0;
}
编译运行结果如下:
使用普通版本函数
如果取消注释,编译运行结果如下:
使用常规函数模板
原因解释:实参是字符a
和b
,与常规函数模板可以完全匹配,不需要转换,比普通函数匹配度更好。所以,编译器选择了常规函数模板。
C++ 泛编程 —— 函数模板(上)
C++ 泛编程 —— 函数模板(下)
感谢浏览,一起学习!