函数模板是C++泛型编程核心,用template声明,支持自动类型推导、多参数及默认参数,但不支持偏特化,需重载或if constexpr处理特例。
函数模板是C++泛型编程的核心机制,它允许你用一套代码适配多种类型,避免重复编写相似逻辑的函数。
函数模板的基本语法
用 template 或 template 声明模板参数,再定义函数。T 是占位符,编译器会在调用时自动推导实际类型。
-
typename 和 class 在这里完全等价,习惯上对类型参数多用 typename
- 模板声明必须紧邻函数定义之前,不能有空行或其它语句隔开
- 函数体中可像使用普通类型一样使用 T,比如声明变量、作为参数或返回值类型
一个实用的交换函数模板
以 swap 为例,对比普通函数和模板写法:
template
void my_swap(T& a, T& b) {
T temp = a;
a = b;
b = temp;
}
- 调用时无需显式指定类型:my_swap(x, y),编译器自动识别 x、y 的类型
- 支持内置类型(int、double)、自定义类(只要支持拷贝构造和赋值)
- 若传入不同类型(如 my_swap(a, 3.14)),编译失败——模板参数 T 必须唯一确定
处理多个类型参数与默认模板参数
模板可接受多个类型参数,也可为部分参数设置默认类型:
template
T add(const T& a, const U& b) {
return static_cast(a + b);
}
- 调用 add(5, 2) 时,T 和 U 都是 int;调用 add(5.5, 2) 时,T 是 double,U 是 int
- 默认参数必须靠右,不能跳过中间参数(即不能只指定 U 而不指定 T)
- 注意隐式转换风险,建议在关键逻辑中用 static_cast 明确类型行为
模板实参推导与显式实例化
大多数时候依赖自动推导,但某些场景需手动指定:
- 函数参数无法提供足够信息时(如空数组、字面量类型模糊),
可用 my_func(x) 显式指定
- 显式实例化(template void my_swap<:string>(std::string&, std::string&);)可强制生成某版本代码,用于分离编译或提前检查
- 函数模板不支持偏特化(类模板才支持),如需特殊处理某类型,应使用函数重载或 if constexpr(C++17起)