276 lines
36 KiB
HTML
276 lines
36 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="zh" dir="ltr" class="client-nojs" xmlns="http://www.w3.org/1999/xhtml" xml:lang="zh">
|
|
<head><meta http-equiv="x-ua-compatible" content="ie=edge">
|
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
|
<title>显式(全)模板特化</title>
|
|
<link rel="stylesheet" href="ext.css" />
|
|
<link rel="stylesheet" href="site_modules.css" />
|
|
</head>
|
|
<body class="mediawiki ltr sitedir-ltr ns-0 ns-subject page-cpp_language_template_specialization skin-cppreference2 action-view cpp-navbar">
|
|
<div id="cpp-content-base">
|
|
<div id="content"><a id="top"></a>
|
|
<h1 id="firstHeading" class="firstHeading">显式(全)模板特化</h1>
|
|
<div id="bodyContent">
|
|
<div id="contentSub"><span class="subpages">< <a href="cpp.html">cpp</a>‎ | <a href="cpp-language.html">language</a></span></div>
|
|
<div id="mw-content-text" lang="zh" dir="ltr" class="mw-content-ltr" xml:lang="zh">
|
|
<p>允许对给定的模板实参集定制模板代码。</p>
|
|
<h3><span class="mw-headline" id=".E8.AF.AD.E6.B3.95">语法</span></h3>
|
|
<table class="t-sdsc-begin">
|
|
<tr>
|
|
<td colspan="10" class="t-sdsc-sep"></td>
|
|
</tr>
|
|
<tr class="t-sdsc">
|
|
<td class="t-sdsc-nopad"><code><b>template</b></code> <code><b><></b></code> <span class="t-spar">声明</span></td>
|
|
<td class="t-sdsc-nopad"></td>
|
|
<td class="t-sdsc-nopad"></td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan="10" class="t-sdsc-sep"></td>
|
|
</tr>
|
|
</table>
|
|
<p>以下任何一项均可以完全特化:</p>
|
|
<ol>
|
|
<li><a href="cpp-language-function_template.html">函数模板</a></li>
|
|
<li><a href="cpp-language-class_template.html">类模板</a></li>
|
|
<li><span class="t-rev-inl t-since-cxx14"><span><a href="cpp-language-variable_template.html">变量模板</a></span> <span><span class="t-mark-rev t-since-cxx14">(C++14 起)</span></span></span></li>
|
|
<li>类模板的<a href="cpp-language-member_functions.html">成员函数</a></li>
|
|
<li>类模板的<a href="cpp-language-static.html">静态数据成员</a></li>
|
|
<li>类模板的<a href="cpp-language-nested_types.html">成员类</a></li>
|
|
<li>类模板的成员<a href="cpp-language-enum.html">枚举</a></li>
|
|
<li>类或类模板的<a href="cpp-language-member_template.html">成员类模板</a></li>
|
|
<li>类或类模板的<a href="cpp-language-member_template.html#.E6.88.90.E5.91.98.E5.87.BD.E6.95.B0.E6.A8.A1.E6.9D.BF">成员函数模板</a></li>
|
|
</ol>
|
|
<p>例如,</p>
|
|
<div class="t-example">
|
|
<div class="t-example-live-link"></div>
|
|
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
|
<div class="cpp source-cpp">
|
|
<pre class="de1"><span class="co2">#include <iostream></span>
|
|
<span class="kw1">template</span><span class="sy1"><</span><span class="kw1">typename</span> T<span class="sy1">></span> <span class="co1">// 主模板</span>
|
|
<span class="kw1">struct</span> is_void <span class="sy4">:</span> <a href="cpp-types-integral_constant.html"><span class="kw650">std::<span class="me2">false_type</span></span></a> <span class="br0">{</span><span class="br0">}</span><span class="sy4">;</span>
|
|
<span class="kw1">template</span><span class="sy1"><></span> <span class="co1">// 对 T = void 的显式特化</span>
|
|
<span class="kw1">struct</span> is_void<span class="sy1"><</span><span class="kw4">void</span><span class="sy1">></span> <span class="sy4">:</span> <a href="cpp-types-integral_constant.html"><span class="kw649">std::<span class="me2">true_type</span></span></a> <span class="br0">{</span><span class="br0">}</span><span class="sy4">;</span>
|
|
|
|
<span class="kw4">int</span> main<span class="br0">(</span><span class="br0">)</span>
|
|
<span class="br0">{</span>
|
|
<span class="co1">// 对于任何非 void 的类型 T,该类均派生自 false_type</span>
|
|
<a href="cpp-io-cout.html"><span class="kw1758">std::<span class="me2">cout</span></span></a> <span class="sy1"><<</span> is_void<span class="sy1"><</span><span class="kw4">char</span><span class="sy1">></span><span class="sy4">::</span><span class="me2">value</span> <span class="sy1"><<</span> <span class="st0">'<span class="es1">\n</span>'</span><span class="sy4">;</span>
|
|
<span class="co1">// 但当 T 为 void 时类派生自 true_type</span>
|
|
<a href="cpp-io-cout.html"><span class="kw1758">std::<span class="me2">cout</span></span></a> <span class="sy1"><<</span> is_void<span class="sy1"><</span><span class="kw4">void</span><span class="sy1">></span><span class="sy4">::</span><span class="me2">value</span> <span class="sy1"><<</span> <span class="st0">'<span class="es1">\n</span>'</span><span class="sy4">;</span>
|
|
<span class="br0">}</span></pre></div>
|
|
</div>
|
|
</div>
|
|
<h3><span class="mw-headline" id=".E7.BB.86.E8.8A.82">细节</span></h3>
|
|
<p>显式特化可以在任何可以定义其主模板的作用域中声明(可以与定义其主模板的作用域不同;例如同<a href="cpp-language-member_template.html">成员模板</a>的类外特化)。显式特化必须在非特化模板声明后出现。</p>
|
|
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
|
<div class="cpp source-cpp">
|
|
<pre class="de1"><span class="kw1">namespace</span> N
|
|
<span class="br0">{</span>
|
|
<span class="kw1">template</span><span class="sy1"><</span><span class="kw1">class</span> T<span class="sy1">></span> <span class="kw1">class</span> X <span class="br0">{</span> <span class="coMULTI">/*...*/</span> <span class="br0">}</span><span class="sy4">;</span> <span class="co1">// 主模板</span>
|
|
<span class="kw1">template</span><span class="sy1"><></span> <span class="kw1">class</span> X<span class="sy1"><</span><span class="kw4">int</span><span class="sy1">></span> <span class="br0">{</span> <span class="coMULTI">/*...*/</span> <span class="br0">}</span><span class="sy4">;</span> <span class="co1">// 同命名空间中的特化</span>
|
|
|
|
<span class="kw1">template</span><span class="sy1"><</span><span class="kw1">class</span> T<span class="sy1">></span> <span class="kw1">class</span> Y <span class="br0">{</span> <span class="coMULTI">/*...*/</span> <span class="br0">}</span><span class="sy4">;</span> <span class="co1">// 主模板</span>
|
|
<span class="kw1">template</span><span class="sy1"><></span> <span class="kw1">class</span> Y<span class="sy1"><</span><span class="kw4">double</span><span class="sy1">></span><span class="sy4">;</span> <span class="co1">// 对 double 特化的前置声明</span>
|
|
<span class="br0">}</span>
|
|
|
|
<span class="kw1">template</span><span class="sy1"><></span>
|
|
<span class="kw1">class</span> N<span class="sy4">::</span><span class="me2">Y</span><span class="sy1"><</span><span class="kw4">double</span><span class="sy1">></span> <span class="br0">{</span> <span class="coMULTI">/*...*/</span> <span class="br0">}</span><span class="sy4">;</span> <span class="co1">// OK:相同命名空间中的特化</span></pre></div>
|
|
</div>
|
|
<p>特化必须在导致隐式实例化的首次使用之前,在每个发生这种使用的翻译单元中声明:</p>
|
|
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
|
<div class="cpp source-cpp">
|
|
<pre class="de1"><span class="kw1">class</span> String <span class="br0">{</span><span class="br0">}</span><span class="sy4">;</span>
|
|
<span class="kw1">template</span><span class="sy1"><</span><span class="kw1">class</span> T<span class="sy1">></span> <span class="kw1">class</span> Array <span class="br0">{</span> <span class="coMULTI">/*...*/</span> <span class="br0">}</span><span class="sy4">;</span>
|
|
<span class="kw1">template</span><span class="sy1"><</span><span class="kw1">class</span> T<span class="sy1">></span> <span class="kw4">void</span> sort<span class="br0">(</span>Array<span class="sy1"><</span>T<span class="sy1">></span><span class="sy3">&</span> v<span class="br0">)</span> <span class="br0">{</span> <span class="coMULTI">/*...*/</span> <span class="br0">}</span> <span class="co1">// 主模板</span>
|
|
|
|
<span class="kw4">void</span> f<span class="br0">(</span>Array<span class="sy1"><</span>String<span class="sy1">></span><span class="sy3">&</span> v<span class="br0">)</span>
|
|
<span class="br0">{</span>
|
|
sort<span class="br0">(</span>v<span class="br0">)</span><span class="sy4">;</span> <span class="co1">// 使用初等模板 sort() 隐式实例化 sort(Array<String>&)</span>
|
|
<span class="br0">}</span>
|
|
|
|
<span class="kw1">template</span><span class="sy1"><></span> <span class="co1">// 错误:sort(Array<String>) 的显式特化在隐式实例化之后出现</span>
|
|
<span class="kw4">void</span> sort<span class="sy1"><</span>String<span class="sy1">></span><span class="br0">(</span>Array<span class="sy1"><</span>String<span class="sy1">></span><span class="sy3">&</span> v<span class="br0">)</span><span class="sy4">;</span></pre></div>
|
|
</div>
|
|
<p>只有声明没有定义的模板特化可以像其他<a href="cpp-language-type.html#.E4.B8.8D.E5.AE.8C.E6.95.B4.E7.B1.BB.E5.9E.8B">不完整类型</a>一样使用(例如可以使用到它的指针和引用):</p>
|
|
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
|
<div class="cpp source-cpp">
|
|
<pre class="de1"><span class="kw1">template</span><span class="sy1"><</span><span class="kw1">class</span> T<span class="sy1">></span> <span class="kw1">class</span> X<span class="sy4">;</span> <span class="co1">// 主模板</span>
|
|
<span class="kw1">template</span><span class="sy1"><></span> <span class="kw1">class</span> X<span class="sy1"><</span><span class="kw4">int</span><span class="sy1">></span><span class="sy4">;</span> <span class="co1">// 特化(声明,不定义)</span>
|
|
|
|
X<span class="sy1"><</span><span class="kw4">int</span><span class="sy1">></span><span class="sy2">*</span> p<span class="sy4">;</span> <span class="co1">// OK:指向不完整类型的指针</span>
|
|
X<span class="sy1"><</span><span class="kw4">int</span><span class="sy1">></span> x<span class="sy4">;</span> <span class="co1">// 错误:不完整类型的对象</span></pre></div>
|
|
</div>
|
|
<h3><span class="mw-headline" id=".E5.87.BD.E6.95.B0.E6.A8.A1.E6.9D.BF.E7.9A.84.E6.98.BE.E5.BC.8F.E7.89.B9.E5.8C.96">函数模板的显式特化</span></h3>
|
|
<p>当特化函数模板时,如果<a href="cpp-language-template_argument_deduction.html">模板实参推导</a>能通过函数实参提供,那么就可以忽略它的模板实参:</p>
|
|
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
|
<div class="cpp source-cpp">
|
|
<pre class="de1"><span class="kw1">template</span><span class="sy1"><</span><span class="kw1">class</span> T<span class="sy1">></span> <span class="kw1">class</span> Array <span class="br0">{</span> <span class="coMULTI">/*...*/</span> <span class="br0">}</span><span class="sy4">;</span>
|
|
<span class="kw1">template</span><span class="sy1"><</span><span class="kw1">class</span> T<span class="sy1">></span> <span class="kw4">void</span> sort<span class="br0">(</span>Array<span class="sy1"><</span>T<span class="sy1">></span><span class="sy3">&</span> v<span class="br0">)</span><span class="sy4">;</span> <span class="co1">// 主模板</span>
|
|
<span class="kw1">template</span><span class="sy1"><></span> <span class="kw4">void</span> sort<span class="br0">(</span>Array<span class="sy1"><</span><span class="kw4">int</span><span class="sy1">></span><span class="sy3">&</span><span class="br0">)</span><span class="sy4">;</span> <span class="co1">// 对 T = int 的特化</span>
|
|
<span class="co1">// 不需要写成 template<> void sort<int>(Array<int>&);</span></pre></div>
|
|
</div>
|
|
<p>与某个特化带有相同名字和相同形参列表的函数不是特化(见<a href="cpp-language-function_template.html">函数模板</a>中的模板重载)</p>
|
|
<p>函数模板的显式特化只有在声明为带 <a href="cpp-language-inline.html">inline 说明符</a>(或定义为弃置)时才是内联函数,主模板是否为内联对它没有影响。</p>
|
|
<p>不能在函数模板,成员函数模板,以及隐式实例化类时的类模板的成员函数的显式特化中指定<a href="cpp-language-default_arguments.html">默认函数实参</a>。</p>
|
|
<p>显式特化不能是<a href="cpp-language-friend.html">友元声明</a>。</p>
|
|
<table class="metadata plainlinks ambox mbox-small-left ambox-notice" style="">
|
|
<tr>
|
|
<td class="mbox-empty-cell"></td>
|
|
<td class="mbox-text" style="">本节未完成<br />
|
|
原因:重新确认不同C++版本对异常说明的要求</td>
|
|
</tr>
|
|
</table>
|
|
<h3><span class="mw-headline" id=".E7.89.B9.E5.8C.96.E7.9A.84.E6.88.90.E5.91.98">特化的成员</span></h3>
|
|
<p>在类体外定义显式特化的类模板的成员时,不使用 <span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="kw1">template</span> <span class="sy1"><></span></span></span> 语法,除非它是某个被特化为类模板的显式特化的成员类模板的成员,因为其他情况下,语法会要求这种定义以嵌套模板所要求的 <span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="kw1">template</span><span class="sy1"><</span>形参<span class="sy1">></span></span></span> 开始</p>
|
|
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
|
<div class="cpp source-cpp">
|
|
<pre class="de1"><span class="kw1">template</span><span class="sy1"><</span> <span class="kw1">typename</span> T<span class="sy1">></span>
|
|
<span class="kw1">struct</span> A
|
|
<span class="br0">{</span>
|
|
<span class="kw1">struct</span> B <span class="br0">{</span><span class="br0">}</span><span class="sy4">;</span> <span class="co1">// 成员类 </span>
|
|
<span class="kw1">template</span><span class="sy1"><</span><span class="kw1">class</span> U<span class="sy1">></span> <span class="kw1">struct</span> C <span class="br0">{</span><span class="br0">}</span><span class="sy4">;</span> <span class="co1">// 成员类模板</span>
|
|
<span class="br0">}</span><span class="sy4">;</span>
|
|
|
|
<span class="kw1">template</span><span class="sy1"><></span> <span class="co1">// 特化</span>
|
|
<span class="kw1">struct</span> A<span class="sy1"><</span><span class="kw4">int</span><span class="sy1">></span>
|
|
<span class="br0">{</span>
|
|
<span class="kw4">void</span> f<span class="br0">(</span><span class="kw4">int</span><span class="br0">)</span><span class="sy4">;</span> <span class="co1">// 特化的成员函数</span>
|
|
<span class="br0">}</span><span class="sy4">;</span>
|
|
<span class="co1">// template<> 不会用于特化的成员</span>
|
|
<span class="kw4">void</span> A<span class="sy1"><</span><span class="kw4">int</span><span class="sy1">></span><span class="sy4">::</span><span class="me2">f</span><span class="br0">(</span><span class="kw4">int</span><span class="br0">)</span> <span class="br0">{</span> <span class="coMULTI">/* ... */</span> <span class="br0">}</span>
|
|
|
|
<span class="kw1">template</span><span class="sy1"><></span> <span class="co1">// 成员类的特化</span>
|
|
<span class="kw1">struct</span> A<span class="sy1"><</span><span class="kw4">char</span><span class="sy1">></span><span class="sy4">::</span><span class="me2">B</span>
|
|
<span class="br0">{</span>
|
|
<span class="kw4">void</span> f<span class="br0">(</span><span class="br0">)</span><span class="sy4">;</span>
|
|
<span class="br0">}</span><span class="sy4">;</span>
|
|
<span class="co1">// template<> 也不会用于特化的成员类的成员</span>
|
|
<span class="kw4">void</span> A<span class="sy1"><</span><span class="kw4">char</span><span class="sy1">></span><span class="sy4">::</span><span class="me2">B</span><span class="sy4">::</span><span class="me2">f</span><span class="br0">(</span><span class="br0">)</span> <span class="br0">{</span> <span class="coMULTI">/* ... */</span> <span class="br0">}</span>
|
|
|
|
<span class="kw1">template</span><span class="sy1"><></span> <span class="co1">// 成员类模板的特化</span>
|
|
<span class="kw1">template</span><span class="sy1"><</span><span class="kw1">class</span> U<span class="sy1">></span> <span class="kw1">struct</span> A<span class="sy1"><</span><span class="kw4">char</span><span class="sy1">></span><span class="sy4">::</span><span class="me2">C</span>
|
|
<span class="br0">{</span>
|
|
<span class="kw4">void</span> f<span class="br0">(</span><span class="br0">)</span><span class="sy4">;</span>
|
|
<span class="br0">}</span><span class="sy4">;</span>
|
|
|
|
<span class="co1">// template<> 会用于定义被特化为类模板的显式特化的成员类模板的成员</span>
|
|
<span class="kw1">template</span><span class="sy1"><></span>
|
|
<span class="kw1">template</span><span class="sy1"><</span><span class="kw1">class</span> U<span class="sy1">></span> <span class="kw4">void</span> A<span class="sy1"><</span><span class="kw4">char</span><span class="sy1">></span><span class="sy4">::</span><span class="me2">C</span><span class="sy1"><</span>U<span class="sy1">></span><span class="sy4">::</span><span class="me2">f</span><span class="br0">(</span><span class="br0">)</span> <span class="br0">{</span> <span class="coMULTI">/* ... */</span> <span class="br0">}</span></pre></div>
|
|
</div>
|
|
<p>模板的静态数据成员的显式特化在它的声明包含初始化器时是定义;否则它是声明。这些定义必须用花括号进行默认初始化:</p>
|
|
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
|
<div class="cpp source-cpp">
|
|
<pre class="de1"><span class="kw1">template</span><span class="sy1"><></span> X Q<span class="sy1"><</span><span class="kw4">int</span><span class="sy1">></span><span class="sy4">::</span><span class="me2">x</span><span class="sy4">;</span> <span class="co1">// 静态成员的声明</span>
|
|
<span class="kw1">template</span><span class="sy1"><></span> X Q<span class="sy1"><</span><span class="kw4">int</span><span class="sy1">></span><span class="sy4">::</span><span class="me2">x</span><span class="br0">(</span><span class="br0">)</span><span class="sy4">;</span> <span class="co1">// 错误:函数声明</span>
|
|
<span class="kw1">template</span><span class="sy1"><></span> X Q<span class="sy1"><</span><span class="kw4">int</span><span class="sy1">></span><span class="sy4">::</span><span class="me2">x</span><span class="br0">{</span><span class="br0">}</span><span class="sy4">;</span> <span class="co1">// 静态成员的默认初始化定义</span></pre></div>
|
|
</div>
|
|
<p>类模板的成员或成员模板可对于类模板的隐式实例化显式特化,即使成员或成员模板定义于类模板定义中。</p>
|
|
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
|
<div class="cpp source-cpp">
|
|
<pre class="de1"><span class="kw1">template</span><span class="sy1"><</span><span class="kw1">typename</span> T<span class="sy1">></span>
|
|
<span class="kw1">struct</span> A
|
|
<span class="br0">{</span>
|
|
<span class="kw4">void</span> f<span class="br0">(</span>T<span class="br0">)</span><span class="sy4">;</span> <span class="co1">// 成员,声明于主模板中</span>
|
|
<span class="kw4">void</span> h<span class="br0">(</span>T<span class="br0">)</span> <span class="br0">{</span><span class="br0">}</span> <span class="co1">// 成员,定义于主模板中</span>
|
|
<span class="kw1">template</span><span class="sy1"><</span><span class="kw1">class</span> X1<span class="sy1">></span> <span class="kw4">void</span> g1<span class="br0">(</span>T, X1<span class="br0">)</span><span class="sy4">;</span> <span class="co1">// 成员模板</span>
|
|
<span class="kw1">template</span><span class="sy1"><</span><span class="kw1">class</span> X2<span class="sy1">></span> <span class="kw4">void</span> g2<span class="br0">(</span>T, X2<span class="br0">)</span><span class="sy4">;</span> <span class="co1">// 成员模板</span>
|
|
<span class="br0">}</span><span class="sy4">;</span>
|
|
|
|
<span class="co1">// 成员的特化</span>
|
|
<span class="kw1">template</span><span class="sy1"><></span> <span class="kw4">void</span> A<span class="sy1"><</span><span class="kw4">int</span><span class="sy1">></span><span class="sy4">::</span><span class="me2">f</span><span class="br0">(</span><span class="kw4">int</span><span class="br0">)</span><span class="sy4">;</span>
|
|
<span class="co1">// 成员特化 OK,即使在类中定义</span>
|
|
<span class="kw1">template</span><span class="sy1"><></span> <span class="kw4">void</span> A<span class="sy1"><</span><span class="kw4">int</span><span class="sy1">></span><span class="sy4">::</span><span class="me2">h</span><span class="br0">(</span><span class="kw4">int</span><span class="br0">)</span> <span class="br0">{</span><span class="br0">}</span>
|
|
|
|
<span class="co1">// 类外成员模板定义</span>
|
|
<span class="kw1">template</span><span class="sy1"><</span><span class="kw1">class</span> T<span class="sy1">></span>
|
|
<span class="kw1">template</span><span class="sy1"><</span><span class="kw1">class</span> X1<span class="sy1">></span> <span class="kw4">void</span> A<span class="sy1"><</span>T<span class="sy1">></span><span class="sy4">::</span><span class="me2">g1</span><span class="br0">(</span>T, X1<span class="br0">)</span> <span class="br0">{</span><span class="br0">}</span>
|
|
|
|
<span class="co1">// 成员模板特化</span>
|
|
<span class="kw1">template</span><span class="sy1"><></span>
|
|
<span class="kw1">template</span><span class="sy1"><</span><span class="kw1">class</span> X1<span class="sy1">></span> <span class="kw4">void</span> A<span class="sy1"><</span><span class="kw4">int</span><span class="sy1">></span><span class="sy4">::</span><span class="me2">g1</span><span class="br0">(</span><span class="kw4">int</span>, X1<span class="br0">)</span><span class="sy4">;</span>
|
|
|
|
<span class="co1">// 成员模板特化</span>
|
|
<span class="kw1">template</span><span class="sy1"><></span>
|
|
<span class="kw1">template</span><span class="sy1"><></span> <span class="kw4">void</span> A<span class="sy1"><</span><span class="kw4">int</span><span class="sy1">></span><span class="sy4">::</span><span class="me2">g2</span><span class="sy1"><</span><span class="kw4">char</span><span class="sy1">></span><span class="br0">(</span><span class="kw4">int</span>, <span class="kw4">char</span><span class="br0">)</span><span class="sy4">;</span> <span class="co1">// 对于 X2 = char</span>
|
|
|
|
<span class="co1">// 同上,用模板实参推导 (X1 = char)</span>
|
|
<span class="kw1">template</span><span class="sy1"><></span>
|
|
<span class="kw1">template</span><span class="sy1"><></span> <span class="kw4">void</span> A<span class="sy1"><</span><span class="kw4">int</span><span class="sy1">></span><span class="sy4">::</span><span class="me2">g1</span><span class="br0">(</span><span class="kw4">int</span>, <span class="kw4">char</span><span class="br0">)</span><span class="sy4">;</span></pre></div>
|
|
</div>
|
|
<p>成员或成员模板可以在多个外围类模板内嵌套。在这种成员的显式特化中,对每个显式特化的外围类模板都有一个 <span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="kw1">template</span><span class="sy1"><></span></span></span>。</p>
|
|
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
|
<div class="cpp source-cpp">
|
|
<pre class="de1"><span class="kw1">template</span><span class="sy1"><</span><span class="kw1">class</span> T1<span class="sy1">></span> <span class="kw1">struct</span> A
|
|
<span class="br0">{</span>
|
|
<span class="kw1">template</span><span class="sy1"><</span><span class="kw1">class</span> T2<span class="sy1">></span> <span class="kw1">struct</span> B
|
|
<span class="br0">{</span>
|
|
<span class="kw1">template</span><span class="sy1"><</span><span class="kw1">class</span> T3<span class="sy1">></span>
|
|
<span class="kw4">void</span> mf<span class="br0">(</span><span class="br0">)</span><span class="sy4">;</span>
|
|
<span class="br0">}</span><span class="sy4">;</span>
|
|
<span class="br0">}</span><span class="sy4">;</span>
|
|
|
|
<span class="kw1">template</span><span class="sy1"><></span> <span class="kw1">struct</span> A<span class="sy1"><</span><span class="kw4">int</span><span class="sy1">></span><span class="sy4">;</span>
|
|
<span class="kw1">template</span><span class="sy1"><></span> <span class="kw1">template</span><span class="sy1"><></span> <span class="kw1">struct</span> A<span class="sy1"><</span><span class="kw4">char</span><span class="sy1">></span><span class="sy4">::</span><span class="me2">B</span><span class="sy1"><</span><span class="kw4">double</span><span class="sy1">></span><span class="sy4">;</span>
|
|
<span class="kw1">template</span><span class="sy1"><></span> <span class="kw1">template</span><span class="sy1"><></span> <span class="kw1">template</span><span class="sy1"><></span> <span class="kw4">void</span> A<span class="sy1"><</span><span class="kw4">char</span><span class="sy1">></span><span class="sy4">::</span><span class="me2">B</span><span class="sy1"><</span><span class="kw4">char</span><span class="sy1">></span><span class="sy4">::</span><span class="me2">mf</span><span class="sy1"><</span><span class="kw4">double</span><span class="sy1">></span><span class="br0">(</span><span class="br0">)</span><span class="sy4">;</span></pre></div>
|
|
</div>
|
|
<p>在这种嵌套声明中,某些层次可保留不特化(但如果它的外围类没有被特化,那么就不能特化类成员模板)。这种层次的每个声明都需要 <span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="kw1">template</span><span class="sy1"><</span>实参<span class="sy1">></span></span></span>,因为这种特化自身也是模板:</p>
|
|
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
|
<div class="cpp source-cpp">
|
|
<pre class="de1"><span class="kw1">template</span> <span class="sy1"><</span><span class="kw1">class</span> T1<span class="sy1">></span> <span class="kw1">class</span> A
|
|
<span class="br0">{</span>
|
|
<span class="kw1">template</span><span class="sy1"><</span><span class="kw1">class</span> T2<span class="sy1">></span> <span class="kw1">class</span> B
|
|
<span class="br0">{</span>
|
|
<span class="kw1">template</span><span class="sy1"><</span><span class="kw1">class</span> T3<span class="sy1">></span> <span class="kw4">void</span> mf1<span class="br0">(</span>T3<span class="br0">)</span><span class="sy4">;</span> <span class="co1">// 成员模板</span>
|
|
<span class="kw4">void</span> mf2<span class="br0">(</span><span class="br0">)</span><span class="sy4">;</span> <span class="co1">// 非模板成员</span>
|
|
<span class="br0">}</span><span class="sy4">;</span>
|
|
<span class="br0">}</span><span class="sy4">;</span>
|
|
|
|
<span class="co1">// 特化</span>
|
|
<span class="kw1">template</span><span class="sy1"><></span> <span class="co1">// 对于特化的 A</span>
|
|
<span class="kw1">template</span><span class="sy1"><</span><span class="kw1">class</span> X<span class="sy1">></span> <span class="co1">// 对于未特化的 B</span>
|
|
<span class="kw1">class</span> A<span class="sy1"><</span><span class="kw4">int</span><span class="sy1">></span><span class="sy4">::</span><span class="me2">B</span>
|
|
<span class="br0">{</span>
|
|
<span class="kw1">template</span> <span class="sy1"><</span><span class="kw1">class</span> T<span class="sy1">></span> <span class="kw4">void</span> mf1<span class="br0">(</span>T<span class="br0">)</span><span class="sy4">;</span>
|
|
<span class="br0">}</span><span class="sy4">;</span>
|
|
|
|
<span class="co1">// 特化</span>
|
|
<span class="kw1">template</span><span class="sy1"><></span> <span class="co1">// 对于特化的 A</span>
|
|
<span class="kw1">template</span><span class="sy1"><></span> <span class="co1">// 对于特化的 B</span>
|
|
<span class="kw1">template</span><span class="sy1"><</span><span class="kw1">class</span> T<span class="sy1">></span> <span class="co1">// 对于未特化的 mf1</span>
|
|
<span class="kw4">void</span> A<span class="sy1"><</span><span class="kw4">int</span><span class="sy1">></span><span class="sy4">::</span><span class="me2">B</span><span class="sy1"><</span><span class="kw4">double</span><span class="sy1">></span><span class="sy4">::</span><span class="me2">mf1</span><span class="br0">(</span>T t<span class="br0">)</span> <span class="br0">{</span><span class="br0">}</span>
|
|
|
|
<span class="co1">// 错误:B<double> 被特化而且是成员模板,所以它外围的 A 也必须特化</span>
|
|
<span class="kw1">template</span><span class="sy1"><</span><span class="kw1">class</span> Y<span class="sy1">></span>
|
|
<span class="kw1">template</span><span class="sy1"><></span> <span class="kw4">void</span> A<span class="sy1"><</span>Y<span class="sy1">></span><span class="sy4">::</span><span class="me2">B</span><span class="sy1"><</span><span class="kw4">double</span><span class="sy1">></span><span class="sy4">::</span><span class="me2">mf2</span><span class="br0">(</span><span class="br0">)</span> <span class="br0">{</span><span class="br0">}</span></pre></div>
|
|
</div>
|
|
<h3><span class="mw-headline" id=".E7.BC.BA.E9.99.B7.E6.8A.A5.E5.91.8A">缺陷报告</span></h3>
|
|
<p>下列更改行为的缺陷报告追溯地应用于以前出版的 C++ 标准。</p>
|
|
<table class="dsctable" style="font-size:0.8em">
|
|
<tr>
|
|
<th>DR</th>
|
|
<th>应用于</th>
|
|
<th>出版时的行为</th>
|
|
<th>正确行为</th>
|
|
</tr>
|
|
<tr>
|
|
<td><a rel="nofollow" class="external text" href="https://wg21.cmeerw.net/cwg/issue727">CWG 727</a></td>
|
|
<td>C++98</td>
|
|
<td>不允许在类作用域的全特化,即使允许部分特化</td>
|
|
<td>允许在任何作用域的全特化</td>
|
|
</tr>
|
|
</table>
|
|
<h3><span class="mw-headline" id=".E5.8F.82.E9.98.85">参阅</span></h3>
|
|
<ul>
|
|
<li><a href="cpp-language-templates.html">模板</a></li>
|
|
<li><a href="cpp-language-class_template.html">类模板</a></li>
|
|
<li><a href="cpp-language-function_template.html">函数模板</a></li>
|
|
<li><a href="cpp-language-partial_specialization.html">部分特化</a></li>
|
|
</ul>
|
|
</div>
|
|
<div class="visualClear"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</body>
|
|
</html>
|