全特化是针对具体类型完全重写模板实现,编译器优先选用;仅类模板支持,函数模板不支持;需声明为空模板参数列表template,且须与原模板同命名空间。

什么是全特化:直接替换整个模板定义
全特化就是针对某组具体类型,完全重写模板的实现。编译器遇到匹配类型时,会优先用这个“定制版”,而不是泛型版本。
常见错误是把全特化写成函数重载——c++ 不允许函数模板全特化(类模板可以)。容易踩的坑是忘记声明模板参数列表为空:template,漏了尖括号就变成普通类或函数,导致链接错误或 ODR 违规。
- 全特化必须和原模板在同一命名空间,且不能在函数体内定义
- 类模板全特化时,
template后面直接跟class MyTemplate<int></int>这种形式,不带typename - 全特化不参与 SFINAE,它要么完全匹配,要么不生效
<pre class="brush:php;toolbar:false;">template<typename T> struct Printer { static void print(const T& v) { std::cout << "generic: " << v << "n"; } }; <p>// 全特化:针对 int 类型 template<> struct Printer<int> { static void print(const int& v) { std::cout << "int special: " << v << "n"; } };
偏特化只适用于类模板,且必须保留部分泛参
偏特化不是“部分实现”,而是“对模板参数施加约束后的另一套定义”。它只能用于类模板(包括 alias template),函数模板不支持偏特化——这是很多人卡住的第一步。
典型错误是试图偏特化函数模板,或者在偏特化中写 template<typename t> 却又把 <code>T 写死成 int,这其实已经是全特化了。偏特化的本质是让参数模式更宽泛但有规律,比如 “所有指针类型” 或 “所有容器类型”。
立即学习“C++免费学习笔记(深入)”;
- 偏特化必须至少保留一个未绑定的模板参数,例如
template<typename t></typename>针对MyClass<t></t> - 多个偏特化之间不能模糊匹配,否则编译报错:ambiguous partial specialization
- 偏特化继承自泛型版本时,注意基类访问权限和构造函数转发
<pre class="brush:php;toolbar:false;">// 偏特化:所有指针类型 template<typename T> struct Printer<T*> { static void print(T* p) { std::cout << "pointer to " << typeid(T).name() << "n"; } };
偏特化与全特化的优先级关系
编译器按“匹配精确度”排序:全特化 > 偏特化 > 泛型。但要注意,“更特殊”不等于“写了更多条件”,而是看模板参数是否被完全确定或受限。
容易忽略的是:两个偏特化如果能同时匹配某个实例(比如 Printer<int> 同时满足 <code>T* 和 const T* 偏特化),就会编译失败。这不是运行时问题,而是在模板实例化阶段就拒掉。
- 用
static_assert在偏特化内部检查std::is_pointer_v<t></t>是冗余的,匹配本身已由模板形参保证 - 偏特化不能只靠
enable_if实现——那属于 SFINAE + 泛型,不是偏特化 - 别在头文件里反复定义同一偏特化,否则可能触发 ODR 违规(尤其跨 TU)
实际项目中该用偏特化还是 if constexpr?
C++17 的 if constexpr 让很多原本需要偏特化的场景,改用单个泛型模板就能完成。它更适合逻辑分支少、类型判断简单的场合;而偏特化更适合结构差异大、成员布局/接口完全不同的情形(比如为 std::vector<bool></bool> 提供专用迭代器)。
性能上没区别——两者都在编译期决定。但偏特化会导致符号膨胀:每个特化生成独立类型;if constexpr 则复用同一类名,调试时更干净。
- 想给
std::optional<t></t>加一个has_value()成员函数?用偏特化不合适,它是标准库类型,你无法特化它(除非 ADL 或 traits) - 要为自定义容器提供不同内存策略?偏特化比一堆
if constexpr更易维护 - 偏特化无法处理非类型模板参数的复杂约束(如数组长度),这时
enable_if+ 泛型更灵活
偏特化真正难的不是语法,而是判断“这个类型变体是否值得单独建一套接口”。多数时候,先写泛型,等真出现编译错误或语义断裂,再拉出偏特化,反而更稳。