必须写 template 才是函数模板,漏写或误写(如少 typename)会导致编译错误;typename 与 class 可互换但忌混用;T 是惯例而非强制;无参数参与推导时需显式指定类型;auto 参数非模板替代品,不支持特化、SFINAE 和 requires 约束。

template<typename t></typename> 是定义函数模板的起点,不加它就不是模板,编译直接报错。
必须写 template<typename t></typename> 才算模板
函数模板不是普通函数,不能省略模板声明。哪怕只用一次,也得显式写出 template<typename t></typename>(或 template<class t></class>,二者完全等价)。常见错误是漏掉这行,或者写成 template<t></t>(少 typename),编译器会立刻拒绝。
-
typename和class可互换,但别混用——比如头文件用typename,实现里突然换成class,容易让协作者困惑 - 模板参数名不强制叫
T,但T是行业惯例;用MyType或Elem也合法,只是偏离直觉 - 如果模板参数没在函数参数列表中出现,编译器无法推导,比如
template<typename t> T make_zero() { return T{}; }</typename>,调用时必须写make_zero<int>()</int>,不能只写make_zero()
auto 参数不是模板替代品
C++20 的 void func(auto x) 看似更短,但它只是模板的语法糖,底层仍是模板实例化。关键区别在于:它不支持特化、不能用 static_assert 对类型做编译期检查、也无法参与 SFINAE。
- 需要为
std::vector<int></int>单独定制行为?必须用template<typename t></typename>+ 特化,auto做不到 - 想限制
T必须有.size()?得靠requires或传统static_assert,auto参数没法加这些约束 - 转发参数包(如
template<typename... args> f(Args&&... args)</typename...>)也不能用auto替代
参数类型必须能统一推导出来
自动推导只在所有实参能映射到同一个 T 时才成功。比如 template<typename t> void f(T a, T b)</typename>,传入 f(1, 2.0) 会失败——int 和 double 冲突,编译器不会帮你隐式转成其中一个。
立即学习“C++免费学习笔记(深入)”;
- 允许不一致?改用多个参数:
template<typename t1 typename t2> void f(T1 a, T2 b)</typename> - 想保留类型信息又支持混合调用?用
decltype推导返回值,例如template<typename t1 typename t2> auto mul(T1 a, T2 b) -> decltype(a * b)</typename> - 传数组时注意退化:
int arr[5]传给T参数会推成int*,要保留长度得写template<typename t size_t n> void f(T (&arr)[N])</typename>
真正难的不是写对第一行 template<typename t></typename>,而是后续每一步都在和类型系统博弈:推导是否如你所愿、隐式转换是否发生、错误信息是否指向调用点而非模板定义处。这些细节不会在编译时报错前暴露,得靠经验预判。


















