模板偏特化是固定部分模板参数的定制实现,类模板支持而函数模板仅支持全特化;需先定义主模板,偏特化匹配优先级介于全特化与主模板之间。

模板偏特化是针对部分类型参数的定制实现
它不是全特化(即不指定所有模板参数),而是只固定其中一部分,让其余参数仍保持泛型。比如 template 偏特化成 template,保留 N 但把 T 固定为 int,这就是偏特化——既不是完全泛型,也不是完全具体。
偏特化必须写在主模板定义之后
否则编译器不认识这个“被偏特化的对象”,会报错 error: explicit specialization of undeclared template。而且偏特化本身不能有默认模板参数,也不能用 inline 或 constexpr 修饰(C++17 起允许 constexpr,但需谨慎)。
templatestruct Pair { T first; U second; }; // ✅ 正确:先有主模板,再偏特化 template struct Pair { // T 固定为 int,U 仍泛型 int first; U second; };
函数模板不支持偏特化,只能全特化或重载
这是容易踩坑的关键点。C++ 标准禁止函数模板偏特化,因为重载机制已足够表达类似意图,且能避免二义性。如果你写了类似下面的代码:
templatevoid foo(T) { } template void foo(T*) { } // ❌ 这不是偏特化,是重载!编译器按重载规则选函数
上面第二段实际是函数重载,不是偏特化。若强行用 template 去特化指针版本,那只能是全特化(如 template void foo),无法留一个参数泛型。
立即学习“C++免费学习笔记(深入)”;
- 类模板:支持全特化和偏特化
- 变量模板(C++14):支持偏特化
- 函数模板:仅支持全特化,不支持偏特化
偏特化匹配优先级高于主模板,但低于全特化
当实例化 Pair 时,编译器会优先匹配 Pair 这个偏特化,而不是主模板;但如果还存在 Pair 全特化,则全特化胜出。注意:偏特化之间不能有歧义,比如同时定义 Pair 和 Pair,对 Pair 就会产生二义性错误。
偏特化真正难的地方不在语法,而在设计时得想清楚类型约束是否正交、是否覆盖完备,以及和 SFINAE、concept(C++20)混用时的可读性——这些细节一不留神就会让编译错误信息变得极长且难定位。









