模板类是编译期生成具体类型的机制,声明与定义必须同在头文件中;依赖模板参数的嵌套类型名需用typename显式声明;template与typename T无语义区别;类模板可偏特化,函数模板仅支持全特化。

模板类不是语法糖,是编译期生成具体类型的机制;写错一个参数或漏掉 typename,编译器报错会直接跳到几百行外的实例化位置,而不是你定义的地方。
模板类声明和定义不能分离在 .h / .cpp 中
因为模板代码不生成目标码,直到被实例化时才由编译器根据实参推导并生成对应类型版本。把 template 的声明放头文件、定义放 .cpp,链接时必然报 undefined reference。
- 全部实现必须写在头文件里(.h 或 .hpp)
- 如果非要拆分,可用
.tpp后缀并在 .h 末尾#include "Stack.tpp",但本质仍是文本包含 - 现代 C++20 的
export template已被移除,别信过时资料
何时必须写 typename?
当模板中出现依赖于模板参数的嵌套类型名时,编译器默认不认为它是类型——比如 T::value_type,它可能是静态成员变量、枚举值,也可能是类型别名。不加 typename 就算你写了 using value_type = int;,也会编译失败。
- 错误写法:
T::iterator it; - 正确写法:
typename T::iterator it; - 仅在模板定义内部、且名字依赖模板参数时需要;非依赖名如
std::vector不用::iterator
template 和 template 有区别吗?
没有语义区别,完全可互换。历史上用 class 是因为最初只支持类类型参数;后来支持内置类型(int、double)后引入 typename 更准确,但标准允许两者混用。
立即学习“C++免费学习笔记(深入)”;
- 习惯上:单个类型参数常用
class T,多个或强调“任意类型”倾向用typename T - 别在同一个项目里随意切换,统一风格比纠结语义更重要
- 注意:
class在模板形参中 ≠ 只接受类类型——template同样能传void f(T x) 42
偏特化(partial specialization)不能用于函数模板
类模板可以偏特化,比如针对指针类型:template;但函数模板只允许全特化(template void foo),不支持偏特化。想实现类似效果,得靠重载或委托给类模板。
- 函数模板偏特化会触发编译错误:
error: partial specialization of function templates is not allowed - 常见替代方案:用
enable_if+ SFINAE 或 C++17 的if constexpr分支 - 类模板偏特化时,偏特化版本的模板参数列表必须比主模板“更特殊”,否则编译器无法决定选哪个
最常被忽略的是:模板参数推导不看函数体,只看调用时传入的实参和形参签名。哪怕你在函数里强制转换了类型,也不会影响推导结果——这是编译期行为,和运行时逻辑无关。










