全特化是完全指定所有模板参数的特化形式,必须以template开头,适用于类和函数模板;偏特化仅适用于类模板,需至少保留一个未定参数,不支持函数模板。

类模板全特化必须写 template 且所有参数具体化
全特化是“完全锁定所有模板参数”的写法,编译器只认这个精确匹配。比如主模板是 template,那对 int 和 double 的全特化必须写成:
template
class Pair<int double> {
public:
void print() { std::cout <p>注意三点:</p>
<ul>
<li>
<code>template</code> 后面不能带任何参数,尖括号必须为空</li>
<li>
<code>Pair<int double></int></code> 中的类型必须和主模板声明顺序、数量严格一致</li>
<li>全特化可以用于类模板和函数模板(但函数模板全特化容易被重载替代,实际少用)</li>
</ul>
<h3>偏特化只能用于类模板,语法里必须保留未特化的参数</h3>
<p>偏特化不是“指定几个类型”,而是“描述一类类型模式”,所以它必须在 <code>template</code> 尖括号里留出至少一个泛型参数。常见写法有:</p>
<ul>
<li>指针类型: <code>template<typename t> class Pair<t int></t></typename></code> —— 第二个参数固定为 <code>int</code>,第一个是任意指针</li>
<li>引用类型: <code>template<typename t> class Pair<t t></t></typename></code> —— 两个参数都得是同类型的引用</li>
<li>模板模板参数: <code>template<typename t template> class C> class Pair<c>, T></c></typename></code>
</li>
</ul>
<p>关键限制:</p>
<ul>
<li>函数模板不支持偏特化 —— 这是 C++ 标准硬性规定,想类似效果只能靠函数重载</li>
<li>偏特化定义必须和主模板在同一命名空间、同一头文件中声明(否则链接时可能找不到)</li>
<li>多个偏特化之间如果存在匹配歧义(比如 <code>T*</code> 和 <code>const T*</code> 都能匹配 <code>const int*</code>),编译器会报错</li>
</ul>
<h3>匹配优先级:全特化 > 偏特化 > 主模板</h3>
<p>当实例化 <code>Pair<int int></int></code> 时,编译器按顺序检查:</p><div class="aritcle_card flexRow artxards">
<div class="artcardd flexRow">
<a class="aritcle_card_img" rel="nofollow" href="/xiazai/gongju/2823" title="C++14"><img
src="https://img.php.cn/upload/manual/001/431/639/6ac8b33c327c4749.png" alt="C++14" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a rel="nofollow" href="/xiazai/gongju/2823" title="C++14" class="overflowclass">C++14</a>
<p class="overflowclass">C++14 对 C++11 的修正与增强版本,适合旧系统维护和较老工具链兼容。</p>
</div>
<a rel="nofollow" href="/xiazai/gongju/2823" title="C++14" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span>
</a>
</div>
</div>
<ul>
<li>有没有 <code>template class Pair<int int></int></code>?有就用它(全特化)</li>
<li>没有,再找 <code>template<typename t> class Pair<t int></t></typename></code>?有就用(偏特化)</li>
<li>都没有,才回落到主模板 <code>template<typename t typename u> class Pair</typename></code>
</li>
</ul>
<p>这个顺序不可逆,也不能靠“写得更靠前”来改变优先级。另外,偏特化本身不能递归特化 —— 你不能对一个已偏特化的版本再做一次偏特化。</p>
<h3>最容易踩的坑:偏特化定义位置和显式实例化冲突</h3>
<p>偏特化不是“额外加个实现”,它是模板定义的一部分。常见错误包括:</p>
<ul>
<li>把偏特化写在 .cpp 文件里,而主模板在头文件中 —— 导致其他 TU(translation unit)看不到偏特化,仍走主模板</li>
<li>在头文件中写了偏特化,但忘了加 <code>#include</code> 依赖,或没用 <code>inline</code> / <code>export</code>(C++20 已废弃)处理 ODR 违规</li>
<li>对非类型参数做偏特化时用了运行期值,比如 <code>template<int n> class Array<int></int></int></code> 是非法的 —— 数组类型退化为指针,N 不再可推导</li>
</ul>
<p>真正写稳偏特化,得把它当成主模板的“合法分支”,而不是补丁。一旦涉及复杂匹配逻辑,建议先用 <code>static_assert</code> 或 <code>std::is_pointer_v</code> 等 trait 做前置校验,避免编译器报出一长串无法定位的 SFINAE 错误。</p></int>
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










