函数模板需编译器实例化后才生成可执行代码;template声明须紧邻函数定义且置于头文件中;类型推导不支持隐式转换;推荐使用const T&传参;支持非类型参数如数组长度N。

函数模板不是“写出来就能用”的函数,它必须被编译器实例化后才生成可调用的函数代码;没传入具体参数、或参数类型不一致,template 声明本身不会产生任何可执行逻辑。
template 声明必须紧挨着函数定义
常见错误是把 template<typename t></typename> 和函数体之间插入了注释、空行或变量声明。g++ 会直接报错 error: 'T' does not name a type 或 error: expected unqualified-id before 'template'。
-
template<typename t></typename>和函数定义必须在同一个翻译单元(通常是头文件),且中间不能有非预处理指令的代码 - 不能在 .cpp 文件里只声明模板、在另一个 .cpp 里定义——链接时必报
undefined reference to `xxx<int>`</int> - 推荐全部写在 .h 文件里,比如
utils.h,然后#include "utils.h"
类型推导失败的典型场景
当你写 max(5, 3.14),编译器无法统一推导出 T:一个参数是 int,一个是 double,template<typename t> T max(T, T)</typename> 就会编译失败。
- 正确做法是显式指定类型:
max<double>(5, 3.14)</double>或max<int>(5, static_cast<int>(3.14))</int></int> - 或者改用多参数模板:
template<typename t1 typename t2> auto add(T1 a, T2 b) -> decltype(a + b)</typename> - 注意:自动推导不会做隐式类型转换,而普通函数会(比如
int + double自动升为double)
参数传递方式影响性能和适用性
直接写 T func(T a, T b) 对 std::string 或自定义大对象来说,每次调用都会触发完整拷贝,开销明显。
立即学习“C++免费学习笔记(深入)”;
- 改为引用传参:
template<typename t> T max(const T& a, const T& b)</typename> - 对内置类型(
int、double)引用和值传参性能无差别,但统一用const T&更安全、更通用 - 如果函数内部要修改形参,才考虑
T&(如swap模板),否则避免非常量引用
模板参数不止能是类型
除了 typename T,你还能传编译期常量,比如数组长度、对齐字节数等。
- 写法:
template<typename t int n> void print_array(const T (&arr)[N])</typename> - 调用:
int a[5] = {1,2,3,4,5}; print_array(a);—— 编译器自动推导出N == 5 - 这种非类型参数必须是字面量常量、constexpr 表达式或全局地址,不能是运行时变量
最容易被忽略的是:模板错误信息冗长且定位困难,尤其嵌套多层时;建议从小范围开始测试,比如先用 int 和 double 验证逻辑,再扩展到自定义类——后者往往需要重载 operator< 或 operator+ 才能通过编译。


















