﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-woaidongmao-随笔分类-模板存档</title><link>http://www.cppblog.com/woaidongmao/category/7770.html</link><description>文章均收录自他人博客，但不喜标题前加-[转贴]，因其丑陋，见谅！~</description><language>zh-cn</language><lastBuildDate>Sun, 21 Sep 2008 16:16:52 GMT</lastBuildDate><pubDate>Sun, 21 Sep 2008 16:16:52 GMT</pubDate><ttl>60</ttl><item><title>C++的模板及模板特化</title><link>http://www.cppblog.com/woaidongmao/archive/2008/09/15/61905.html</link><dc:creator>肥仔</dc:creator><author>肥仔</author><pubDate>Mon, 15 Sep 2008 15:22:00 GMT</pubDate><guid>http://www.cppblog.com/woaidongmao/archive/2008/09/15/61905.html</guid><wfw:comment>http://www.cppblog.com/woaidongmao/comments/61905.html</wfw:comment><comments>http://www.cppblog.com/woaidongmao/archive/2008/09/15/61905.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/woaidongmao/comments/commentRss/61905.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/woaidongmao/services/trackbacks/61905.html</trackback:ping><description><![CDATA[<p></p> <p class="MsoNormal"><span lang="EN-US" style="color: black; font-family: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: arial">&nbsp;&nbsp; </span><span style="color: black; font-family: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: arial">说起<span lang="EN-US">C++</span>的模板及模板特化，<span lang="EN-US">&nbsp;</span>相信很多人都很熟悉<span lang="EN-US">&nbsp;</span>，但是说到模板特化的几种类型，相信了解的人就不是很多。我这里归纳了模板特化的几种类型，<span lang="EN-US">&nbsp;</span>一是特化为绝对类型；<span lang="EN-US">&nbsp;</span>而是特化为引用，指针类型；三是特化为另外一个模板类。 <span lang="EN-US"><?xml:namespace prefix = o /><o:p></o:p></span></span></p> <p class="MsoNormal"><span lang="EN-US" style="color: black; font-family: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: arial"><o:p>&nbsp;</o:p></span></p> <p class="MsoNormal" style="text-indent: 21pt; mso-char-indent-count: 2.0"><span style="color: black; font-family: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: arial">这里用一个简单的例子来说明这三种情况：<span lang="EN-US"> <br></span></span><span lang="EN-US" style="color: blue; font-family: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: arial">// general version <br>template&lt;class T&gt; <br>class Compare <br>{ <br>public: <br>&nbsp;&nbsp;&nbsp; static bool IsEqual(const T&amp; lh, const T&amp; rh) <br>&nbsp;&nbsp;&nbsp; { <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return lh == rh; <br>&nbsp;&nbsp;&nbsp; } <br>};</span><span lang="EN-US" style="color: black; font-family: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: arial"><o:p></o:p></span></p> <p class="MsoNormal" style="text-indent: 21pt; mso-char-indent-count: 2.0"><span style="color: black; font-family: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: arial">这是一个用于比较的模板类，里面可以有多种用于比较的函数，<span lang="EN-US">&nbsp;</span>以<span lang="EN-US">IsEqual</span>为例。<span lang="EN-US"> <br>&nbsp; <br></span></span><b style="mso-bidi-font-weight: normal"><span style="font-size: 14pt; color: black; font-family: 宋体; mso-bidi-font-family: arial">一、特化为绝对类型 </span></b><span lang="EN-US" style="color: black; font-family: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: arial"><o:p></o:p></span></p> <p class="MsoNormal" style="text-indent: 21pt; mso-char-indent-count: 2.0"><span style="color: black; font-family: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: arial">也就是说直接为某个特定类型做特化，这是我们最常见的一种特化方式，<span lang="EN-US">&nbsp;</span>如特化为<span lang="EN-US">float, double</span>等<span lang="EN-US"> <br></span></span><span lang="EN-US" style="color: blue; font-family: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: arial">// specialize for float <br>template&lt;&gt; <br>class Compare&lt;float&gt; <br>{ <br>public: <br>&nbsp;&nbsp;&nbsp; static bool IsEqual(const float&amp; lh, const float&amp; rh) <br>&nbsp;&nbsp;&nbsp; { <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return abs(lh - rh) &lt; 10e-3; <br>&nbsp;&nbsp;&nbsp; } <br>}; <br><br>// specialize for double <br>template&lt;&gt; <br>class Compare&lt;double&gt; <br>{ <br>public: <br>&nbsp;&nbsp;&nbsp; static bool IsEqual(const double&amp; lh, const double&amp; rh) <br>&nbsp;&nbsp;&nbsp; { <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return abs(lh - rh) &lt; 10e-6; <br>&nbsp;&nbsp;&nbsp; } <br>}; <o:p></o:p></span></p> <p class="MsoNormal"><b style="mso-bidi-font-weight: normal"><span lang="EN-US" style="font-size: 14pt; color: black; font-family: 宋体; mso-bidi-font-family: arial"><o:p>&nbsp;</o:p></span></b></p> <p class="MsoNormal"><b style="mso-bidi-font-weight: normal"><span style="font-size: 14pt; color: black; font-family: 宋体; mso-bidi-font-family: arial">二、特化为引用，指针类型<span lang="EN-US"><o:p></o:p></span></span></b></p> <p class="MsoNormal" style="text-indent: 21pt; mso-char-indent-count: 2.0"><span style="color: black; font-family: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: arial">这种特化我最初是在<span lang="EN-US">stl</span>源码的的<span lang="EN-US">iterator_traits</span>特化中发现的，<span lang="EN-US">&nbsp;</span>如下：<span lang="EN-US"> <br></span></span><span lang="EN-US" style="color: blue; font-family: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: arial">template &lt;class _Iterator&gt; <br>struct iterator_traits <o:p></o:p></span></p> <p class="MsoNormal"><span lang="EN-US" style="color: blue; font-family: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: arial">{ <br>&nbsp; typedef typename _Iterator::iterator_category iterator_category; <br>&nbsp; typedef typename _Iterator::value_type&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; value_type; <br>&nbsp; typedef typename _Iterator::difference_type&nbsp;&nbsp; difference_type; <br>&nbsp; typedef typename _Iterator::pointer&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pointer; <br>&nbsp; typedef typename _Iterator::reference&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; reference; <br>}; <br><br>// specialize for _Tp* <br>template &lt;class _Tp&gt; <br>struct iterator_traits&lt;_Tp*&gt; <o:p></o:p></span></p> <p class="MsoNormal"><span lang="EN-US" style="color: blue; font-family: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: arial">{ <br>&nbsp; typedef random_access_iterator_tag iterator_category; <br>&nbsp; typedef _Tp&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; value_type; <br>&nbsp; typedef ptrdiff_t&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; difference_type;<o:p></o:p></span></p> <p class="MsoNormal" style="text-indent: 10.5pt; mso-char-indent-count: 1.0"><span lang="EN-US" style="color: blue; font-family: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: arial">typedef _Tp*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pointer; <br>&nbsp; typedef _Tp&amp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; reference; <br>}; <br><br>// specialize for const _Tp* <br>template &lt;class _Tp&gt; <br>struct iterator_traits&lt;const _Tp*&gt; <o:p></o:p></span></p> <p class="MsoNormal"><span lang="EN-US" style="color: blue; font-family: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: arial">{ <br>&nbsp; typedef random_access_iterator_tag iterator_category; <br>&nbsp; typedef _Tp&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; value_type; <br>&nbsp; typedef ptrdiff_t&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; difference_type; <br>&nbsp; typedef const _Tp*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pointer; <br>&nbsp; typedef const _Tp&amp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; reference; <br>}; <br style="mso-special-character: line-break"><br style="mso-special-character: line-break"></span><span lang="EN-US" style="color: black; font-family: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: arial"><o:p></o:p></span></p> <p class="MsoNormal" style="text-indent: 21pt; mso-char-indent-count: 2.0"><span style="color: black; font-family: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: arial">当然，除了<span lang="EN-US">T*, </span>我们也可以将<span lang="EN-US">T</span>特化为<span lang="EN-US"> const T*, T&amp;, const T&amp;</span>等，以下还是以<span lang="EN-US">T*</span>为例：<span lang="EN-US"> <br></span></span><span lang="EN-US" style="color: blue; font-family: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: arial">// specialize for T* <br>template&lt;class T&gt; <br>class Compare&lt;T*&gt; <br>{ <br>public: <br>&nbsp;&nbsp;&nbsp; static bool IsEqual(const T* lh, const T* rh) <br>&nbsp;&nbsp;&nbsp; { <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return Compare&lt;T&gt;::IsEqual(*lh, *rh); <br>&nbsp;&nbsp;&nbsp; } <br>}; <o:p></o:p></span></p> <p class="MsoNormal" style="text-indent: 21pt; mso-char-indent-count: 2.0"><span style="color: black; font-family: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: arial">这种特化其实是就不是一种绝对的特化，<span lang="EN-US">&nbsp;</span>它只是对类型做了某些限定，但仍然保留了其一定的模板性，这种特化给我们提供了极大的方便，<span lang="EN-US">&nbsp;</span>如这里，<span lang="EN-US">&nbsp;</span>我们就不需要对<span lang="EN-US">int*, float*, double*</span>等等类型分别做特化了。<span lang="EN-US"> <br><br></span></span><b style="mso-bidi-font-weight: normal"><span style="font-size: 14pt; color: black; font-family: 宋体; mso-bidi-font-family: arial">三、特化为另外一个模板类 </span></b><span lang="EN-US" style="color: black; font-family: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: arial"><o:p></o:p></span></p> <p class="MsoNormal" style="text-indent: 21pt; mso-char-indent-count: 2.0"><span style="color: black; font-family: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: arial">这其实是第二种方式的扩展，其实也是对类型做了某种限定，而不是绝对化为某个具体类型，如下：<span lang="EN-US"> <br></span></span><span lang="EN-US" style="color: blue; font-family: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: arial">// specialize for vector&lt;T&gt; <br>template&lt;class T&gt; <br>class Compare&lt;vector&lt;T&gt; &gt; <br>{ <br>public: <br>&nbsp;&nbsp;&nbsp; static bool IsEqual(const vector&lt;T&gt;&amp; lh, const vector&lt;T&gt;&amp; rh) <br>&nbsp;&nbsp;&nbsp; { <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(lh.size() != rh.size())<o:p></o:p></span></p> <p class="MsoNormal" style="text-indent: 52.5pt; mso-char-indent-count: 5.0"><span lang="EN-US" style="color: blue; font-family: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: arial">return false;<o:p></o:p></span></p> <p class="MsoNormal"><span lang="EN-US" style="color: blue; font-family: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: arial">&nbsp;&nbsp;&nbsp; <span style="mso-spacerun: yes">&nbsp;&nbsp; </span> else <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; { <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for(int i = 0; i &lt; lh.size(); ++i) <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; { <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(lh[i] != rh[i]) return false; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return true; <br>&nbsp;&nbsp;&nbsp; } <br>}; <o:p></o:p></span></p> <p class="MsoNormal"><span lang="EN-US" style="color: blue; font-family: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: arial"><o:p>&nbsp;</o:p></span></p> <p class="MsoNormal" style="text-indent: 21pt; mso-char-indent-count: 2.0"><span style="color: black; font-family: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: arial">这就把<span lang="EN-US">IsEqual</span>的参数限定为一种<span lang="EN-US">vector</span>类型，<span lang="EN-US">&nbsp;</span>但具体是<span lang="EN-US">vector&lt;int&gt;</span>还是<span lang="EN-US">vector&lt;float&gt;</span>，<span lang="EN-US">&nbsp;</span>我们可以不关心，<span lang="EN-US">&nbsp;</span>因为对于这两种类型，我们的处理方式是一样的，我们可以把这种方式称为<span lang="EN-US">“</span>半特化<span lang="EN-US">”</span>。 <span lang="EN-US"><o:p></o:p></span></span></p> <p class="MsoNormal" style="text-indent: 21pt; mso-char-indent-count: 2.0"><span style="color: black; font-family: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: arial">当然，<span lang="EN-US">&nbsp;</span>我们可以将其<span lang="EN-US">“</span>半特化<span lang="EN-US">”</span>为任何我们自定义的模板类类型：<span lang="EN-US"> <br></span></span><span lang="EN-US" style="color: blue; font-family: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: arial">// specialize for any template class type <br>template &lt;class T1&gt;&nbsp; <br>struct SpecializedType <br>{ <br>&nbsp;&nbsp;&nbsp; T1 x1; <br>&nbsp;&nbsp;&nbsp; T1 x2; <br>}; <o:p></o:p></span></p> <p class="MsoNormal"><span lang="EN-US" style="color: blue; font-family: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: arial"><br>template &lt;class T&gt; <br>class Compare&lt;SpecializedType&lt;T&gt; &gt; <br>{ <br>public: <br>&nbsp;&nbsp;&nbsp; static bool IsEqual(const SpecializedType&lt;T&gt;&amp; lh, const SpecializedType&lt;T&gt;&amp; rh) <br>&nbsp;&nbsp;&nbsp; { <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return Compare&lt;T&gt;::IsEqual(lh.x1 + lh.x2, rh.x1 + rh.x2); <br>&nbsp;&nbsp;&nbsp; } <br>}; <br style="mso-special-character: line-break"><br style="mso-special-character: line-break"><o:p></o:p></span></p> <p class="MsoNormal" style="text-indent: 21pt; mso-char-indent-count: 2.0"><span style="color: black; font-family: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: arial">这就是三种类型的模板特化，<span lang="EN-US">&nbsp;</span>我们可以这么使用这个<span lang="EN-US">Compare</span>类：<span lang="EN-US"> <br></span></span><span lang="EN-US" style="color: blue; font-family: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: arial">// int <br>&nbsp;&nbsp;&nbsp; int i1 = 10; <br>&nbsp;&nbsp;&nbsp; int i2 = 10; <br>&nbsp;&nbsp;&nbsp; bool r1 = Compare&lt;int&gt;::IsEqual(i1, i2); <br><br>&nbsp;&nbsp;&nbsp; // float <br>&nbsp;&nbsp;&nbsp; float f1 = 10; <br>&nbsp;&nbsp;&nbsp; float f2 = 10; <br>&nbsp;&nbsp;&nbsp; bool r2 = Compare&lt;float&gt;::IsEqual(f1, f2); <br><br>&nbsp;&nbsp;&nbsp; // double <br>&nbsp;&nbsp;&nbsp; double d1 = 10; <br>&nbsp;&nbsp;&nbsp; double d2 = 10; <br>&nbsp;&nbsp;&nbsp; bool r3 = Compare&lt;double&gt;::IsEqual(d1, d2); <br><br>&nbsp;&nbsp;&nbsp; // pointer <br>&nbsp;&nbsp;&nbsp; int* p1 = &amp;i1; <br>&nbsp;&nbsp;&nbsp; int* p2 = &amp;i2;<o:p></o:p></span></p> <p class="MsoNormal" style="text-indent: 21pt; mso-char-indent-count: 2.0"><span lang="EN-US" style="color: blue; font-family: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: arial">bool r4 = Compare&lt;int*&gt;::IsEqual(p1, p2); <br><br>&nbsp;&nbsp;&nbsp; // vector&lt;T&gt; <br>&nbsp;&nbsp;&nbsp; vector&lt;int&gt; v1; <br>&nbsp;&nbsp;&nbsp; v1.push_back(1); <br>&nbsp;&nbsp;&nbsp; v1.push_back(2); <br><br>&nbsp;&nbsp;&nbsp; vector&lt;int&gt; v2; <br>&nbsp;&nbsp;&nbsp; v2.push_back(1); <br>&nbsp;&nbsp;&nbsp; v2.push_back(2); <br>&nbsp;&nbsp;&nbsp; bool r5 = Compare&lt;vector&lt;int&gt; &gt;::IsEqual(v1, v2); <br><br>&nbsp;&nbsp;&nbsp; // custom template class&nbsp; <br>&nbsp;&nbsp;&nbsp; SpecializedType&lt;float&gt; s1 = {<?xml:namespace prefix = st1 /><st1:chmetcnv w:st="on" tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue="10.1" unitname="F">10.1f</st1:chmetcnv>,<st1:chmetcnv w:st="on" tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue="10.2" unitname="F">10.2f</st1:chmetcnv>}; <br>&nbsp;&nbsp;&nbsp; SpecializedType&lt;float&gt; s2 = {<st1:chmetcnv w:st="on" tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue="10.3" unitname="F">10.3f</st1:chmetcnv>,<st1:chmetcnv w:st="on" tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue="10" unitname="F">10.0f</st1:chmetcnv>}; <br>&nbsp;&nbsp;&nbsp; bool r6 = Compare&lt;SpecializedType&lt;float&gt; &gt;::IsEqual(s1, s2);<o:p></o:p></span></p><img src ="http://www.cppblog.com/woaidongmao/aggbug/61905.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/woaidongmao/" target="_blank">肥仔</a> 2008-09-15 23:22 <a href="http://www.cppblog.com/woaidongmao/archive/2008/09/15/61905.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++ Template 的相关书籍</title><link>http://www.cppblog.com/woaidongmao/archive/2008/09/15/61901.html</link><dc:creator>肥仔</dc:creator><author>肥仔</author><pubDate>Mon, 15 Sep 2008 15:08:00 GMT</pubDate><guid>http://www.cppblog.com/woaidongmao/archive/2008/09/15/61901.html</guid><wfw:comment>http://www.cppblog.com/woaidongmao/comments/61901.html</wfw:comment><comments>http://www.cppblog.com/woaidongmao/archive/2008/09/15/61901.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/woaidongmao/comments/commentRss/61901.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/woaidongmao/services/trackbacks/61901.html</trackback:ping><description><![CDATA[<p>&nbsp;&nbsp;&nbsp; 聊聊C++ Template的一些好书吧！ <p>&nbsp;&nbsp;&nbsp; 关于template一本很全面的介绍C++ Template的书在china-pub上可以找得到：<a href="http://www.china-pub.com/computers/common/info.asp?id=17709">http://www.china-pub.com/computers/common/info.asp?id=17709</a>，也有中文翻译版本(哈哈，刚才看了一下，英文版缺货，中文版绝版，幸亏偶买的早)。 <p>&nbsp;&nbsp;&nbsp; 如果再配合看这本：《Modern C++ Design: Generic Programming and Design Patterns Applied》<a href="http://www.china-pub.com/computers/common/info.asp?id=12302">http://www.china-pub.com/computers/common/info.asp?id=12302</a>，这个也有中文版的，ms也是侯捷翻译的，不过我不喜欢他的风格。 <p>&nbsp;&nbsp;&nbsp; 常用的C++ STL库就是template的一个很好的demo，这方面的书很多。《泛型编程与STL》<a href="http://www.china-pub.com/computers/common/info.asp?id=14364">http://www.china-pub.com/computers/common/info.asp?id=14364</a>这本书貌似大家的评价不错，不过我没有看过，本来打算买，无奈囊肿羞涩，不过我还是决定省吃俭用买下来看看。《C++标准程序库——自修教程与参考手册》<a href="http://www.china-pub.com/computers/common/info.asp?id=7645">http://www.china-pub.com/computers/common/info.asp?id=7645</a>，这本书全面的介绍STL的应用，这本书很适合做为参考手册用。又是侯捷翻译的，很贵，多贵？可以演一桌水浒了！！（这就是我为什么特烦他了，他的书都死贵，从这个角度上说我还是支持盗版）以前好几个师弟买了，我都蹭书看，呵呵。侯捷还自己写了一本《STL源码剖析》<a href="http://www.china-pub.com/computers/common/info.asp?id=6384">http://www.china-pub.com/computers/common/info.asp?id=6384</a>，不过真相知道STL怎么回事，还是自己跟源代码最好。 <p>&nbsp;&nbsp;&nbsp; 微软的ATL（Active Template Library）库也是一个很牛的demo，它比STL更难理解一点，不过基本的思想都差不多。《ATL技术内幕》（&lt;ATL Internals&gt;）是一本不错的书<a href="http://www.china-pub.com/computers/common/info.asp?id=12480">http://www.china-pub.com/computers/common/info.asp?id=12480</a>，这本书可以让你知道ATL深层的机制，不是专门教你怎么用ATL开发的，比较好的ATL开发的书国内都没有，只有一些关于COM的书中零零星星的提到，很多年以前出过基本翻译的，不过早绝版了。Amazon上还有本叫《Inside ATL》微软出的<a href="http://www.amazon.com/gp/product/1572318589/qid=1137230246/sr=8-1/ref=pd_bbs_1/102-5612415-4809763?n=507846&amp;s=books&amp;v=glance">http://www.amazon.com/gp/product/1572318589/qid=1137230246/sr=8-1/ref=pd_bbs_1/102-5612415-4809763?n=507846&amp;s=books&amp;v=glance</a>，不过这本没看过，国内没有引进。要真正学会ATL还需要很多COM和Windows的基本知识，这就会掉到另两个更大的坑里面！ <p>&nbsp;&nbsp;&nbsp; 另一个关于Template的是TMP(Template MetaProgramming)，关于TMP编程的一本好书是：《C++ Template Metaprogramming》<a href="http://www.amazon.com/gp/product/0321227255/qid=1114520696/sr=1-4/ref=sr_1_4/102-5612415-4809763?s=books&amp;v=glance&amp;n=283155">http://www.amazon.com/gp/product/0321227255/qid=1114520696/sr=1-4/ref=sr_1_4/102-5612415-4809763?s=books&amp;v=glance&amp;n=283155</a>，据说中文版由荣耀和侯捷翻译，06年将会出版，不过我觉得看英文的最好。TMP将C++的template技术发挥到了极致的境界，越看越觉得舒服，并且感慨：牛人都是怎么炼成的阿？ <p>&nbsp;&nbsp;&nbsp; 其实，还是那句老话：“聪明在于学习，天才在于积累”，只是在寻寻觅觅中，忘记了最根本的。</p><img src ="http://www.cppblog.com/woaidongmao/aggbug/61901.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/woaidongmao/" target="_blank">肥仔</a> 2008-09-15 23:08 <a href="http://www.cppblog.com/woaidongmao/archive/2008/09/15/61901.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++ 的静态分派技术</title><link>http://www.cppblog.com/woaidongmao/archive/2008/09/15/61861.html</link><dc:creator>肥仔</dc:creator><author>肥仔</author><pubDate>Mon, 15 Sep 2008 05:42:00 GMT</pubDate><guid>http://www.cppblog.com/woaidongmao/archive/2008/09/15/61861.html</guid><wfw:comment>http://www.cppblog.com/woaidongmao/comments/61861.html</wfw:comment><comments>http://www.cppblog.com/woaidongmao/archive/2008/09/15/61861.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/woaidongmao/comments/commentRss/61861.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/woaidongmao/services/trackbacks/61861.html</trackback:ping><description><![CDATA[<div id="main"> <div class="post"> <div class="postbody"> <div><span lang="EN-US"><font face="Times New Roman" size="2">我们可以用不同的整数来实例化同一个模板，从而构造不同的类型，进而在编译期执行某些抉择。</font> </span></div> <div><font size="3"><span lang="EN-US"><font face="Times New Roman"> <p style="margin: 7.8pt 0cm; mso-para-margin-top: .5gd; mso-para-margin-right: 0cm; mso-para-margin-bottom: .5gd; mso-para-margin-left: 0cm"></p> <hr id="[object]">  <p></p></font></span></font> <p style="margin: 7.8pt 0cm; mso-para-margin-top: .5gd; mso-para-margin-right: 0cm; mso-para-margin-bottom: .5gd; mso-para-margin-left: 0cm"><font size="2"><span lang="EN-US"><font face="Times New Roman">Alexandrescu</font> </span><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">最初设计的一个简单的模版，现在成了泛型设计的常用手法：</span> </font></p> <p style="background: #d9d9d9; margin: 0cm 0cm 0pt; text-align: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="font-size: 10pt; color: blue; font-family: 'Lucida Console'; mso-font-kerning: 0pt; mso-no-proof: yes">template</span> <span lang="EN-US" style="font-size: 10pt; font-family: 'Lucida Console'; mso-font-kerning: 0pt; mso-no-proof: yes">&lt;<font face="Lucida Console"><span style="color: blue">int</span> v&gt;<?xml:namespace prefix = o /><o:p></o:p></font></span> </p> <p style="background: #d9d9d9; margin: 0cm 0cm 0pt; text-align: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="font-size: 10pt; color: blue; font-family: 'Lucida Console'; mso-font-kerning: 0pt; mso-no-proof: yes">struct</span> <span lang="EN-US" style="font-size: 10pt; font-family: 'Lucida Console'; mso-font-kerning: 0pt; mso-no-proof: yes">Int2Type {<o:p></o:p></span> </p> <p style="background: #d9d9d9; margin: 0cm 0cm 0pt; text-align: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="font-size: 10pt; font-family: 'Lucida Console'; mso-font-kerning: 0pt; mso-no-proof: yes"><font face="Lucida Console"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp; </span><span style="color: blue">enum</span> { value<span style="mso-spacerun: yes">&nbsp; </span>= v };<o:p></o:p></font> </span></p> <p style="background: #d9d9d9; margin: 0cm 0cm 0pt"><span lang="EN-US" style="font-size: 10pt; font-family: 'Lucida Console'; mso-font-kerning: 0pt; mso-no-proof: yes">};<o:p></o:p></span> </p> <p style="margin: 7.8pt 0cm; mso-para-margin-top: .5gd; mso-para-margin-right: 0cm; mso-para-margin-bottom: .5gd; mso-para-margin-left: 0cm"><span style="font-size: 10pt; font-family: 宋体; mso-font-kerning: 0pt; mso-hansi-font-family: 'Lucida Console'; mso-ascii-font-family: 'Lucida Console'; mso-no-proof: yes">对于每一个不同的常整数，</span> <span lang="EN-US" style="font-size: 10pt; font-family: 'Lucida Console'; mso-font-kerning: 0pt; mso-no-proof: yes">Int2Type</span> <span style="font-size: 10pt; font-family: 宋体; mso-font-kerning: 0pt; mso-hansi-font-family: 'Lucida Console'; mso-ascii-font-family: 'Lucida Console'; mso-no-proof: yes">都代表不同的类型。这是因为不同的模版实例化都代表不同的类型，也就是说</span> <span lang="EN-US" style="font-size: 10pt; font-family: 'Lucida Console'; mso-font-kerning: 0pt; mso-no-proof: yes">Int2Type&lt;0&gt;</span> <span style="font-size: 10pt; font-family: 宋体; mso-font-kerning: 0pt; mso-hansi-font-family: 'Lucida Console'; mso-ascii-font-family: 'Lucida Console'; mso-no-proof: yes">和</span> <span lang="EN-US" style="font-size: 10pt; font-family: 'Lucida Console'; mso-font-kerning: 0pt; mso-no-proof: yes">Int2Type&lt;1&gt;</span> <span style="font-size: 10pt; font-family: 宋体; mso-font-kerning: 0pt; mso-hansi-font-family: 'Lucida Console'; mso-ascii-font-family: 'Lucida Console'; mso-no-proof: yes">是完全不同的。</span> <span lang="EN-US" style="font-size: 10pt; font-family: 'Lucida Console'; mso-font-kerning: 0pt; mso-no-proof: yes"><o:p></o:p></span></p> <p style="margin: 7.8pt 0cm; mso-para-margin-top: .5gd; mso-para-margin-right: 0cm; mso-para-margin-bottom: .5gd; mso-para-margin-left: 0cm"><span style="font-size: 10pt; font-family: 宋体; mso-font-kerning: 0pt; mso-hansi-font-family: 'Lucida Console'; mso-ascii-font-family: 'Lucida Console'; mso-no-proof: yes">当你想根据编译时结果来进行某些抉择——例如选择不同的函数——时，你可以依赖一个常整数来帮你完成分派工作，这时</span> <span lang="EN-US" style="font-size: 10pt; font-family: 'Lucida Console'; mso-font-kerning: 0pt; mso-no-proof: yes">Int2Type</span> <span style="font-size: 10pt; font-family: 宋体; mso-font-kerning: 0pt; mso-hansi-font-family: 'Lucida Console'; mso-ascii-font-family: 'Lucida Console'; mso-no-proof: yes">便可以帮你是实现这个方法。</span> <span lang="EN-US" style="font-size: 10pt; font-family: 'Lucida Console'; mso-font-kerning: 0pt; mso-no-proof: yes"><o:p></o:p></span></p> <p style="margin: 7.8pt 0cm; mso-para-margin-top: .5gd; mso-para-margin-right: 0cm; mso-para-margin-bottom: .5gd; mso-para-margin-left: 0cm"><span style="font-size: 10pt; font-family: 宋体; mso-font-kerning: 0pt; mso-hansi-font-family: 'Lucida Console'; mso-ascii-font-family: 'Lucida Console'; mso-no-proof: yes">一般来说，你在下面两个情况中需要使用</span> <span lang="EN-US" style="font-size: 10pt; font-family: 'Lucida Console'; mso-font-kerning: 0pt; mso-no-proof: yes">Int2Type</span> <span style="font-size: 10pt; font-family: 宋体; mso-font-kerning: 0pt; mso-hansi-font-family: 'Lucida Console'; mso-ascii-font-family: 'Lucida Console'; mso-no-proof: yes">：</span> <span lang="EN-US" style="font-size: 10pt; font-family: 'Lucida Console'; mso-font-kerning: 0pt; mso-no-proof: yes"><o:p></o:p></span></p> <p style="margin: 0cm 0cm 0pt 21pt; text-indent: -21pt; tab-stops: list 21.0pt; mso-list: l0 level1 lfo1"><span lang="EN-US" style="font-size: 10pt; font-family: wingdings; mso-bidi-font-family: wingdings; mso-font-kerning: 0pt; mso-fareast-font-family: wingdings; mso-no-proof: yes"><span style="mso-list: ignore"><font face="Wingdings">l</font> <span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span style="font-size: 10pt; font-family: 宋体; mso-font-kerning: 0pt; mso-hansi-font-family: 'Lucida Console'; mso-ascii-font-family: 'Lucida Console'; mso-no-proof: yes">你需要根据编译时常量来调用不同的函数</span> <span lang="EN-US" style="font-size: 10pt; font-family: 'Lucida Console'; mso-font-kerning: 0pt; mso-no-proof: yes"><o:p></o:p></span></p> <p style="margin: 0cm 0cm 0pt 21pt; text-indent: -21pt; tab-stops: list 21.0pt; mso-list: l0 level1 lfo1"><span lang="EN-US" style="font-family: wingdings; mso-bidi-font-family: wingdings; mso-fareast-font-family: wingdings"><span style="mso-list: ignore"><font face="Wingdings" size="3">l</font> <span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span style="font-size: 10pt; font-family: 宋体; mso-font-kerning: 0pt; mso-hansi-font-family: 'Lucida Console'; mso-ascii-font-family: 'Lucida Console'; mso-no-proof: yes">你需要在编译时执行分派工作</span> </p> <p style="margin: 7.8pt 0cm; mso-para-margin-top: .5gd; mso-para-margin-right: 0cm; mso-para-margin-bottom: .5gd; mso-para-margin-left: 0cm"><span style="font-size: 10pt; font-family: 宋体; mso-font-kerning: 0pt; mso-hansi-font-family: 'Lucida Console'; mso-ascii-font-family: 'Lucida Console'; mso-no-proof: yes">如果是在运行时执行分派工作，你可以用</span> <span lang="EN-US" style="font-size: 10pt; font-family: 'Lucida Console'; mso-font-kerning: 0pt; mso-no-proof: yes">if-else</span> <span style="font-size: 10pt; font-family: 宋体; mso-font-kerning: 0pt; mso-hansi-font-family: 'Lucida Console'; mso-ascii-font-family: 'Lucida Console'; mso-no-proof: yes">或</span> <span lang="EN-US" style="font-size: 10pt; font-family: 'Lucida Console'; mso-font-kerning: 0pt; mso-no-proof: yes">switch</span> <span style="font-size: 10pt; font-family: 宋体; mso-font-kerning: 0pt; mso-hansi-font-family: 'Lucida Console'; mso-ascii-font-family: 'Lucida Console'; mso-no-proof: yes">语句来简单的实现。在大部分的时候，这种运行时成本都是微不足道的。但是，有时它们却不能满足你的要求。既是是在编译期可以决定其分支，编译器还是会勤劳的为你编译其所有的分支，这也就意味着</span> <span lang="EN-US" style="font-size: 10pt; font-family: 'Lucida Console'; mso-font-kerning: 0pt; mso-no-proof: yes">if-else</span> <span style="font-size: 10pt; font-family: 宋体; mso-font-kerning: 0pt; mso-hansi-font-family: 'Lucida Console'; mso-ascii-font-family: 'Lucida Console'; mso-no-proof: yes">的所有分支必须被成功编译。有些困惑？继续看下去：</span> <span lang="EN-US" style="font-size: 10pt; font-family: 'Lucida Console'; mso-font-kerning: 0pt; mso-no-proof: yes"><o:p></o:p></span></p> <p style="margin: 7.8pt 0cm; mso-para-margin-top: .5gd; mso-para-margin-right: 0cm; mso-para-margin-bottom: .5gd; mso-para-margin-left: 0cm"><span style="font-size: 10pt; font-family: 宋体; mso-font-kerning: 0pt; mso-hansi-font-family: 'Lucida Console'; mso-ascii-font-family: 'Lucida Console'; mso-no-proof: yes">考虑下面的情形：你设计了一个泛型容器</span> <span lang="EN-US" style="font-size: 10pt; font-family: 'Lucida Console'; mso-font-kerning: 0pt; mso-no-proof: yes">NiftyContainer</span> <span style="font-size: 10pt; font-family: 宋体; mso-font-kerning: 0pt; mso-hansi-font-family: 'Lucida Console'; mso-ascii-font-family: 'Lucida Console'; mso-no-proof: yes">：</span> <span lang="EN-US" style="font-size: 10pt; font-family: 'Lucida Console'; mso-font-kerning: 0pt; mso-no-proof: yes"><o:p></o:p></span></p> <p style="background: #d9d9d9; margin: 0cm 0cm 0pt; text-align: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="font-size: 10pt; color: blue; font-family: 'Lucida Console'; mso-font-kerning: 0pt; mso-no-proof: yes">template</span> <span lang="EN-US" style="font-size: 10pt; font-family: 'Lucida Console'; mso-font-kerning: 0pt; mso-no-proof: yes">&lt;<font face="Lucida Console"><span style="color: blue">class</span> T&gt; <span style="color: blue">class</span> NiftyContainer {<o:p></o:p></font></span> </p> <p style="background: #d9d9d9; margin: 0cm 0cm 0pt; text-align: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="font-size: 10pt; font-family: 'Lucida Console'; mso-font-kerning: 0pt; mso-no-proof: yes"><font face="Lucida Console"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp; </span>...<o:p></o:p></font> </span></p> <p style="background: #d9d9d9; margin: 0cm 0cm 0pt"><span lang="EN-US" style="font-size: 10pt; font-family: 'Lucida Console'; mso-font-kerning: 0pt; mso-no-proof: yes">};<o:p></o:p></span> </p> <p style="margin: 7.8pt 0cm; mso-para-margin-top: .5gd; mso-para-margin-right: 0cm; mso-para-margin-bottom: .5gd; mso-para-margin-left: 0cm"><span style="font-size: 10pt; font-family: 宋体; mso-font-kerning: 0pt; mso-hansi-font-family: 'Lucida Console'; mso-ascii-font-family: 'Lucida Console'; mso-no-proof: yes">令</span> <span lang="EN-US" style="font-size: 10pt; font-family: 'Lucida Console'; mso-font-kerning: 0pt; mso-no-proof: yes">NiftyContainer</span> <span style="font-size: 10pt; font-family: 宋体; mso-font-kerning: 0pt; mso-hansi-font-family: 'Lucida Console'; mso-ascii-font-family: 'Lucida Console'; mso-no-proof: yes">容器包含指向</span> <span lang="EN-US" style="font-size: 10pt; font-family: 'Lucida Console'; mso-font-kerning: 0pt; mso-no-proof: yes">T</span> <span style="font-size: 10pt; font-family: 宋体; mso-font-kerning: 0pt; mso-hansi-font-family: 'Lucida Console'; mso-ascii-font-family: 'Lucida Console'; mso-no-proof: yes">对象的指针。为了复制</span> <span lang="EN-US" style="font-size: 10pt; font-family: 'Lucida Console'; mso-font-kerning: 0pt; mso-no-proof: yes">NiftyContainer</span> <span style="font-size: 10pt; font-family: 宋体; mso-font-kerning: 0pt; mso-hansi-font-family: 'Lucida Console'; mso-ascii-font-family: 'Lucida Console'; mso-no-proof: yes">中的一个对象，你可能需要调用</span> <span lang="EN-US" style="font-size: 10pt; font-family: 'Lucida Console'; mso-font-kerning: 0pt; mso-no-proof: yes">T</span> <span style="font-size: 10pt; font-family: 宋体; mso-font-kerning: 0pt; mso-hansi-font-family: 'Lucida Console'; mso-ascii-font-family: 'Lucida Console'; mso-no-proof: yes">的拷贝构造函数（对于非多态类型）或者一个名为</span> <span lang="EN-US" style="font-size: 10pt; font-family: 'Lucida Console'; mso-font-kerning: 0pt; mso-no-proof: yes">Clone()</span> <span style="font-size: 10pt; font-family: 宋体; mso-font-kerning: 0pt; mso-hansi-font-family: 'Lucida Console'; mso-ascii-font-family: 'Lucida Console'; mso-no-proof: yes">的虚函数（对于多态类型）。你可以通过设置一个</span> <span lang="EN-US" style="font-size: 10pt; font-family: 'Lucida Console'; mso-font-kerning: 0pt; mso-no-proof: yes">bool</span> <span style="font-size: 10pt; font-family: 宋体; mso-font-kerning: 0pt; mso-hansi-font-family: 'Lucida Console'; mso-ascii-font-family: 'Lucida Console'; mso-no-proof: yes">类型的模版参数来从类的客户手里获得关于多态的信息。</span> <span lang="EN-US" style="font-size: 10pt; font-family: 'Lucida Console'; mso-font-kerning: 0pt; mso-no-proof: yes"><o:p></o:p></span></p> <p style="background: #d9d9d9; margin: 0cm 0cm 0pt; text-align: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="font-size: 10pt; background: #d9d9d9; color: blue; font-family: 'Lucida Console'; mso-font-kerning: 0pt; mso-no-proof: yes">template</span> <span lang="EN-US" style="font-size: 10pt; background: #d9d9d9; font-family: 'Lucida Console'; mso-font-kerning: 0pt; mso-no-proof: yes">&lt;<font face="Lucida Console"><span style="color: blue">class</span> T, <span style="color: blue">bool</span> isPolymorphic&gt; <span style="color: blue">class</span> NiftyContainer {</font></span> <span lang="EN-US" style="font-size: 10pt; font-family: 'Lucida Console'; mso-font-kerning: 0pt; mso-no-proof: yes"><o:p></o:p></span></p> <p style="background: #d9d9d9; margin: 0cm 0cm 0pt; text-align: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="font-size: 10pt; font-family: 'Lucida Console'; mso-font-kerning: 0pt; mso-no-proof: yes"><font face="Lucida Console"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp; </span><span style="color: green">// Other actions<o:p></o:p></span> </font></span></p> <p style="background: #d9d9d9; margin: 0cm 0cm 0pt; text-align: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="font-size: 10pt; font-family: 'Lucida Console'; mso-font-kerning: 0pt; mso-no-proof: yes"><font face="Lucida Console"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp; </span><span style="color: blue">void</span> DoSomething() {<o:p></o:p></font> </span></p> <p style="background: #d9d9d9; margin: 0cm 0cm 0pt; text-align: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="font-size: 10pt; font-family: 'Lucida Console'; mso-font-kerning: 0pt; mso-no-proof: yes"><font face="Lucida Console"><span style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>T* pSomeObj = ...;<o:p></o:p></font> </span></p> <p style="background: #d9d9d9; margin: 0cm 0cm 0pt; text-align: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="font-size: 10pt; font-family: 'Lucida Console'; mso-font-kerning: 0pt; mso-no-proof: yes"><font face="Lucida Console"><span style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: blue">if</span>(isPolymorphic) {<o:p></o:p></font> </span></p> <p style="background: #d9d9d9; margin: 0cm 0cm 0pt; text-align: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="font-size: 10pt; font-family: 'Lucida Console'; mso-font-kerning: 0pt; mso-no-proof: yes"><font face="Lucida Console"><span style="mso-tab-count: 3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>T* pNewObj = pSomeObj-&gt;Clone();<o:p></o:p></font> </span></p> <p style="background: #d9d9d9; margin: 0cm 0cm 0pt; text-align: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="font-size: 10pt; font-family: 'Lucida Console'; mso-font-kerning: 0pt; mso-no-proof: yes"><font face="Lucida Console"><span style="mso-tab-count: 3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: green">// Some polymorphic algorithm<o:p></o:p></span> </font></span></p> <p style="background: #d9d9d9; margin: 0cm 0cm 0pt; text-align: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="font-size: 10pt; font-family: 'Lucida Console'; mso-font-kerning: 0pt; mso-no-proof: yes"><font face="Lucida Console"><span style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}<o:p></o:p></font> </span></p> <p style="background: #d9d9d9; margin: 0cm 0cm 0pt; text-align: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="font-size: 10pt; font-family: 'Lucida Console'; mso-font-kerning: 0pt; mso-no-proof: yes"><font face="Lucida Console"><span style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: blue">else</span> {<o:p></o:p></font> </span></p> <p style="background: #d9d9d9; margin: 0cm 0cm 0pt; text-align: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="font-size: 10pt; font-family: 'Lucida Console'; mso-font-kerning: 0pt; mso-no-proof: yes"><font face="Lucida Console"><span style="mso-tab-count: 3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>T* pNewObj = <span style="color: blue">new</span> T(*pSomeObj);<o:p></o:p></font> </span></p> <p style="background: #d9d9d9; margin: 0cm 0cm 0pt; text-align: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="font-size: 10pt; font-family: 'Lucida Console'; mso-font-kerning: 0pt; mso-no-proof: yes"><font face="Lucida Console"><span style="mso-tab-count: 3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: green">// Some non-polymorphic algorithm<o:p></o:p></span> </font></span></p> <p style="background: #d9d9d9; margin: 0cm 0cm 0pt; text-align: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="font-size: 10pt; font-family: 'Lucida Console'; mso-font-kerning: 0pt; mso-no-proof: yes"><font face="Lucida Console"><span style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}<o:p></o:p></font> </span></p> <p style="background: #d9d9d9; margin: 0cm 0cm 0pt; text-align: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="font-size: 10pt; font-family: 'Lucida Console'; mso-font-kerning: 0pt; mso-no-proof: yes"><font face="Lucida Console"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp; </span>}<o:p></o:p></font> </span></p> <p style="background: #d9d9d9; margin: 0cm 0cm 0pt"><span lang="EN-US" style="font-size: 10pt; font-family: 'Lucida Console'; mso-font-kerning: 0pt; mso-no-proof: yes">};<o:p></o:p></span> </p> <p style="margin: 7.8pt 0cm; mso-para-margin-top: .5gd; mso-para-margin-right: 0cm; mso-para-margin-bottom: .5gd; mso-para-margin-left: 0cm"><span style="font-size: 10pt; font-family: 宋体; mso-font-kerning: 0pt; mso-hansi-font-family: 'Lucida Console'; mso-ascii-font-family: 'Lucida Console'; mso-no-proof: yes">问题在于编译器不会让你侥幸编译上面的代码。例如，如果一个多态类型没有定义</span> <span lang="EN-US" style="font-size: 10pt; font-family: 'Lucida Console'; mso-font-kerning: 0pt; mso-no-proof: yes">Clone()</span> <span style="font-size: 10pt; font-family: 宋体; mso-font-kerning: 0pt; mso-hansi-font-family: 'Lucida Console'; mso-ascii-font-family: 'Lucida Console'; mso-no-proof: yes">，那么</span> <span lang="EN-US" style="font-size: 10pt; font-family: 'Lucida Console'; mso-font-kerning: 0pt; mso-no-proof: yes">NiftyContainer::DoSomething</span> <span style="font-size: 10pt; font-family: 宋体; mso-font-kerning: 0pt; mso-hansi-font-family: 'Lucida Console'; mso-ascii-font-family: 'Lucida Console'; mso-no-proof: yes">绝对不会通过编译。尽管在编译时我们肯定可以对于分支进行判断，但这毕竟不是编译器的工作，他只会勤劳的为你编译出所有的代码。于是当你试图调用</span> <span lang="EN-US" style="font-size: 10pt; font-family: 'Lucida Console'; mso-font-kerning: 0pt; mso-no-proof: yes">NiftyContainer&lt;int, false&gt;::DoSomething</span> <span style="font-size: 10pt; font-family: 宋体; mso-font-kerning: 0pt; mso-hansi-font-family: 'Lucida Console'; mso-ascii-font-family: 'Lucida Console'; mso-no-proof: yes">的时候，编译器还是会停在</span> <span lang="EN-US" style="font-size: 10pt; font-family: 'Lucida Console'; mso-font-kerning: 0pt; mso-no-proof: yes">pObj-&gt;Clone()</span> <span style="font-size: 10pt; font-family: 宋体; mso-font-kerning: 0pt; mso-hansi-font-family: 'Lucida Console'; mso-ascii-font-family: 'Lucida Console'; mso-no-proof: yes">上，并且抱怨说：“你在做什么？”</span> <span lang="EN-US" style="font-size: 10pt; font-family: 'Lucida Console'; mso-font-kerning: 0pt; mso-no-proof: yes"><o:p></o:p></span></p> <p style="margin: 7.8pt 0cm; mso-para-margin-top: .5gd; mso-para-margin-right: 0cm; mso-para-margin-bottom: .5gd; mso-para-margin-left: 0cm"><span style="font-size: 10pt; font-family: 宋体; mso-font-kerning: 0pt; mso-hansi-font-family: 'Lucida Console'; mso-ascii-font-family: 'Lucida Console'; mso-no-proof: yes">对于非多态类型分支，也有可能发生编译错误。如果</span> <span lang="EN-US" style="font-size: 10pt; font-family: 'Lucida Console'; mso-font-kerning: 0pt; mso-no-proof: yes">T</span> <span style="font-size: 10pt; font-family: 宋体; mso-font-kerning: 0pt; mso-hansi-font-family: 'Lucida Console'; mso-ascii-font-family: 'Lucida Console'; mso-no-proof: yes">是一个多态类型，并且把它的拷贝构造函数设定为</span> <span lang="EN-US" style="font-size: 10pt; font-family: 'Lucida Console'; mso-font-kerning: 0pt; mso-no-proof: yes">private</span> <span style="font-size: 10pt; font-family: 宋体; mso-font-kerning: 0pt; mso-hansi-font-family: 'Lucida Console'; mso-ascii-font-family: 'Lucida Console'; mso-no-proof: yes">的时候（这时一个多态类的良好行为），非多态分支的</span> <span lang="EN-US" style="font-size: 10pt; font-family: 'Lucida Console'; mso-font-kerning: 0pt; mso-no-proof: yes">new T(*pObj)</span> <span style="font-size: 10pt; font-family: 宋体; mso-font-kerning: 0pt; mso-hansi-font-family: 'Lucida Console'; mso-ascii-font-family: 'Lucida Console'; mso-no-proof: yes">就会发生错误。</span> <span lang="EN-US" style="font-size: 10pt; font-family: 'Lucida Console'; mso-font-kerning: 0pt; mso-no-proof: yes"><o:p></o:p></span></p> <p style="margin: 7.8pt 0cm; mso-para-margin-top: .5gd; mso-para-margin-right: 0cm; mso-para-margin-bottom: .5gd; mso-para-margin-left: 0cm"><span style="font-size: 10pt; font-family: 宋体; mso-font-kerning: 0pt; mso-hansi-font-family: 'Lucida Console'; mso-ascii-font-family: 'Lucida Console'; mso-no-proof: yes">你可能会想，如果编译器可以不去理会那些不必要的分支就好了，但是看来不太可能。那么，如何是好呢？</span> <span lang="EN-US" style="font-size: 10pt; font-family: 'Lucida Console'; mso-font-kerning: 0pt; mso-no-proof: yes"><o:p></o:p></span></p> <p style="margin: 7.8pt 0cm; mso-para-margin-top: .5gd; mso-para-margin-right: 0cm; mso-para-margin-bottom: .5gd; mso-para-margin-left: 0cm"><span style="font-size: 10pt; font-family: 宋体; mso-font-kerning: 0pt; mso-hansi-font-family: 'Lucida Console'; mso-ascii-font-family: 'Lucida Console'; mso-no-proof: yes">其实，方法有很多，</span> <span lang="EN-US" style="font-size: 10pt; font-family: 'Lucida Console'; mso-font-kerning: 0pt; mso-no-proof: yes">Int2Type</span> <span style="font-size: 10pt; font-family: 宋体; mso-font-kerning: 0pt; mso-hansi-font-family: 'Lucida Console'; mso-ascii-font-family: 'Lucida Console'; mso-no-proof: yes">提供了一个简洁的办法。它可以根据</span> <span lang="EN-US" style="font-size: 10pt; font-family: 'Lucida Console'; mso-font-kerning: 0pt; mso-no-proof: yes">true</span> <span style="font-size: 10pt; font-family: 宋体; mso-font-kerning: 0pt; mso-hansi-font-family: 'Lucida Console'; mso-ascii-font-family: 'Lucida Console'; mso-no-proof: yes">和</span> <span lang="EN-US" style="font-size: 10pt; font-family: 'Lucida Console'; mso-font-kerning: 0pt; mso-no-proof: yes">false</span> <span style="font-size: 10pt; font-family: 宋体; mso-font-kerning: 0pt; mso-hansi-font-family: 'Lucida Console'; mso-ascii-font-family: 'Lucida Console'; mso-no-proof: yes">来生成两个不同的类型，而后根据</span> <span lang="EN-US" style="font-size: 10pt; font-family: 'Lucida Console'; mso-font-kerning: 0pt; mso-no-proof: yes">Int2Type&lt;isPolymorphic&gt;</span> <span style="font-size: 10pt; font-family: 宋体; mso-font-kerning: 0pt; mso-hansi-font-family: 'Lucida Console'; mso-ascii-font-family: 'Lucida Console'; mso-no-proof: yes">评估正确的调用。</span> <span lang="EN-US" style="font-size: 10pt; font-family: 'Lucida Console'; mso-font-kerning: 0pt; mso-no-proof: yes"><o:p></o:p></span></p> <p style="background: #d9d9d9; margin: 0cm 0cm 0pt; text-align: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="font-size: 10pt; color: blue; font-family: 'Lucida Console'; mso-font-kerning: 0pt; mso-no-proof: yes">template</span> <span lang="EN-US" style="font-size: 10pt; font-family: 'Lucida Console'; mso-font-kerning: 0pt; mso-no-proof: yes">&lt;<font face="Lucida Console"><span style="color: blue">class</span> T, <span style="color: blue">bool</span> isPolymorphic&gt; <span style="color: blue">class</span> NiftyContainer {<o:p></o:p></font></span> </p> <p style="background: #d9d9d9; margin: 0cm 0cm 0pt; text-align: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="font-size: 10pt; color: blue; font-family: 'Lucida Console'; mso-font-kerning: 0pt; mso-no-proof: yes">private</span> <span lang="EN-US" style="font-size: 10pt; font-family: 'Lucida Console'; mso-font-kerning: 0pt; mso-no-proof: yes">:<o:p></o:p></span> </p> <p style="background: #d9d9d9; margin: 0cm 0cm 0pt; text-align: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="font-size: 10pt; font-family: 'Lucida Console'; mso-font-kerning: 0pt; mso-no-proof: yes"><font face="Lucida Console"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp; </span><span style="color: green">// Other actions<o:p></o:p></span> </font></span></p> <p style="background: #d9d9d9; margin: 0cm 0cm 0pt; text-align: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="font-size: 10pt; font-family: 'Lucida Console'; mso-font-kerning: 0pt; mso-no-proof: yes"><font face="Lucida Console"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp; </span><span style="color: blue">void</span> DoSomething(T* pObj, Int2Type&lt;<span style="color: blue">true</span>&gt;) {<o:p></o:p></font> </span></p> <p style="background: #d9d9d9; margin: 0cm 0cm 0pt; text-align: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="font-size: 10pt; font-family: 'Lucida Console'; mso-font-kerning: 0pt; mso-no-proof: yes"><font face="Lucida Console"><span style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>T* pNewObj = pSomeObj-&gt;Clone();<o:p></o:p></font> </span></p> <p style="background: #d9d9d9; margin: 0cm 0cm 0pt; text-align: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="font-size: 10pt; font-family: 'Lucida Console'; mso-font-kerning: 0pt; mso-no-proof: yes"><font face="Lucida Console"><span style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: green">// Some polymorphic algorithm<o:p></o:p></span> </font></span></p> <p style="background: #d9d9d9; margin: 0cm 0cm 0pt; text-align: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="font-size: 10pt; font-family: 'Lucida Console'; mso-font-kerning: 0pt; mso-no-proof: yes"><font face="Lucida Console"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp; </span>}<o:p></o:p></font> </span></p> <p style="background: #d9d9d9; margin: 0cm 0cm 0pt; text-align: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="font-size: 10pt; font-family: 'Lucida Console'; mso-font-kerning: 0pt; mso-no-proof: yes"><font face="Lucida Console"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp; </span><span style="color: blue">void</span> DoSomething(T* pObj, Int2Type&lt;<span style="color: blue">false</span>&gt;) {<o:p></o:p></font> </span></p> <p style="background: #d9d9d9; margin: 0cm 0cm 0pt; text-align: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="font-size: 10pt; font-family: 'Lucida Console'; mso-font-kerning: 0pt; mso-no-proof: yes"><font face="Lucida Console"><span style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>T* pNewObj = <span style="color: blue">new</span> T(*pSomeObj);<o:p></o:p></font> </span></p> <p style="background: #d9d9d9; margin: 0cm 0cm 0pt; text-align: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="font-size: 10pt; font-family: 'Lucida Console'; mso-font-kerning: 0pt; mso-no-proof: yes"><font face="Lucida Console"><span style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: green">// Some non-polymorphic algorithm<o:p></o:p></span> </font></span></p> <p style="background: #d9d9d9; margin: 0cm 0cm 0pt; text-align: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="font-size: 10pt; font-family: 'Lucida Console'; mso-font-kerning: 0pt; mso-no-proof: yes"><font face="Lucida Console"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp; </span>}<o:p></o:p></font> </span></p> <p style="background: #d9d9d9; margin: 0cm 0cm 0pt; text-align: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="font-size: 10pt; color: blue; font-family: 'Lucida Console'; mso-font-kerning: 0pt; mso-no-proof: yes">public</span> <span lang="EN-US" style="font-size: 10pt; font-family: 'Lucida Console'; mso-font-kerning: 0pt; mso-no-proof: yes">:<o:p></o:p></span> </p> <p style="background: #d9d9d9; margin: 0cm 0cm 0pt; text-align: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="font-size: 10pt; font-family: 'Lucida Console'; mso-font-kerning: 0pt; mso-no-proof: yes"><font face="Lucida Console"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp; </span><span style="color: blue">void</span> DoSomething(T* pObj) {<o:p></o:p></font> </span></p> <p style="background: #d9d9d9; margin: 0cm 0cm 0pt; text-align: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="font-size: 10pt; font-family: 'Lucida Console'; mso-font-kerning: 0pt; mso-no-proof: yes"><font face="Lucida Console"><span style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>DoSomething(pObj, Int2Type&lt;isPolymorphic&gt;());<o:p></o:p></font> </span></p> <p style="background: #d9d9d9; margin: 0cm 0cm 0pt; text-align: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="font-size: 10pt; font-family: 'Lucida Console'; mso-font-kerning: 0pt; mso-no-proof: yes"><font face="Lucida Console"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp; </span>}<o:p></o:p></font> </span></p> <p style="background: #d9d9d9; margin: 0cm 0cm 0pt"><span lang="EN-US" style="font-size: 10pt; font-family: 'Lucida Console'; mso-font-kerning: 0pt; mso-no-proof: yes">};<o:p></o:p></span> </p> <p style="margin: 7.8pt 0cm; mso-para-margin-top: .5gd; mso-para-margin-right: 0cm; mso-para-margin-bottom: .5gd; mso-para-margin-left: 0cm"><span style="font-size: 10pt; font-family: 宋体; mso-font-kerning: 0pt; mso-hansi-font-family: 'Lucida Console'; mso-ascii-font-family: 'Lucida Console'; mso-no-proof: yes">当你想把常整数用作一个类型的时候，</span> <span lang="EN-US" style="font-size: 10pt; font-family: 'Lucida Console'; mso-font-kerning: 0pt; mso-no-proof: yes">Int2Type</span> <span style="font-size: 10pt; font-family: 宋体; mso-font-kerning: 0pt; mso-hansi-font-family: 'Lucida Console'; mso-ascii-font-family: 'Lucida Console'; mso-no-proof: yes">是非常方便的。你可以传递一个临时的变量来重载函数。而之所以我们可以这样做，是因为编译器不会去编译没有用到的模板函数。</span> <span lang="EN-US" style="font-size: 10pt; font-family: 'Lucida Console'; mso-font-kerning: 0pt; mso-no-proof: yes"><o:p></o:p></span></p></div></div></div></div> <div id="main"> <div id="AjaxHolder_UpdatePanel1"> <h3>Feedback</h3> <div class="post"> <div class="posthead"> <h2><a title="permalink: re: C++的静态分派技术" href="http://www.cppblog.com/nacci/archive/2005/11/11/1058.html#1132">#</a>&nbsp;<a name="1132"></a>re: C++的静态分派技术&nbsp; <a href="http://www.cppblog.com/nacci/archive/2005/11/11/1058.html#post">回复</a>&nbsp; <a title="查看该作者发表过的评论" href="http://www.cppblog.com/comment?author=christanxw" target="_blank">更多评论</a> <a id="AjaxHolder_Comments_CommentList_ctl00_DeleteLink" href="http://www.cppblog.com/"></a>&nbsp; <a id="AjaxHolder_Comments_CommentList_ctl00_EditLink"></a> </h2>2005-11-15 16:36 by <a id="AjaxHolder_Comments_CommentList_ctl00_NameLink" href="http://www.cppblog.com/christanxw/" target="_blank">christanxw</a> </div> <div class="postbody">这在STL中有着广泛的应用</div></div></div></div><img src ="http://www.cppblog.com/woaidongmao/aggbug/61861.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/woaidongmao/" target="_blank">肥仔</a> 2008-09-15 13:42 <a href="http://www.cppblog.com/woaidongmao/archive/2008/09/15/61861.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>浅析C++ Compile-time Assertion技术</title><link>http://www.cppblog.com/woaidongmao/archive/2008/09/15/61860.html</link><dc:creator>肥仔</dc:creator><author>肥仔</author><pubDate>Mon, 15 Sep 2008 05:39:00 GMT</pubDate><guid>http://www.cppblog.com/woaidongmao/archive/2008/09/15/61860.html</guid><wfw:comment>http://www.cppblog.com/woaidongmao/comments/61860.html</wfw:comment><comments>http://www.cppblog.com/woaidongmao/archive/2008/09/15/61860.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/woaidongmao/comments/commentRss/61860.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/woaidongmao/services/trackbacks/61860.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 你可能经常需要利用运行时断言技术，它可以方便地测试前提条件。但是，随着Metaprogramming概念的出现，编译时断言技术也已经和runtime assertion一样的普遍了。如何在编译时进行断言呢？其实，方法只有一个，就是让编译器生成一条错误信息，但是编译器生成的错误信息信息性往往有又理想。并且，即使你在一种编译上设计了一种方案，你也很难把它移植到其他的编译器上。我们通过其实现方法的改进和...&nbsp;&nbsp;<a href='http://www.cppblog.com/woaidongmao/archive/2008/09/15/61860.html'>阅读全文</a><img src ="http://www.cppblog.com/woaidongmao/aggbug/61860.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/woaidongmao/" target="_blank">肥仔</a> 2008-09-15 13:39 <a href="http://www.cppblog.com/woaidongmao/archive/2008/09/15/61860.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++ 模板类型萃取技术</title><link>http://www.cppblog.com/woaidongmao/archive/2008/09/15/61855.html</link><dc:creator>肥仔</dc:creator><author>肥仔</author><pubDate>Mon, 15 Sep 2008 05:31:00 GMT</pubDate><guid>http://www.cppblog.com/woaidongmao/archive/2008/09/15/61855.html</guid><wfw:comment>http://www.cppblog.com/woaidongmao/comments/61855.html</wfw:comment><comments>http://www.cppblog.com/woaidongmao/archive/2008/09/15/61855.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/woaidongmao/comments/commentRss/61855.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/woaidongmao/services/trackbacks/61855.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 自从C++中引入了template后，以泛型技术为中心的设计得到了长足的进步。STL就是这个阶段杰出的产物。STL的目标就是要把数据和算法分开，分别对其进行设计，之后通过一种名为iterator的东西，把这二者再粘接到一起。设计模式中，关于iterator的描述为：一种能够顺序访问容器中每个元素的方法，使用该方法不能暴露容器内部的表达方式。可以说，类型萃取技术就是为了要解决和iterator有关的...&nbsp;&nbsp;<a href='http://www.cppblog.com/woaidongmao/archive/2008/09/15/61855.html'>阅读全文</a><img src ="http://www.cppblog.com/woaidongmao/aggbug/61855.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/woaidongmao/" target="_blank">肥仔</a> 2008-09-15 13:31 <a href="http://www.cppblog.com/woaidongmao/archive/2008/09/15/61855.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>测试一下 Intel C++8.0 对模板的支持程度</title><link>http://www.cppblog.com/woaidongmao/archive/2008/09/15/61851.html</link><dc:creator>肥仔</dc:creator><author>肥仔</author><pubDate>Mon, 15 Sep 2008 05:07:00 GMT</pubDate><guid>http://www.cppblog.com/woaidongmao/archive/2008/09/15/61851.html</guid><wfw:comment>http://www.cppblog.com/woaidongmao/comments/61851.html</wfw:comment><comments>http://www.cppblog.com/woaidongmao/archive/2008/09/15/61851.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/woaidongmao/comments/commentRss/61851.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/woaidongmao/services/trackbacks/61851.html</trackback:ping><description><![CDATA[<p class="MsoNormal" style="background: white; word-break: break-all; line-height: 160%; text-align: left; mso-pagination: widow-orphan" align="left"><span style="color: #4b4b4b; line-height: 160%; font-family: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">有关模板的语法很多很杂，无法一一列举，在此仅测试几个简单常用的语法。<span lang="EN-US"> <br></span>以下有关模板的语法分别使用<span lang="EN-US"> Dev-CPP4991</span>、<span lang="EN-US">VC++6.0 </span>和<span lang="EN-US"> Intel C++8.0 </span>进行测试，<span lang="EN-US">DEVCPP</span>和<span lang="EN-US">ICC</span>都能完全通过测试，<span lang="EN-US">VC++6</span>有部分通不过测试。<span lang="EN-US"> <br><br>1. </span>模板类静态成员<span lang="EN-US"> <br>template &lt;typename T&gt; struct testClass { <br>&nbsp;&nbsp;&nbsp; static int _data; <br>}; <br>template&lt;&gt; int testClass&lt;char&gt;::_data = 1; <br>template&lt;&gt; int testClass&lt;long&gt;::_data = 2; <br>int main( void ) { <br>&nbsp;&nbsp;&nbsp; cout &lt;&lt; boolalpha &lt;&lt; (1==testClass&lt;char&gt;::_data) &lt;&lt; endl; <br>&nbsp;&nbsp;&nbsp; cout &lt;&lt; boolalpha &lt;&lt; (2==testClass&lt;long&gt;::_data) &lt;&lt; endl; <br>} <br><br>2. </span>模板类偏特化<span lang="EN-US"> <br>template &lt;class I, class O&gt; struct testClass { <br>&nbsp;&nbsp;&nbsp; testClass() { cout &lt;&lt; "I, O" &lt;&lt; endl; } <br>}; <br>template &lt;class T&gt; struct testClass&lt;T*, T*&gt; { <br>&nbsp;&nbsp;&nbsp; testClass() { cout &lt;&lt; "T*, T*" &lt;&lt; endl; } <br>}; <br>template &lt;class T&gt; struct testClass&lt;const T*, T*&gt; { <br>&nbsp;&nbsp;&nbsp; testClass() { cout &lt;&lt; "const T*, T*" &lt;&lt; endl; } <br>}; <br>int main( void ) { <br>&nbsp;&nbsp;&nbsp; testClass&lt;int, char&gt; obj1; <br>&nbsp;&nbsp;&nbsp; testClass&lt;int*, int*&gt; obj2; <br>&nbsp;&nbsp;&nbsp; testClass&lt;const int*, int*&gt; obj3; <br>} <br>[</span>注<span lang="EN-US">]: </span></span><span lang="EN-US" style="color: red; line-height: 160%; font-family: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">VC++6 </span><span style="color: red; line-height: 160%; font-family: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">编译不通过</span><span lang="EN-US" style="color: #4b4b4b; line-height: 160%; font-family: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"> <br><br>3. function template partial order <br>template &lt;class T&gt; struct testClass { <br>&nbsp;&nbsp;&nbsp; void swap( testClass&lt;T&gt;&amp; ) { cout &lt;&lt; "swap()" &lt;&lt; endl; } <br>}; <br>template &lt;class T&gt; inline void swap( testClass&lt;T&gt;&amp; x, testClass&lt;T&gt;&amp; y ) { <br>&nbsp;&nbsp;&nbsp; x.swap( y ); <br>} <br>int main( void ) { <br>&nbsp;&nbsp;&nbsp; testClass&lt;int&gt; obj1; <br>&nbsp;&nbsp;&nbsp; testClass&lt;int&gt; obj2; <br>&nbsp;&nbsp;&nbsp; swap( obj1, obj2 ); <br>} <br>[</span><span style="color: #4b4b4b; line-height: 160%; font-family: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">注<span lang="EN-US">]: </span></span><span lang="EN-US" style="color: red; line-height: 160%; font-family: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">VC++6 </span><span style="color: red; line-height: 160%; font-family: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">编译不通过</span><span style="color: #4b4b4b; line-height: 160%; font-family: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"> <span lang="EN-US"><br><br>4. </span>类成员函数模板<span lang="EN-US"> <br>struct testClass { <br>&nbsp;&nbsp;&nbsp; template &lt;class T&gt; void mfun( const T&amp; t ) { <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cout &lt;&lt; t &lt;&lt; endl; <br>&nbsp;&nbsp;&nbsp; } <br>&nbsp;&nbsp;&nbsp; template &lt;class T&gt; operator T() { <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return T(); <br>&nbsp;&nbsp;&nbsp; } <br>}; <br>int main( void ) { <br>&nbsp;&nbsp;&nbsp; testClass obj; <br>&nbsp;&nbsp;&nbsp; obj.mfun( 1 ); <br>&nbsp;&nbsp;&nbsp; int i = obj; <br>&nbsp;&nbsp;&nbsp; cout &lt;&lt; i &lt;&lt; endl; <br>} <br>[</span>注<span lang="EN-US">]: </span></span><span style="color: red; line-height: 160%; font-family: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">对于第二个成员函数模板，<span lang="EN-US">VC++6 </span>运行异常</span><span lang="EN-US" style="color: #4b4b4b; line-height: 160%; font-family: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"> <br><br>5. </span><span style="color: #4b4b4b; line-height: 160%; font-family: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">缺省模板参数推导<span lang="EN-US"> <br>template &lt;class T&gt; struct test { <br>&nbsp;&nbsp;&nbsp; T a; <br>}; <br>template &lt;class I, class O=test&lt;I&gt; &gt; struct testClass { <br>&nbsp;&nbsp;&nbsp; I b; <br>&nbsp;&nbsp;&nbsp; O c; <br>}; <br><br>6. </span>非类型模板参数<span lang="EN-US"> <br>template &lt;class T, int n&gt; struct testClass { <br>&nbsp;&nbsp;&nbsp; T _t; <br>&nbsp;&nbsp;&nbsp; testClass() : _t(n) { <br>&nbsp;&nbsp;&nbsp; } <br>}; <br>int main( void ) { <br>&nbsp;&nbsp;&nbsp; testClass&lt;int,1&gt; obj1; <br>&nbsp;&nbsp;&nbsp; testClass&lt;int,2&gt; obj2; <br>} <br><br>7. </span>空模板参数<span lang="EN-US"> <br>template &lt;class T&gt; struct testClass; <br>template &lt;class T&gt; bool operator==( const testClass&lt;T&gt;&amp;, const testClass&lt;T&gt;&amp; ) { <br>&nbsp;&nbsp;&nbsp; return false; <br>}; <br>template &lt;class T&gt; struct testClass { <br>&nbsp;&nbsp;&nbsp; friend bool operator== &lt;&gt;( const testClass&amp;, const testClass&amp; ); <br>}; <br>[</span>注<span lang="EN-US">]: </span></span><span lang="EN-US" style="color: red; line-height: 160%; font-family: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">VC++6 </span><span style="color: red; line-height: 160%; font-family: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">编译不通过</span><span lang="EN-US" style="color: #4b4b4b; line-height: 160%; font-family: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"> <br><br>8. </span><span style="color: #4b4b4b; line-height: 160%; font-family: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">模板特化<span lang="EN-US"> <br>template &lt;class T&gt; struct testClass { <br>}; <br>template &lt;&gt; struct testClass&lt;int&gt; { <br>}; <br><br>9. <br>template &lt;template &lt;class T&gt; class X&gt; <br>&nbsp;&nbsp;&nbsp; struct Widget{ <br>}; <br>[</span>注<span lang="EN-US">]: </span></span><span lang="EN-US" style="color: red; line-height: 160%; font-family: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">VC++6 </span><span style="color: red; line-height: 160%; font-family: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">编译不通过</span><span lang="EN-US" style="color: #4b4b4b; line-height: 160%; font-family: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"> <br><br>10. [hpho]</span><span style="color: #4b4b4b; line-height: 160%; font-family: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">提供的一个事例<span lang="EN-US"> <br>struct Widget1 { <br>template&lt;typename T&gt; <br>&nbsp;&nbsp;&nbsp; T foo(){} <br>}; <br>template&lt;template&lt;class T&gt;class X&gt; <br>&nbsp;&nbsp;&nbsp; struct Widget2{ <br>}; <br>[</span>注<span lang="EN-US">]: </span></span><span lang="EN-US" style="color: red; line-height: 160%; font-family: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">VC++6 </span><span style="color: red; line-height: 160%; font-family: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">编译不通过</span><span style="color: #4b4b4b; line-height: 160%; font-family: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"> <span lang="EN-US"><?xml:namespace prefix = o /><o:p></o:p></span></span></p> <p class="MsoNormal"><span lang="EN-US" style="font-family: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: arial"><o:p>&nbsp;</o:p></span></p><img src ="http://www.cppblog.com/woaidongmao/aggbug/61851.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/woaidongmao/" target="_blank">肥仔</a> 2008-09-15 13:07 <a href="http://www.cppblog.com/woaidongmao/archive/2008/09/15/61851.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>模版套模版</title><link>http://www.cppblog.com/woaidongmao/archive/2008/09/14/61803.html</link><dc:creator>肥仔</dc:creator><author>肥仔</author><pubDate>Sun, 14 Sep 2008 10:13:00 GMT</pubDate><guid>http://www.cppblog.com/woaidongmao/archive/2008/09/14/61803.html</guid><wfw:comment>http://www.cppblog.com/woaidongmao/comments/61803.html</wfw:comment><comments>http://www.cppblog.com/woaidongmao/archive/2008/09/14/61803.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/woaidongmao/comments/commentRss/61803.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/woaidongmao/services/trackbacks/61803.html</trackback:ping><description><![CDATA[<div class="post"> <div class="postText">1 模版类中有成员是模版：<br> <div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"><span style="color: #000000">#include </span><span style="color: #000000">&lt;</span><span style="color: #000000">iostream</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top">#include </span><span style="color: #000000">&lt;</span><span style="color: #000000">typeinfo</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"></span><span style="color: #0000ff">using</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">namespace</span><span style="color: #000000"> std;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top">template</span><span style="color: #000000">&lt;</span><span style="color: #0000ff">class</span><span style="color: #000000"> T</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"></span><span style="color: #0000ff">class</span><span style="color: #000000"> Outer <br><img id="Codehighlighter1_93_171_Open_Image" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top"><img id="Codehighlighter1_93_171_Closed_Image" style="display: none" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align="top"></span><span id="Codehighlighter1_93_171_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id="Codehighlighter1_93_171_Open_Text"><span style="color: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top"></span><span style="color: #0000ff">public</span><span style="color: #000000">:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp; template</span><span style="color: #000000">&lt;</span><span style="color: #0000ff">class</span><span style="color: #000000"> R</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp; </span><span style="color: #0000ff">class</span><span style="color: #000000"> Inner <br><img id="Codehighlighter1_140_168_Open_Image" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"><img id="Codehighlighter1_140_168_Closed_Image" style="display: none" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align="top">&nbsp; </span><span id="Codehighlighter1_140_168_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id="Codehighlighter1_140_168_Open_Text"><span style="color: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp; </span><span style="color: #0000ff">public</span><span style="color: #000000">:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff">void</span><span style="color: #000000"> f();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top">&nbsp; }</span></span><span style="color: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top">}</span></span><span style="color: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top">template</span><span style="color: #000000">&lt;</span><span style="color: #0000ff">class</span><span style="color: #000000"> T</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top">template </span><span style="color: #000000">&lt;</span><span style="color: #0000ff">class</span><span style="color: #000000"> R</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"></span><span style="color: #0000ff">void</span><span style="color: #000000"> Outer</span><span style="color: #000000">&lt;</span><span style="color: #000000">T</span><span style="color: #000000">&gt;</span><span style="color: #000000">::Inner</span><span style="color: #000000">&lt;</span><span style="color: #000000">R</span><span style="color: #000000">&gt;</span><span style="color: #000000">::f()<br><img id="Codehighlighter1_242_406_Open_Image" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top"><img id="Codehighlighter1_242_406_Closed_Image" style="display: none" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align="top"></span><span id="Codehighlighter1_242_406_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id="Codehighlighter1_242_406_Open_Text"><span style="color: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp; cout </span><span style="color: #000000">&lt;&lt;</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">Outer == </span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">&lt;&lt;</span><span style="color: #000000"> typeid(T).name() </span><span style="color: #000000">&lt;&lt;</span><span style="color: #000000"> endl;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp; cout </span><span style="color: #000000">&lt;&lt;</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">Inner == </span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">&lt;&lt;</span><span style="color: #000000"> typeid(R).name() </span><span style="color: #000000">&lt;&lt;</span><span style="color: #000000"> endl;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp; cout </span><span style="color: #000000">&lt;&lt;</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">Full Inner == </span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">&lt;&lt;</span><span style="color: #000000"> typeid(</span><span style="color: #000000">*</span><span style="color: #0000ff">this</span><span style="color: #000000">).name() </span><span style="color: #000000">&lt;&lt;</span><span style="color: #000000"> endl;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top">}</span></span><span style="color: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"></span><span style="color: #0000ff">int</span><span style="color: #000000"> main() <br><img id="Codehighlighter1_421_469_Open_Image" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top"><img id="Codehighlighter1_421_469_Closed_Image" style="display: none" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align="top"></span><span id="Codehighlighter1_421_469_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id="Codehighlighter1_421_469_Open_Text"><span style="color: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp; Outer</span><span style="color: #000000">&lt;</span><span style="color: #0000ff">int</span><span style="color: #000000">&gt;</span><span style="color: #000000">::Inner</span><span style="color: #000000">&lt;</span><span style="color: #0000ff">bool</span><span style="color: #000000">&gt;</span><span style="color: #000000"> inner;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp; inner.f();<br><img id="Codehighlighter1_471_476_Open_Image" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top"><img id="Codehighlighter1_471_476_Closed_Image" style="display: none" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align="top">}</span></span><span style="color: #000000">&nbsp;</span><span id="Codehighlighter1_471_476_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff">/**/</span><span id="Codehighlighter1_471_476_Open_Text"><span style="color: #808080">///</span><span style="color: #008000">:~</span><span style="color: #808080"></span></span><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"><span style="color: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"></span><span style="color: #008000">//</span><span style="color: #008000">output:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"></span><span style="color: #008000">//</span><span style="color: #008000">Outer == int<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"></span><span style="color: #008000">//</span><span style="color: #008000">Inner == bool<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"></span><span style="color: #008000">//</span><span style="color: #008000">Full Inner == class Outer&lt;int&gt;::Inner&lt;bool&gt;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"></span><span style="color: #008000">//</span><span style="color: #008000">Press any key to continue . . .</span></div><br>2 模版类的参数是模版：<br> <div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"><span style="color: #008000">//</span><span style="color: #008000"> A print function for standard C++ sequences</span><span style="color: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"></span><span style="color: #000000">#include </span><span style="color: #000000">&lt;</span><span style="color: #000000">iostream</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top">#include </span><span style="color: #000000">&lt;</span><span style="color: #000000">list</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top">#include </span><span style="color: #000000">&lt;</span><span style="color: #000000">memory</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top">#include </span><span style="color: #000000">&lt;</span><span style="color: #000000">vector</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top">#include </span><span style="color: #000000">&lt;</span><span style="color: #000000">deque</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"></span><span style="color: #0000ff">using</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">namespace</span><span style="color: #000000"> std;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top">template</span><span style="color: #000000">&lt;</span><span style="color: #0000ff">class</span><span style="color: #000000"> T, template</span><span style="color: #000000">&lt;</span><span style="color: #0000ff">class</span><span style="color: #000000"> U, </span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000"> allocator</span><span style="color: #000000">&lt;</span><span style="color: #000000">U</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff">class</span><span style="color: #000000"> Seq</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"></span><span style="color: #0000ff">void</span><span style="color: #000000"> printSeq(Seq</span><span style="color: #000000">&lt;</span><span style="color: #000000">T</span><span style="color: #000000">&gt;&amp;</span><span style="color: #000000"> seq) <br><img id="Codehighlighter1_274_376_Open_Image" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top"><img id="Codehighlighter1_274_376_Closed_Image" style="display: none" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align="top"></span><span id="Codehighlighter1_274_376_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id="Codehighlighter1_274_376_Open_Text"><span style="color: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp; </span><span style="color: #0000ff">for</span><span style="color: #000000"> (typename Seq</span><span style="color: #000000">&lt;</span><span style="color: #000000">T</span><span style="color: #000000">&gt;</span><span style="color: #000000">::iterator b </span><span style="color: #000000">=</span><span style="color: #000000"> seq.begin();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; b </span><span style="color: #000000">!=</span><span style="color: #000000"> seq.end();)<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp; cout </span><span style="color: #000000">&lt;&lt;</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">*</span><span style="color: #000000">b</span><span style="color: #000000">++</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">&lt;&lt;</span><span style="color: #000000"> endl;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top">}</span></span><span style="color: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"></span><span style="color: #0000ff">int</span><span style="color: #000000"> main() <br><img id="Codehighlighter1_391_666_Open_Image" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top"><img id="Codehighlighter1_391_666_Closed_Image" style="display: none" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align="top"></span><span id="Codehighlighter1_391_666_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id="Codehighlighter1_391_666_Open_Text"><span style="color: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp; </span><span style="color: #008000">//</span><span style="color: #008000"> Process a vector</span><span style="color: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top"></span><span style="color: #000000">&nbsp; vector</span><span style="color: #000000">&lt;</span><span style="color: #0000ff">int</span><span style="color: #000000">&gt;</span><span style="color: #000000"> v;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp; v.push_back(</span><span style="color: #000000">1</span><span style="color: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp; v.push_back(</span><span style="color: #000000">2</span><span style="color: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp; printSeq(v);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp; </span><span style="color: #008000">//</span><span style="color: #008000"> Process a list</span><span style="color: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top"></span><span style="color: #000000">&nbsp; list</span><span style="color: #000000">&lt;</span><span style="color: #0000ff">int</span><span style="color: #000000">&gt;</span><span style="color: #000000"> lst;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp; lst.push_back(</span><span style="color: #000000">3</span><span style="color: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp; lst.push_back(</span><span style="color: #000000">4</span><span style="color: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp; printSeq(lst);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp; </span><span style="color: #008000">//</span><span style="color: #008000"> Process a deque</span><span style="color: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top"></span><span style="color: #000000">&nbsp; deque</span><span style="color: #000000">&lt;</span><span style="color: #0000ff">int</span><span style="color: #000000">&gt;</span><span style="color: #000000"> d;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp; d.push_back(</span><span style="color: #000000">5</span><span style="color: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp; d.push_back(</span><span style="color: #000000">6</span><span style="color: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp; printSeq(d);<br><img id="Codehighlighter1_668_673_Open_Image" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top"><img id="Codehighlighter1_668_673_Closed_Image" style="display: none" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align="top">}</span></span><span style="color: #000000">&nbsp;</span><span id="Codehighlighter1_668_673_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff">/**/</span><span id="Codehighlighter1_668_673_Open_Text"><span style="color: #808080">///</span><span style="color: #008000">:~</span></span></div><br>注意：typename 通知编译器被限定的标识符应该为类型，不同与typedef 是定义新的类型。<br></div></div><img src ="http://www.cppblog.com/woaidongmao/aggbug/61803.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/woaidongmao/" target="_blank">肥仔</a> 2008-09-14 18:13 <a href="http://www.cppblog.com/woaidongmao/archive/2008/09/14/61803.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>模版元编程</title><link>http://www.cppblog.com/woaidongmao/archive/2008/09/14/61802.html</link><dc:creator>肥仔</dc:creator><author>肥仔</author><pubDate>Sun, 14 Sep 2008 10:11:00 GMT</pubDate><guid>http://www.cppblog.com/woaidongmao/archive/2008/09/14/61802.html</guid><wfw:comment>http://www.cppblog.com/woaidongmao/comments/61802.html</wfw:comment><comments>http://www.cppblog.com/woaidongmao/archive/2008/09/14/61802.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/woaidongmao/comments/commentRss/61802.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/woaidongmao/services/trackbacks/61802.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: I.背景C++在很多人的心目中，一直是一种OO语言，而事实上，现在对C++的非OO部分的各种使用被逐渐地挖掘出来，其中最大的部分莫过于是 template。STL、loki、boost，，很多先行者为我们提供了方案，有的已经被列入C++标准的一部分。template的一个重要使用方法就是template meta programming，它利用编译器对于template的解释是静态的这一特性，让编...&nbsp;&nbsp;<a href='http://www.cppblog.com/woaidongmao/archive/2008/09/14/61802.html'>阅读全文</a><img src ="http://www.cppblog.com/woaidongmao/aggbug/61802.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/woaidongmao/" target="_blank">肥仔</a> 2008-09-14 18:11 <a href="http://www.cppblog.com/woaidongmao/archive/2008/09/14/61802.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++模版：编译期检测可转换和可继承</title><link>http://www.cppblog.com/woaidongmao/archive/2008/09/14/61800.html</link><dc:creator>肥仔</dc:creator><author>肥仔</author><pubDate>Sun, 14 Sep 2008 10:02:00 GMT</pubDate><guid>http://www.cppblog.com/woaidongmao/archive/2008/09/14/61800.html</guid><wfw:comment>http://www.cppblog.com/woaidongmao/comments/61800.html</wfw:comment><comments>http://www.cppblog.com/woaidongmao/archive/2008/09/14/61800.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/woaidongmao/comments/commentRss/61800.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/woaidongmao/services/trackbacks/61800.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 《C++设计新思维》虽然可能实际中可能用不着，但是可以作为理解模版的特化哦！ //C++模版：编译期检测可转换和可继承//一般我们使用dynamic_cast&lt;&gt;在运行期进行转化，但是对于模版编程，我们可以实现编译时类型检测。利用了模版技术，sizeof的编译期就可以得到结果和函数的重载技术。//比如我们检测T是否可以转化为U，我们实现一个函数Test和他的一个重载，函数的参数分别是U...&nbsp;&nbsp;<a href='http://www.cppblog.com/woaidongmao/archive/2008/09/14/61800.html'>阅读全文</a><img src ="http://www.cppblog.com/woaidongmao/aggbug/61800.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/woaidongmao/" target="_blank">肥仔</a> 2008-09-14 18:02 <a href="http://www.cppblog.com/woaidongmao/archive/2008/09/14/61800.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++模版使用技巧--Int2Type</title><link>http://www.cppblog.com/woaidongmao/archive/2008/09/14/61797.html</link><dc:creator>肥仔</dc:creator><author>肥仔</author><pubDate>Sun, 14 Sep 2008 09:54:00 GMT</pubDate><guid>http://www.cppblog.com/woaidongmao/archive/2008/09/14/61797.html</guid><wfw:comment>http://www.cppblog.com/woaidongmao/comments/61797.html</wfw:comment><comments>http://www.cppblog.com/woaidongmao/archive/2008/09/14/61797.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/woaidongmao/comments/commentRss/61797.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/woaidongmao/services/trackbacks/61797.html</trackback:ping><description><![CDATA[<div class="post"> <div class="postText">一&nbsp; Int2Type<br>平常我们所看到的int是一个类型，例如1，2，3...等属于int。 但是这里说的是通过模版使每一个int类型变量都当成是不同的类型。<br>二 C++模版的迟绑定<br>这个名字是我起的，因为不知道正式的称呼是什么，意思是说在使用C++的模版的时候，只有在你的代码里面调用了某个模版方法，在编译的时候才会产生对应的方法，也即编译后的代码中不包含我们没有使用的模版方法。看下面的实例是可以编译运行的：<br> <div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><img id="Codehighlighter1_8_32_Open_Image" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top"><img id="Codehighlighter1_8_32_Closed_Image" style="display: none" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align="top"><span style="color: #0000ff">class</span><span style="color: #000000"> X </span><span id="Codehighlighter1_8_32_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id="Codehighlighter1_8_32_Open_Text"><span style="color: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top"></span><span style="color: #0000ff">public</span><span style="color: #000000">:<br><img id="Codehighlighter1_29_30_Open_Image" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"><img id="Codehighlighter1_29_30_Closed_Image" style="display: none" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align="top">&nbsp; </span><span style="color: #0000ff">void</span><span style="color: #000000"> f() </span><span id="Codehighlighter1_29_30_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id="Codehighlighter1_29_30_Open_Text"><span style="color: #000000">{}</span></span><span style="color: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top">}</span></span><span style="color: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"><br><img id="Codehighlighter1_44_68_Open_Image" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top"><img id="Codehighlighter1_44_68_Closed_Image" style="display: none" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align="top"></span><span style="color: #0000ff">class</span><span style="color: #000000"> Y </span><span id="Codehighlighter1_44_68_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id="Codehighlighter1_44_68_Open_Text"><span style="color: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top"></span><span style="color: #0000ff">public</span><span style="color: #000000">:<br><img id="Codehighlighter1_65_66_Open_Image" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"><img id="Codehighlighter1_65_66_Closed_Image" style="display: none" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align="top">&nbsp; </span><span style="color: #0000ff">void</span><span style="color: #000000"> g() </span><span id="Codehighlighter1_65_66_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id="Codehighlighter1_65_66_Open_Text"><span style="color: #000000">{}</span></span><span style="color: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top">}</span></span><span style="color: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"><br><img id="Codehighlighter1_102_163_Open_Image" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top"><img id="Codehighlighter1_102_163_Closed_Image" style="display: none" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align="top">template </span><span style="color: #000000">&lt;</span><span style="color: #000000">typename T</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">class</span><span style="color: #000000"> Z </span><span id="Codehighlighter1_102_163_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id="Codehighlighter1_102_163_Open_Text"><span style="color: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp; T t;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top"></span><span style="color: #0000ff">public</span><span style="color: #000000">:<br><img id="Codehighlighter1_130_139_Open_Image" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"><img id="Codehighlighter1_130_139_Closed_Image" style="display: none" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align="top">&nbsp; </span><span style="color: #0000ff">void</span><span style="color: #000000"> a() </span><span id="Codehighlighter1_130_139_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id="Codehighlighter1_130_139_Open_Text"><span style="color: #000000">{ t.f(); }</span></span><span style="color: #000000"><br><img id="Codehighlighter1_152_161_Open_Image" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"><img id="Codehighlighter1_152_161_Closed_Image" style="display: none" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align="top">&nbsp; </span><span style="color: #0000ff">void</span><span style="color: #000000"> b() </span><span id="Codehighlighter1_152_161_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id="Codehighlighter1_152_161_Open_Text"><span style="color: #000000">{ t.g(); }</span></span><span style="color: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top">}</span></span><span style="color: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"><br><img id="Codehighlighter1_178_278_Open_Image" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top"><img id="Codehighlighter1_178_278_Closed_Image" style="display: none" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align="top"></span><span style="color: #0000ff">int</span><span style="color: #000000"> main() </span><span id="Codehighlighter1_178_278_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id="Codehighlighter1_178_278_Open_Text"><span style="color: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp; Z</span><span style="color: #000000">&lt;</span><span style="color: #000000">X</span><span style="color: #000000">&gt;</span><span style="color: #000000"> zx;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp; zx.a(); </span><span style="color: #008000">//</span><span style="color: #008000"> Doesn't create Z&lt;X&gt;::b()</span><span style="color: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top"></span><span style="color: #000000">&nbsp; Z</span><span style="color: #000000">&lt;</span><span style="color: #000000">Y</span><span style="color: #000000">&gt;</span><span style="color: #000000"> zy;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp; zy.b(); </span><span style="color: #008000">//</span><span style="color: #008000"> Doesn't create Z&lt;Y&gt;::a()</span><span style="color: #008000"><br><img id="Codehighlighter1_280_285_Open_Image" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top"><img id="Codehighlighter1_280_285_Closed_Image" style="display: none" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align="top"></span><span style="color: #000000">}</span></span><span style="color: #000000">&nbsp;</span><span id="Codehighlighter1_280_285_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff">/**/</span><span id="Codehighlighter1_280_285_Open_Text"><span style="color: #808080">///</span><span style="color: #008000">:~</span></div><br>三 问题<br><br> <div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"><span style="color: #000000">template </span><span style="color: #000000">&lt;</span><span style="color: #000000">typename T, </span><span style="color: #0000ff">bool</span><span style="color: #000000"> isPolymorphic</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"></span><span style="color: #0000ff">class</span><span style="color: #000000"> NiftyContainer<br><img id="Codehighlighter1_63_286_Open_Image" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top"><img id="Codehighlighter1_63_286_Closed_Image" style="display: none" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align="top"></span><span id="Codehighlighter1_63_286_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id="Codehighlighter1_63_286_Open_Text"><span style="color: #000000">{&nbsp;&nbsp; <br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp; </span><span style="color: #0000ff">void</span><span style="color: #000000"> DoSomething()<br><img id="Codehighlighter1_93_284_Open_Image" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"><img id="Codehighlighter1_93_284_Closed_Image" style="display: none" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align="top">&nbsp;&nbsp; </span><span id="Codehighlighter1_93_284_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id="Codehighlighter1_93_284_Open_Text"><span style="color: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; T</span><span style="color: #000000">*</span><span style="color: #000000"> pSomeObj </span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;<img src="http://www.cppblog.com/Images/dot.gif">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff">if</span><span style="color: #000000"> (isPolymorphic)<br><img id="Codehighlighter1_151_202_Open_Image" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"><img id="Codehighlighter1_151_202_Closed_Image" style="display: none" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span id="Codehighlighter1_151_202_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id="Codehighlighter1_151_202_Open_Text"><span style="color: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; T</span><span style="color: #000000">*</span><span style="color: #000000"> pNewObj </span><span style="color: #000000">=</span><span style="color: #000000"> pSomeObj</span><span style="color: #000000">-&gt;</span><span style="color: #000000">Clone();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span></span><span style="color: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff">else</span><span style="color: #000000"><br><img id="Codehighlighter1_221_279_Open_Image" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"><img id="Codehighlighter1_221_279_Closed_Image" style="display: none" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span id="Codehighlighter1_221_279_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id="Codehighlighter1_221_279_Open_Text"><span style="color: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; T</span><span style="color: #000000">*</span><span style="color: #000000"> pNewObj </span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000"> T(</span><span style="color: #000000">*</span><span style="color: #000000">pSomeObj);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span></span><span style="color: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top">&nbsp;&nbsp; }</span></span><span style="color: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top">}</span></span><span style="color: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"></span><span style="color: #0000ff">class</span><span style="color: #000000"> Test<br><img id="Codehighlighter1_300_321_Open_Image" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top"><img id="Codehighlighter1_300_321_Closed_Image" style="display: none" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align="top"></span><span id="Codehighlighter1_300_321_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id="Codehighlighter1_300_321_Open_Text"><span style="color: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top"></span><span style="color: #0000ff">public</span><span style="color: #000000">:<br><img id="Codehighlighter1_317_318_Open_Image" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"><img id="Codehighlighter1_317_318_Closed_Image" style="display: none" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align="top">&nbsp;&nbsp;&nbsp; Test()</span><span id="Codehighlighter1_317_318_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id="Codehighlighter1_317_318_Open_Text"><span style="color: #000000">{}</span></span><span style="color: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top">}</span></span><span style="color: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"></span><span style="color: #0000ff">void</span><span style="color: #000000"> main()<br><img id="Codehighlighter1_337_408_Open_Image" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top"><img id="Codehighlighter1_337_408_Closed_Image" style="display: none" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align="top"></span><span id="Codehighlighter1_337_408_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id="Codehighlighter1_337_408_Open_Text"><span style="color: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp; NiftyContainer</span><span style="color: #000000">&lt;</span><span style="color: #000000">Test,</span><span style="color: #0000ff">true</span><span style="color: #000000">&gt;</span><span style="color: #000000"> test;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp; </span><span style="color: #008000">//</span><span style="color: #008000">test.DoSomething(); </span><span style="color: #008000">//</span><span style="color: #008000"> 这里通不过编译</span><span style="color: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top"></span><span style="color: #000000">&nbsp;&nbsp;&nbsp; <br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top">}</span></span></div>大家也许会说上面的方法代码没有问题，我说，有问题，仔细看一开始的代码和我的说明，我说的是只要我们的代码里面用到模版方法就会被编译为目标代码，而不是说在代码运行的时候使用到的代码才会被编译为目标代码，好的，搞清楚了这个就可以知道上面的实例为什么通不过编译了。<br>四 Int2Type<br>下面正式进入主题Int2Type的作用和使用，上面的实例，我们传入的T类型中只有clone或public构造函数中的一个，我们想根据bool值来选择使用clone或new，但是上面的代码有问题，编译都不过偶，下面使用Int2Type来实现：<br><br> <div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"><span style="color: #000000">template </span><span style="color: #000000">&lt;</span><span style="color: #0000ff">int</span><span style="color: #000000"> v</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"></span><span style="color: #0000ff">struct</span><span style="color: #000000"> Int2Type<br><img id="Codehighlighter1_33_58_Open_Image" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top"><img id="Codehighlighter1_33_58_Closed_Image" style="display: none" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align="top"></span><span id="Codehighlighter1_33_58_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id="Codehighlighter1_33_58_Open_Text"><span style="color: #000000">{<br><img id="Codehighlighter1_43_55_Open_Image" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"><img id="Codehighlighter1_43_55_Closed_Image" style="display: none" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align="top">&nbsp;&nbsp; </span><span style="color: #0000ff">enum</span><span style="color: #000000">&nbsp;</span><span id="Codehighlighter1_43_55_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id="Codehighlighter1_43_55_Open_Text"><span style="color: #000000">{ value </span><span style="color: #000000">=</span><span style="color: #000000"> v }</span></span><span style="color: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top">}</span></span><span style="color: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top">template </span><span style="color: #000000">&lt;</span><span style="color: #000000">typename T, </span><span style="color: #0000ff">bool</span><span style="color: #000000"> isPolymorphic</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"></span><span style="color: #0000ff">class</span><span style="color: #000000"> NiftyContainer<br><img id="Codehighlighter1_126_426_Open_Image" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top"><img id="Codehighlighter1_126_426_Closed_Image" style="display: none" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align="top"></span><span id="Codehighlighter1_126_426_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id="Codehighlighter1_126_426_Open_Text"><span style="color: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top"></span><span style="color: #0000ff">private</span><span style="color: #000000">:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp; </span><span style="color: #0000ff">void</span><span style="color: #000000"> DoSomething(T</span><span style="color: #000000">*</span><span style="color: #000000"> pObj, Int2Type</span><span style="color: #000000">&lt;</span><span style="color: #0000ff">true</span><span style="color: #000000">&gt;</span><span style="color: #000000">)<br><img id="Codehighlighter1_185_229_Open_Image" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"><img id="Codehighlighter1_185_229_Closed_Image" style="display: none" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align="top">&nbsp;&nbsp; </span><span id="Codehighlighter1_185_229_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id="Codehighlighter1_185_229_Open_Text"><span style="color: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; T</span><span style="color: #000000">*</span><span style="color: #000000"> pNewObj </span><span style="color: #000000">=</span><span style="color: #000000"> pObj</span><span style="color: #000000">-&gt;</span><span style="color: #000000">Clone();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp; <br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top">&nbsp;&nbsp; }</span></span><span style="color: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp; </span><span style="color: #0000ff">void</span><span style="color: #000000"> DoSomething(T</span><span style="color: #000000">*</span><span style="color: #000000"> pObj, Int2Type</span><span style="color: #000000">&lt;</span><span style="color: #0000ff">false</span><span style="color: #000000">&gt;</span><span style="color: #000000">)<br><img id="Codehighlighter1_280_325_Open_Image" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"><img id="Codehighlighter1_280_325_Closed_Image" style="display: none" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align="top">&nbsp;&nbsp; </span><span id="Codehighlighter1_280_325_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id="Codehighlighter1_280_325_Open_Text"><span style="color: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; T</span><span style="color: #000000">*</span><span style="color: #000000"> pNewObj </span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000"> T(</span><span style="color: #000000">*</span><span style="color: #000000">pObj);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top">&nbsp;&nbsp; }</span></span><span style="color: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top"></span><span style="color: #0000ff">public</span><span style="color: #000000">:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp; </span><span style="color: #0000ff">void</span><span style="color: #000000"> DoSomething(T</span><span style="color: #000000">*</span><span style="color: #000000"> pObj)<br><img id="Codehighlighter1_367_424_Open_Image" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"><img id="Codehighlighter1_367_424_Closed_Image" style="display: none" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align="top">&nbsp;&nbsp; </span><span id="Codehighlighter1_367_424_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id="Codehighlighter1_367_424_Open_Text"><span style="color: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DoSomething(pObj, Int2Type</span><span style="color: #000000">&lt;</span><span style="color: #000000">isPolymorphic</span><span style="color: #000000">&gt;</span><span style="color: #000000">());<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top">&nbsp;&nbsp; }</span></span><span style="color: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top">}</span></span><span style="color: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"></span><span style="color: #0000ff">class</span><span style="color: #000000"> Test<br><img id="Codehighlighter1_440_461_Open_Image" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top"><img id="Codehighlighter1_440_461_Closed_Image" style="display: none" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align="top"></span><span id="Codehighlighter1_440_461_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id="Codehighlighter1_440_461_Open_Text"><span style="color: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top"></span><span style="color: #0000ff">public</span><span style="color: #000000">:<br><img id="Codehighlighter1_457_458_Open_Image" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"><img id="Codehighlighter1_457_458_Closed_Image" style="display: none" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align="top">&nbsp;&nbsp;&nbsp; Test()</span><span id="Codehighlighter1_457_458_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id="Codehighlighter1_457_458_Open_Text"><span style="color: #000000">{}</span></span><span style="color: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top">}</span></span><span style="color: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"></span><span style="color: #0000ff">void</span><span style="color: #000000"> main()<br><img id="Codehighlighter1_476_573_Open_Image" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top"><img id="Codehighlighter1_476_573_Closed_Image" style="display: none" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align="top"></span><span id="Codehighlighter1_476_573_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id="Codehighlighter1_476_573_Open_Text"><span style="color: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp; NiftyContainer</span><span style="color: #000000">&lt;</span><span style="color: #000000">Test,</span><span style="color: #0000ff">false</span><span style="color: #000000">&gt;</span><span style="color: #000000"> test; </span><span style="color: #008000">//</span><span style="color: #008000">如果用ture不会通过编译</span><span style="color: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top"></span><span style="color: #000000">&nbsp;&nbsp;&nbsp; Test</span><span style="color: #000000">*</span><span style="color: #000000"> t </span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000"> Test();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp; test.DoSomething(t);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top">}</span></span></div><br>看了上面的代码，我不禁要再次的赞叹《C++设计新思维》的作者，高！<br></span></div></div><img src ="http://www.cppblog.com/woaidongmao/aggbug/61797.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/woaidongmao/" target="_blank">肥仔</a> 2008-09-14 17:54 <a href="http://www.cppblog.com/woaidongmao/archive/2008/09/14/61797.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++模版全掌握（实例）</title><link>http://www.cppblog.com/woaidongmao/archive/2008/09/14/61795.html</link><dc:creator>肥仔</dc:creator><author>肥仔</author><pubDate>Sun, 14 Sep 2008 09:37:00 GMT</pubDate><guid>http://www.cppblog.com/woaidongmao/archive/2008/09/14/61795.html</guid><wfw:comment>http://www.cppblog.com/woaidongmao/comments/61795.html</wfw:comment><comments>http://www.cppblog.com/woaidongmao/archive/2008/09/14/61795.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/woaidongmao/comments/commentRss/61795.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/woaidongmao/services/trackbacks/61795.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 前段时间重新学习C++，主要看C++编程思想和C++设计新思维。对模版的使用有了更进一层的了解，特总结如下：下面列出了模版的常用情况： //1. 模板类静态成员template &lt;typename T&gt;&nbsp;struct testClass { &nbsp;&nbsp;&nbsp; static&nbsp;int _data; }; template&lt;&gt;&nbsp;i...&nbsp;&nbsp;<a href='http://www.cppblog.com/woaidongmao/archive/2008/09/14/61795.html'>阅读全文</a><img src ="http://www.cppblog.com/woaidongmao/aggbug/61795.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/woaidongmao/" target="_blank">肥仔</a> 2008-09-14 17:37 <a href="http://www.cppblog.com/woaidongmao/archive/2008/09/14/61795.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++模板元编程技术研究</title><link>http://www.cppblog.com/woaidongmao/archive/2008/09/01/60585.html</link><dc:creator>肥仔</dc:creator><author>肥仔</author><pubDate>Mon, 01 Sep 2008 04:13:00 GMT</pubDate><guid>http://www.cppblog.com/woaidongmao/archive/2008/09/01/60585.html</guid><wfw:comment>http://www.cppblog.com/woaidongmao/comments/60585.html</wfw:comment><comments>http://www.cppblog.com/woaidongmao/archive/2008/09/01/60585.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/woaidongmao/comments/commentRss/60585.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/woaidongmao/services/trackbacks/60585.html</trackback:ping><description><![CDATA[<p></p> <p>　　本文描述了模板元编程技术的起源、概念和机制，并介绍了模板元编程技术在Blitz++和Loki程序库中的应用。 <br>　　要害字<br>　　编译期计算 模板元编程 Blitz++ Loki <br>　　导言 <br>　　1994年，C++标准委员会在圣迭哥举行的一次会议期间Erwin Unruh展示了一段可以产生质数的代码。这段代码的非凡之处在于质数产生于编译期而非运行期，在编译器产生的一系列错误信息中间夹杂着从2到某个设定值之间的所有质数： <br>// Prime number computation by Erwin Unruh <br>template &lt;int i&gt; strUCt D { D(void*); operator int(); }; <br>template &lt;int p, int i&gt; struct is_prime { <br>enum { prim = (p%i) &amp;&amp; is_prime&lt;(i &gt; 2 ? p : 0), i -1&gt; :: prim }; <br>}; <br>template &lt; int i &gt; struct Prime_print { <br>Prime_print&lt;i-1&gt; a; <br>enum { prim = is_prime&lt;i, i-1&gt;::prim }; <br>void f() { D&lt;i&gt; d = prim; } <br>}; <br>struct is_prime&lt;0,0&gt; { enum {prim=1}; }; <br>struct is_prime&lt;0,1&gt; { enum {prim=1}; }; <br>struct Prime_print&lt;2&gt; { enum {prim = 1}; void f() { D&lt;2&gt; d = prim; } }; <br>#ifndef LAST <br>#define LAST 10 <br>#endif <br>main () { <br>Prime_print&lt;LAST&gt; a; <br>} <br>　　类模板D只有一个参数为void*的构造器，而只有0才能被合法转换为void*。1994年，Erwin Unruh采用Metaware 编译器编译出错信息如下（以及其它一些信息，简短起见，它们被删除了）： <br>Type `enum{}′ can′t be converted to tXPe `D&lt;2&gt;′ ("primes.cpp",L2/C25). <br>Type `enum{}′ can′t be converted to txpe `D&lt;3&gt;′ ("primes.cpp",L2/C25). <br>Type `enum{}′ can′t be converted to txpe `D&lt;5&gt;′ ("primes.cpp",L2/C25). <br>Type `enum{}′ can′t be converted to txpe `D&lt;7&gt;′ ("primes.cpp",L2/C25). <br>　　如今，上面的代码已经不再是合法的C++程序了。以下是Erwin Unruh亲手给出的修订版，可以在今天符合标准的C++编译器上进行编译： <br>// Prime number computation by Erwin Unruh <br>template &lt;int i&gt; struct D { D(void*); operator int(); }; <br>template &lt;int p, int i&gt; struct is_prime { <br>enum { prim = (p==2) (p%i) &amp;&amp; is_prime&lt;(i&gt;2?p:0), i-1&gt; :: prim }; <br>}; <br>template &lt;int i&gt; struct Prime_print { <br>Prime_print&lt;i-1&gt; a; <br>enum { prim = is_prime&lt;i, i-1&gt;::prim }; <br>void f() { D&lt;i&gt; d = prim ? 1 : 0; a.f();} <br>}; <br>template&lt;&gt; struct is_prime&lt;0,0&gt; { enum {prim=1}; }; <br>template&lt;&gt; struct is_prime&lt;0,1&gt; { enum {prim=1}; }; <br>template&lt;&gt; struct Prime_print&lt;1&gt; { <br>enum {prim=0}; <br>void f() { D&lt;1&gt; d = prim ? 1 : 0; }; <br>}; <br>#ifndef LAST <br>#define LAST 18 <br>#endif <br>main() { <br>Prime_print&lt;LAST&gt; a; <br>a.f(); <br>} <br>　　在GNU C++ (MinGW Special) 3.2中编译这段程序时，编译器将会给出如下出错信息（以及其它一些信息，简短起见，它们被删除了）： <br>Unruh.cpp:12: initializing argument 1 of `D&lt;i&gt;::D(void*) [with int i = 17]'<br>Unruh.cpp:12: initializing argument 1 of `D&lt;i&gt;::D(void*) [with int i = 13]'<br>Unruh.cpp:12: initializing argument 1 of `D&lt;i&gt;::D(void*) [with int i = 11]'<br>Unruh.cpp:12: initializing argument 1 of `D&lt;i&gt;::D(void*) [with int i = 7]'<br>Unruh.cpp:12: initializing argument 1 of `D&lt;i&gt;::D(void*) [with int i = 5]'<br>Unruh.cpp:12: initializing argument 1 of `D&lt;i&gt;::D(void*) [with int i = 3]'<br>Unruh.cpp:12: initializing argument 1 of `D&lt;i&gt;::D(void*) [with int i = 2]' <br>　　这个例子展示了可以利用模板实例化机制于编译期执行一些计算。这种通过模板实例化而执行的非凡的编译期计算技术即被称为模板元编程。<br>　　顺便说一句，因为编译器的出错信息并未被标准化，所以，假如你在Visual C++、Borland C++等编译器上看不到这么具体的出错信息，请不必讶异。 <br>一个可以运行的模板元编程例子 <br>　　模板元编程（Template Metaprogramming）更准确的含义应该是“编‘可以编程序的’程序”，而模板元程序（Template Metaprogram）则是“‘可以编程序的’程序”。也就是说，我们给出代码的产生规则，编译器在编译期解释这些规则并生成新代码来实现我们预期的功能。 <br>　　Erwin Unruh的那段经典代码并没有执行，它只是以编译出错信息的方式输出中间计算结果。让我们来看一个可以运行的模板元编程例子 — 计算给定整数的指定次方： <br>// xy.h<br>//原始摸板<br>template&lt;int Base, int Exponent&gt;<br>class XY<br>{<br>public:<br>enum { result_ = Base * XY&lt;Base, Exponent-1&gt;::result_ };<br>};<br>//用于终结递归的局部特化版<br>template&lt;int Base&gt;<br>class XY&lt;Base, 0&gt; <br>{<br>public:<br>enum { result_ = 1 };<br>};<br>　　模板元编程技术之根本在于递归模板实例化。第一个模板实现了一般情况下的递归规则。当用一对整数&lt;X, Y&gt;来实例化模板时，模板XY&lt;X, Y&gt;需要计算其result_的值，将同一模板中针对&lt;X, Y-1&gt;实例化所得结果乘以X即可。第二个模板是一个局部特化版本，用于终结递归。 <br>　　让我们看看使用此模板来计算5^4 （通过实例化XY&lt;5, 4&gt;）时发生了什么： <br>// xytest.cpp<br>#include &lt;iostream&gt;<br>#include "xy.h"<br>int main() <br>{<br>std::cout &lt;&lt; "X^Y&lt;5, 4&gt;::result_ = " &lt;&lt; XY&lt;5, 4&gt;::result_;<br>}<br>　　首先，编译器实例化XY&lt;5, 4&gt;，它的result_为5 * XY&lt;5, 3&gt;::result_，如此一来，又需要针对&lt;5, 3&gt;实例化同样的模板，后者又实例化XY&lt;5, 2&gt;…… 当实例化到XY&lt;5, 0&gt;的时候，result_的值被计算为1，至此递归结束。 <br>　　递归模板实例化的深度和终结条件 <br>　　可以想象，假如我们以非常大的Y值来实例化类模板XY，那肯定会占用大量的编译器资源甚至会迅速耗尽可用资源（在计算结果溢出之前），因此，在实践中我们应该有节制地使用模板元编程技术。 <br>　　虽然 C++标准建议的最小实例化深度只有17层，然而大多数编译器都能够处理至少几十层，有些编译器答应实例化至数百层，更有一些可达数千层，直至资源耗尽。 <br>　　假如我们拿掉XY模板局部特化版本，情况会如何？ <br>// xy2.h<br>//原始摸板<br>template&lt;int Base, int Exponent&gt;<br>class XY<br>{<br>public:<br>enum { result_ = Base * XY&lt;Base, Exponent-1&gt;::result_ };<br>};<br>　　测试程序不变： <br>// xytest2.cpp<br>#include &lt;iostream&gt;<br>#include "xy2.h"<br>int main() <br>{<br>std::cout &lt;&lt; "X^Y&lt;5, 4&gt;::result_ = " &lt;&lt; XY&lt;5, 4&gt;::result_;<br>} <br>　　执行如下编译命令： <br>C:\&gt;g++ -c xytest2.cpp <br>　　你将会看到递归实例化将一直进行下去，直到达到编译器的极限。 <br>　　GNU C++ (MinGW Special) 3.2的默认实例化极限深度为500层，你也可以手工调整实例化深度： <br>C:\&gt;g++ -ftemplate-depth-3400 -c xytest2.cpp <br>　　事实上，就本例而言，g++ 3.2答应的实例化极限深度还可以再大一些（我的测试结果是不超过3450层）。 <br>　　因此，在使用模板元编程技术时，我们总是要给出原始模板的特化版（局部特化版或完全特化版或兼而有之），以作为递归模板实例化的终结准则。 利用模板元编程技术解开循环 <br>　　模板元编程技术最早的实际应用之一是用于数值计算中的解循环。举个例子，对一个数组进行求和的常见方法是： <br>// sumarray.h<br>template &lt;typename T&gt;<br>inline T sum_array(int Dim, T* a)<br>{<br>T result = T();<br>for (int i = 0; i &lt; Dim; ++i) <br>{ <br>result += a[i];<br>}<br>return result;<br>}<br>　　这当然可行，但我们也可以利用模板元编程技术来解开循环： <br>// sumarray2.h<br>// 原始模板<br>template &lt;int Dim, typename T&gt;<br>class Sumarray <br>{<br>public:<br>static T result(T* a)<br>{<br>return a[0] + Sumarray&lt;Dim-1, T&gt;::result(a+1);<br>}<br>};<br>// 作为终结准则的局部特化版<br>template &lt;typename T&gt;<br>class Sumarray&lt;1, T&gt; <br>{<br>public:<br>static T result(T* a)<br>{<br>return a[0];<br>}<br>};<br>　　用法如下： <br>// sumarraytest2.cpp<br>#include &lt;iostream&gt;<br>#include "sumarray2.h"<br>int main()<br>{<br>int a[6] = {1, 2, 3, 4, 5, 6};<br>std::cout &lt;&lt; " Sumarray&lt;6&gt;(a) = " &lt;&lt; Sumarray&lt;6, int&gt;::result(a);<br>}<br>　　当我们计算Sumarray&lt;6, int&gt;::result(a)时，实例化过程如下： <br>Sumarray&lt;6, int&gt;::result(a)<br>= a[0] + Sumvector&lt;5, int&gt;::result(a+1)<br>= a[0] + a[1] + Sumvector&lt;4, int&gt;::result(a+2)<br>= a[0] + a[1] + a[2] + Sumvector&lt;3, int&gt;::result(a+3)<br>= a[0] + a[1] + a[2] + a[3] + Sumvector&lt;2, int&gt;::result(a+4)<br>= a[0] + a[1] + a[2] + a[3] + a[4] + Sumvector&lt;1, int&gt;::result(a+5)<br>= a[0] + a[1] + a[2] + a[3] + a[4] + a[5] <br>　　可见，循环被展开为a[0] + a[1] + a[2] + a[3] + a[4] + a[5]。这种直截了当的展开运算几乎总是比循环来得更有效率。 <br>　　也许拿一个有着600万个元素的数组来例证循环开解的优势可能更有说服力。生成这样的数组很轻易，有爱好，你不妨测试、对比一下。<br>　　（感谢一位不知名的朋友的测试。他说：“据在Visual C++ 2003上实测编译器应当进行了尾递归优化，可以不受上面说的递归层次的限制，然而连加的结果在数组个数达到4796之后就不再正确了，程序输出了空行，已经出错” — 2003年12月30日补充） 模板元编程在数值计算程序库中的应用 <br>　　Blitz++之所以“快如闪电”（这正是blitz的字面含义），离不开模板元程序的功劳。Blitz++淋漓尽致地使用了元编程技术，你可以到这些文件源代码中窥探究竟： <br>dot.h <br>matassign.h <br>matmat.h <br>matvec.h <br>metaprog.h <br>product.h <br>sum.h <br>vecassign.h <br>　　让我们看看Blitz++程序库dot.h文件中的模板元程序： <br>template&lt;int N, int I&gt;<br>class _bz_meta_vectorDot {<br>public:<br>enum { loopFlag = (I &lt; N-1) ? 1 : 0 };<br>template&lt;class T_expr1, class T_expr2&gt;<br>static inline BZ_PROMOTE(_bz_typename T_expr1::T_numtype, _bz_typename T_expr2::T_numtype)<br>f(const T_expr1&amp; a, const T_expr2&amp; b)<br>{<br>return a[I] * b[I] + _bz_meta_vectorDot&lt;loopFlag * N, loopFlag * (I+1)&gt;::f(a,b);<br>}<br>template&lt;class T_expr1, class T_expr2&gt;<br>static inline BZ_PROMOTE(_bz_typename T_expr1::T_numtype, _bz_typename T_expr2::T_numtype)<br>f_value_ref(T_expr1 a, const T_expr2&amp; b)<br>{<br>return a[I] * b[I] + _bz_meta_vectorDot&lt;loopFlag * N, loopFlag * (I+1)&gt;::f(a,b);<br>}<br>template&lt;class T_expr1, class T_expr2&gt;<br>static inline BZ_PROMOTE(_bz_typename T_expr1::T_numtype, _bz_typename T_expr2::T_numtype)<br>f_ref_value(const T_expr1&amp; a, T_expr2 b)<br>{<br>return a[I] * b[I] + _bz_meta_vectorDot&lt;loopFlag * N, loopFlag * (I+1)&gt;::f(a,b);<br>}<br>template&lt;class T_expr1, class P_numtype2&gt;<br>static inline BZ_PROMOTE(_bz_typename T_expr1::T_numtype, P_numtype2)<br>dotWithArgs(const T_expr1&amp; a, P_numtype2 i1, P_numtype2 i2=0,<br>P_numtype2 i3=0, P_numtype2 i4=0, P_numtype2 i5=0, P_numtype2 i6=0,<br>P_numtype2 i7=0, P_numtype2 i8=0, P_numtype2 i9=0, P_numtype2 i10=0)<br>{<br>return a[I] * i1 + _bz_meta_vectorDot&lt;loopFlag * N, loopFlag * (I+1)&gt;::dotWithArgs<br>(a, i2, i3, i4, i5, i6, i7, i8, i9);<br>}<br>};<br>template&lt;&gt;<br>class _bz_meta_vectorDot&lt;0,0&gt; {<br>public:<br>template&lt;class T_expr1, class T_expr2&gt;<br>static inline _bz_meta_nullOperand f(const T_expr1&amp;, const T_expr2&amp;)<br>{ return _bz_meta_nullOperand(); }<br>template&lt;class T_expr1, class P_numtype2&gt;<br>static inline _bz_meta_nullOperand <br>dotWithArgs(const T_expr1&amp; a, P_numtype2 i1, P_numtype2 i2=0,<br>P_numtype2 i3=0, P_numtype2 i4=0, P_numtype2 i5=0, P_numtype2 i6=0,<br>P_numtype2 i7=0, P_numtype2 i8=0, P_numtype2 i9=0, P_numtype2 i10=0)<br>{<br>return _bz_meta_nullOperand(); <br>}<br>};<br>　　这段代码远比它乍看上去的简单。_bz_meta_vectorDot类模板使用了一个临时变量loopFlag来存放每一步循环条件的评估结果，并使用了一个完全特化版作为递归终结的条件。需要说明的是，和几乎所有元程序一样，这个临时变量作用发挥于编译期，并将从运行代码中优化掉。 <br>　　Todd是在Blitz++数值数组库的主要作者。这个程序库（以及MTL和POOMA等程序库）例证了模板元程序可以为我们带来更加高效的数值计算性能。Todd宣称Blitz++的性能可以和对应的Fortran程序库媲美。 <br><strong>Loki程序库：活用模板元编程技术的典范 </strong><br>　　模板元编程的价值仅仅在于高性能数值计算吗？不仅如此。Loki程序库以对泛型模式的开创性工作闻名于C++社群。它很巧妙地利用了模板元编程技术实现了Typelist<a href="http://www.knowsky.com/tag-14.html">组件</a>。Typelist是实现Abstract Factory、Visitor等泛型模式不可或缺的基础设施。 <br>　　就像C++标准库组件std::list提供对一组数值的操作一样，Typelist可以用来操纵一组类型，其定义非常简单（摘自Loki程序库Typelist.h单元）： <br>template &lt;class T, class U&gt;<br>struct Typelist<br>{<br>typedef T Head;<br>typedef U Tail;<br>};<br>　　显然，Typelist没有任何状态，也未定义任何操作，其作用只在于携带类型信息，它并未打算被实例化，因此，对于Typelist的任何处理都必然发生于编译期而非运行期。 <br>　　Typelist可以被无限扩展，因为模板参数可以是任何类型（包括该模板的其他具现体）。例如： <br>　　Typelist&lt;char, Typelist&lt;int, Typelist&lt;float, NullType&gt; &gt; &gt; <br>　　就是一个包含有char、int、float三种类型的Typelist。 <br>　　按照Loki的约定，每一个Typelist都必须以NullType结尾。NullType的作用类似于传统C字符串的“\0”，它被声明于Loki程序库的NullType.h文件中： <br>class NullType; <br>　　NullType只有声明，没有定义，因为Loki程序库永远都不需要创建一个NullType对象。 <br>　　让我们看看IndexOf模板元程序，它可以在一个Typelist中查找给定类型的位置（摘自Loki程序库的Typelist.h单元）： <br>template &lt;class TList, class T&gt;<br>struct IndexOf;<br>template &lt;class T&gt;<br>struct IndexOf&lt;NullType, T&gt;<br>{<br>enum { value = -1 };<br>};<br>template &lt;class T, class Tail&gt;<br>struct IndexOf&lt;Typelist&lt;T, Tail&gt;, T&gt;<br>{<br>enum { value = 0 };<br>};<br>template &lt;class Head, class Tail, class T&gt;<br>struct IndexOf&lt;Typelist&lt;Head, Tail&gt;, T&gt;<br>{<br>private:<br>enum { temp = IndexOf&lt;Tail, T&gt;::value };<br>public:<br>enum { value = (temp == -1 ? -1 : 1 + temp) };<br>}; <br>　　IndexOf提供了一个原始模板和三个局部特化版。算法非常简单：假如TList（就是一个Typelist）是一个NullType，则value为-1。假如TList的头部就是T，则value为0。否则将IndexOf施行于TList的尾部和T，并将评估结果置于一个临时变量temp中。假如temp为-1，则value为-1，否则value为1 + temp。 <br>　　为了加深你对Typelist采用的模板元编程技术的熟悉，我从Loki程序库剥离出如下代码，放入一个typelistlite.h文件中： <br>// typelistlite.h<br>// 声明Nulltype <br>class NullType;<br>// Typelist的定义<br>template &lt;class T, class U&gt;<br>struct Typelist<br>{<br>typedef T Head;<br>typedef U Tail;<br>};<br>// IndexOf的定义 <br>// IndexOf原始模板<br>template &lt;class TList, class T&gt; struct IndexOf;<br>// 针对NullType的局部特化版<br>template &lt;class T&gt;<br>struct IndexOf&lt;NullType, T&gt;<br>{<br>enum { value = -1 };<br>};<br>// 针对“Tlist头部就是我们要查找的T”的局部特化版<br>template &lt;class T, class Tail&gt;<br>struct IndexOf&lt;Typelist&lt;T, Tail&gt;, T&gt;<br>{<br>enum { value = 0 };<br>};<br>// 处理Tlist尾部的局部特化版<br>template &lt;class Head, class Tail, class T&gt;<br>struct IndexOf&lt;Typelist&lt;Head, Tail&gt;, T&gt;<br>{<br>private:<br>enum { temp = IndexOf&lt;Tail, T&gt;::value };<br>public:<br>enum { value = (temp == -1 ? -1 : 1 + temp) };<br>}; <br>　　测试程序如下： <br>// typelistlite_test.cpp<br>#include &lt;iostream&gt;<br>#include "typelistlite.h"<br>// 自定义类型Royal<br>class Royal {};<br>// 定义一个包含有char、int、Royal和float的Typelist<br>typedef Typelist&lt;char, Typelist&lt;int, Typelist&lt;Royal, Typelist&lt;float, NullType&gt; &gt; &gt; &gt; CIRF;<br>int main()<br>{<br>std::cout &lt;&lt; "IndexOf&lt;CIRF, int&gt;::value = " &lt;&lt; IndexOf&lt;CIRF, int&gt;::value &lt;&lt; "\n";<br>std::cout &lt;&lt; "IndexOf&lt;CIRF, Royal&gt;::value = " &lt;&lt; IndexOf&lt;CIRF, Royal&gt;::value &lt;&lt; "\n";<br>std::cout &lt;&lt; "IndexOf&lt;CIRF, double&gt;::value = " &lt;&lt; IndexOf&lt;CIRF, double&gt;::value &lt;&lt; "\n";<br>} <br>　　程序输出如下： <br>IndexOf&lt;CIRF, int&gt;::value = 1<br>IndexOf&lt;CIRF, Royal&gt;::value = 2<br>IndexOf&lt;CIRF, double&gt;::value = -1 <br>　　结束语 <br>　　模板元编程技术并非都是优点，比方说，模板元程序编译耗时，带有模板元程序的程序生成的代码尺寸要比普通程序的大，而且通常这种程序调试起来也比常规程序困难得多。另外，对于一些程序员来说，以类模板的方式描述算法也许有点抽象。 <br>　　编译耗时的代价换来的是卓越的运行期性能。通常来说，一个有意义的程序的运行次数（或服役时间）总是远远超过编译次数（或编译时间）。为程序的用户带来更好的体验，或者为性能要求严格的数值计算换取更高的性能，值得程序员付出这样的代价。 <br>　　很难想象模板元编程技术会成为每一个普通程序员的日常工具，相反，就像Blitz++和Loki那样，模板元程序几乎总是应该被封装在一个程序库的内部。对于库的用户来说，它应该是透明的。模板元程序可以（也应该）用作常规模板代码的内核，为要害的算法实现更好的性能，或者为非凡的目的实现非凡的效果。 <br>　　模板元编程技术首次正式亮相于Todd Veldhuizen的Using C++ Template Metaprograms论文之中。这篇文章首先发表于1995年5月的C++ Report期刊上，后来Stanley Lippman编辑C++ Gems一书时又收录了它。参考文献中给出了这篇文章的链接，它还描述了许多本文没有描述到的内容。 </p><img src ="http://www.cppblog.com/woaidongmao/aggbug/60585.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/woaidongmao/" target="_blank">肥仔</a> 2008-09-01 12:13 <a href="http://www.cppblog.com/woaidongmao/archive/2008/09/01/60585.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>c++模板基础</title><link>http://www.cppblog.com/woaidongmao/archive/2008/09/01/60584.html</link><dc:creator>肥仔</dc:creator><author>肥仔</author><pubDate>Mon, 01 Sep 2008 04:10:00 GMT</pubDate><guid>http://www.cppblog.com/woaidongmao/archive/2008/09/01/60584.html</guid><wfw:comment>http://www.cppblog.com/woaidongmao/comments/60584.html</wfw:comment><comments>http://www.cppblog.com/woaidongmao/archive/2008/09/01/60584.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/woaidongmao/comments/commentRss/60584.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/woaidongmao/services/trackbacks/60584.html</trackback:ping><description><![CDATA[<p></p> <p>只有使用C++语言的少数用户才努力尝试去理解模板的基本原理。然而那些希望去探索更多高级用法的人往往发现自己需要努力去理解模板是如何被语言所支持的，因为缺乏明确的说明。一个很大的问题在于一些工具只实现了C++标准的一个子集。本文将指出它们共同的缺陷并深入剖析如何使用C++模板快速产生可重用和高效的代码。 <p>模板功能应用的典型是通过一系列模板类形成的完整类库，特别是STL和ATL。标准C++库(STL)提供了很多可重用和灵活的类及算法，而ATL则是使用C++进行COM编程的事实标准。要掌握这些及其它的模板库，理解模板是如何工作的这一基础是非常重要的。 <p>函数模板 <p>int main()<br>{<br>&nbsp;&nbsp;&nbsp; 0 cout&lt;&lt;add(2,3)&lt;&lt;endl;<br>&nbsp;&nbsp;&nbsp; 1 cout&lt;&lt;add(2.1,3)&lt;&lt;endl;<br>&nbsp;&nbsp;&nbsp; 2 cout&lt;&lt;add(2,3.2)&lt;&lt;endl;<br>&nbsp;&nbsp;&nbsp; 3 cout&lt;&lt;add(2.2,3.3)&lt;&lt;endl;<br>&nbsp;&nbsp;&nbsp; 4 cout&lt;&lt;add("hello eone ","world")&lt;&lt;endl;<br>&nbsp;&nbsp;&nbsp; return 0;<br>} <p>&nbsp;&nbsp;&nbsp;&nbsp; 也可以通过宏定义#define add(a,b) ((a)+(b))来实现,但是指针(字符串)不能直接相加.对于2,3,4需要进行模板特化. <p>通过重载函数，我们能够完成多种不同数据类型的相同操作。要实现两个double数值的加法和两个整数类型的加法，我们可以使用一个重载函数： <p>int add(const int x, const int y)  <p>{  <p>return x + y;  <p>}  <p>double add(const double x, const double y)  <p>{  <p>return x + y;  <p>}  <p>这时，编译器将根据它们的参数正确地解决这一问题。 <p>// 调用int add(const int, const int);  <p>const int z1 = add(3, 2);  <p>// 调用double add(const double, const double);  <p>const double z2 = add(3.0, 2.0);  <p>如果我们需要处理其它类型，我们就不得不提供其他函数重载。对每个不同的数据类型实现一个函数重载，它们都遵循相同的模式，每当我们需要调用针对某一数据类型的函数时，原则上编译器为我们生成相应的代码。而一个模板函数则以如下方式实现： <p>template&lt;class T&gt;  <p>const T add(const T &amp;t1, const T &amp;t2)  <p>{  <p>return t1 + t2;  <p>}  <p>从概念上来说，编译器通过模板关键字(后面跟随着模板由一或多个模板参数构成的参数列表)来识别模板。当为某一具体类型调用add时，编译器将根据模板定义并用给定的类型替换出现在模板中的参数。在这个例子中，模板参数列表由一个独立的类型模板参数T构成。使用一个模板函数替代函数重载，编译器可以自动为所需的新类型生成代码 <p>我们可以对任何拥有+操作符定义的类型使用add模板。假设一个自定义的String类提供了字符串连接并知道如何将自身写入到std::ostream。因为String与该模板函数兼容，因此我们可以调用它来实现字符串相加： <p>// 示例字符串 <p>const string strBook("book");  <p>const string strWorm("worm");  <p>// 显示 "bookworm".  <p>cout &lt;&lt; add(strBook, strWorm) &lt;&lt; endl;  <p>Seeing that we intended to add two String values, the compiler will generate the appropriate add function on our behalf, which would look something like: <p>const String add(const String &amp;t1, const String &amp;t2) <p>{ <p>return t1 + t2; <p>} <p>显式实例化 <p>调用模板函数时，编译器将先把正确的类型实例化模板。虽然标准允许显式模板实例化，然而并非所有厂商都能够正确地实例它。例如，Visual C++ 6.0 会潜在地调用错误的函数：: <p>template&lt;class T&gt;  <p>int getSize(void) { <p>return sizeof(T);  <p>}  <p>// 输出4，应该为8  <p>cout &lt;&lt; "double: " &lt;&lt; getSize&lt;double&gt;() &lt;&lt; endl;  <p>// 输出4，正确 <p>cout &lt;&lt; "int: " &lt;&lt; getSize&lt;int&gt;() &lt;&lt; endl;  <p>跨平台代码设计者不希望依赖于显式模板函数实例化，除非有更好的编译器能够对它提供有效的支持 <p>&nbsp;</p> <p>&nbsp;</p> <p>类似于函数模板，模板也可以应用于类。模板可以用于根据普通模式提供一系列类。如果我们需要一套完整的算术运算来补充add函数，我们可以考虑使用一个类。通过模板，它就可以根据类型参数化为一个普通类： <p>template&lt;class T&gt;  <p>class CCalculator  <p>{  <p>public:  <p>CCalculator(const T &amp;x, const T &amp;y) : m_x(x), m_y(y){ }  <p>~CCalculator(void){ }  <p>const T add(void){ return m_x + m_y; }  <p>const T sub(void){ return m_x - m_y; }  <p>const T mult(void){ return m_x * m_y; }  <p>const T div(void){ return m_x / m_y; }  <p>private:  <p>const T m_x;  <p>const T m_y;  <p>};  <p>要实例化模板类，我们需要提供一个指定类型： <p>// 创建一个整数计算对象 <p>CCalculator&lt;int&gt; calc(5, 2);  <p>// 结果应该为 10  <p>const int z = calc.mult();  <p>如函数模板一样，编译器为模板不同类型的引用创建不同的类。这为代码重用提供了一个强大的机制，允许单个模板用于任何兼容的数据类型 <p>模板编辑模型 <p>在编写模板类时，函数定义通常与它们的声明一起保存在头文件中，而不使用另外的.cpp文件。否则可能会导致链接错误。这是因为大多数编译器要求模板定义在以头文件为单位的转译单元中有效 <p>这个行为的原因是模板只是一个模式，同样它们不直接产生代码(直到编译器遇到一个应用实例)。如果我们创建一个CCalculator&lt;int&gt; 实例并调用其中的某个类方法，编译器将需要找到函数定义。如果头文件中包含了该定义则一切都会是正确的。但是如果定义存在于.cpp文件中，编译器不能期望在此时找到匹配的模式并利用其产生所需的代码。然而，C++标准提供了一个机制对编译器进行辅助。Export关键字可以使通知编译器我们提供了一个分离的编辑模板： <p>// MyTemplateFunction.h  <p>template&lt;class T&gt;  <p>void myTemplateFunction(const T &amp;t1);  <p>// MyTemplateFunction.cpp  <p>export template &lt;class T&gt;  <p>void myTemplateFunction(const T &amp;t1)  <p>{  <p>...  <p>}  <p>现在，大多数编译器要求模板定义通过头文件包含被显式添加到转译单元，虽然标准期望能够独立定义于.cpp文件中。这两个不同的模板编辑模型即为包含模型和分离模型。在编写时，我所知的支持分离模型的唯一的编译器是Comeau C++。Comeau 的使用了不少方法来实现对标准中所定义的export关键字用法，但目前也还只是beta版本而已 <p>typename关键字 <p>另一个与模板相关的关键字是typename关键字，它有两种用法。参数下面的模板类： <p>template&lt;class T&gt;  <p>void myFunction(void)  <p>{  <p>// 这里可能会有问题 <p>T::x1 * x2;  <p>} <p>初次讲到的时候可能会以为myFunction声明了一个T::x1类型的指针变量x2。然而，这个函数也能够表示类T的成员变量x1与全局变量x2的二进制乘法操作。使用typename关键字可以告诉编译器某个未知标识符是一个类型： <p>// T:x1 是一个类型，而x2是一个指针 <p>typename T:x1* x2;  <p>第二种用法是在指定模板参数时替换class关键字： <p>// 下面的两种方法是等效的...  <p>template&lt;class T1, class T2&gt;;  <p>template&lt;typename T1, typename T2&gt;;  <p>标准允许以上任意一种方法，它们都是合法的。 <p>成员函数模板 <p>除了全局模板函数外，语言也支持成员模板函数：一个类可以拥有带有模板参数列表的成员函数。参考下面的非模板类，它的构造函数被模板化： <p>class CTypeSize  <p>{  <p>public:  <p>template&lt;class T&gt;  <p>CTypeSize(const T &amp;t1) :  <p>m_nSize(sizeof(t1))  <p>{  <p>}  <p>~CTypeSize(void){ };  <p>int getSize(void) const{ return m_nSize; }  <p>private:  <p>const int m_nSize;  <p>};  <p>当模板成员函数被调用时，编译器使用模板模式为给定类型生成代码。这种情况下，我们能够使用任意类型变量创建一个CtypeSize实例： <p>// 显示12  <p>CTypeSize t1("Hello World");  <p>cout &lt;&lt; t1.getSize() &lt;&lt; endl; <p>// 在VC++6/Win32中显示8  <p>CTypeSize t2(7.0);  <p>cout &lt;&lt; t2.getSize() &lt;&lt; endl; <p>某些时候，成员模板是实现拷贝构造函数最有效的方法，参考一个只有一个交易会的简单容器类： <p>template&lt;class T&gt;  <p>class CSingle  <p>{  <p>public:  <p>CSingle(const T &amp;t1) : m_Value(t1) { }  <p>~CSingle(void){ }  <p>T m_Value;  <p>}; <p>它导致下面的问题： <p>// 创建一个整数容器 <p>CSingle&lt;int&gt; x(7);  <p>// 这里需要一个拷贝构造...  <p>CSingle&lt;double&gt; y(x);  <p>通过使用成员模板，拷贝构造就能够轻松完成： <p>template&lt;class S&gt;  <p>CSingle(const CSingle&lt;S&gt; &amp;s1) : m_Value(s1.m_Value) { } <p>当编辑器能够将类型T的实例转换为类型S时，这是可行的；这是因为double可以从一个整数构造。 <p>总结 <p>模板是C++的一个强大特征，它允许从数据类型中抽象出算法。本文介绍了模板定义和实例化的基础，包括函数、类及成员模板的区别。</p><img src ="http://www.cppblog.com/woaidongmao/aggbug/60584.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/woaidongmao/" target="_blank">肥仔</a> 2008-09-01 12:10 <a href="http://www.cppblog.com/woaidongmao/archive/2008/09/01/60584.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>微软VC++对友元类和模板的支持真的这么差吗？</title><link>http://www.cppblog.com/woaidongmao/archive/2008/08/31/60542.html</link><dc:creator>肥仔</dc:creator><author>肥仔</author><pubDate>Sun, 31 Aug 2008 13:58:00 GMT</pubDate><guid>http://www.cppblog.com/woaidongmao/archive/2008/08/31/60542.html</guid><wfw:comment>http://www.cppblog.com/woaidongmao/comments/60542.html</wfw:comment><comments>http://www.cppblog.com/woaidongmao/archive/2008/08/31/60542.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/woaidongmao/comments/commentRss/60542.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/woaidongmao/services/trackbacks/60542.html</trackback:ping><description><![CDATA[<form id="Form1" name="Form1" action="http://www.cppblog.com/8678.aspx" method="post" _initialAction="8678.aspx"> <div id="centercontent"> <div class="post"> <p>以前写代码的时候就遇到VC++对友元支持得不太好的问题，同时也看过侯捷老师对gnu c++, VC++, BCB 三种编译器的比较，其中VC++对模板友元的支持就不是很好。<br>今天晚上写了一个比较简单的链表的模板类，其中头文件Chain.h原来的代码如下：<br><br><font color="#0000ff" size="2">#include &lt;iostream&gt;<br>using namespace std;</font></p> <p><font color="#0000ff" size="2">#ifndef _CHAIN<br>#define _CHAIN</font> </p> <p><font color="#0000ff" size="2">template&lt;class T&gt;<br>class ChainNode<br>{<br> friend class Chain&lt;T&gt;;<br>private:<br> T data;<br> ChainNode&lt;T&gt; *link;<br>};</font> </p> <p><font color="#0000ff" size="2">template&lt;class T&gt;<br>class Chain{<br>public:<br> Chain() <br> {<br>&nbsp; first = 0;<br> };<br> ~Chain();<br> bool IsEmpty() const {return first == 0;}<br> int Length() const;<br> bool Find(int k, T&amp; x) const;<br> int Search(const T&amp; x) const;<br> //Chain&lt;T&gt;&amp; Delete(int k, T&amp; x);<br> Chain&lt;T&gt;&amp; Insert(int k, const T&amp; x);<br> void Output(ostream&amp; out = cout) const;<br>private:<br> ChainNode&lt;T&gt; *first; // 指向第一个节点的指针<br>};</font> </p> <p><font color="#0000ff" size="2">#endif&nbsp; // _CHAIN<br><br>结果报错：<br>--------------------Configuration: Chain - Win32 Debug--------------------<br>Compiling...<br>Chain.cpp<br>g:\work plan\c++ code practice\chain\chain.h(17) : error C2059: syntax error : '&lt;'<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; g:\work plan\c++ code practice\chain\chain.h(21) : see reference to class template instantiation 'ChainNode&lt;T&gt;' being compiled<br>g:\work plan\c++ code practice\chain\chain.h(17) : error C2238: unexpected token(s) preceding ';'<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; g:\work plan\c++ code practice\chain\chain.h(21) : see reference to class template instantiation 'ChainNode&lt;T&gt;' being compiled<br>g:\work plan\c++ code practice\chain\chain.h(40) : error C2989: 'Chain' : template class has already been defined as a non-template class<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; g:\work plan\c++ code practice\chain\chain.h(17) : see declaration of 'Chain'<br>g:\work plan\c++ code practice\chain\chain.cpp(6) : error C2059: syntax error : '&lt;'<br>g:\work plan\c++ code practice\chain\chain.cpp(6) : error C2588: '::~Chain' : illegal global destructor<br>g:\work plan\c++ code practice\chain\chain.cpp(6) : fatal error C1903: unable to recover from previous error(s); stopping compilation<br>Error executing cl.exe.</font> </p> <p><font color="#0000ff" size="2">Chain.obj - 6 error(s), 0 warning(s)<br><br><font size="3"><font color="#000000">感觉从代码来看应该是没有问题的，如果哪个高手看出问题来了请一定告诉我啊，如果知道编译不通过的原因也请一定要告诉我啊。没办法，最后采用解决的办法就是修改ChainNode的定义了，定义为结构体:)<br><font color="#0000ff" size="2">template&lt;class T&gt;<br>struct ChainNode<br>{<br>&nbsp; T data;<br>&nbsp; ChainNode&lt;T&gt; *link;<br>};</font><br>反正结构体中的数据成员都是public的，至于访问限制的实现就依靠迭代器来实现了，g++的STL中的树结点不也是结构体吗？:)<br></font></font></font></p> <div class="postDesc">posted on 2006-06-17 23:39 <a href="http://www.cppblog.com/bourne/">Bourne</a> 阅读(733) <a href="http://www.cppblog.com/#Post">评论(4)</a>&nbsp; <a href="http://www.cppblog.com/bourne/admin/EditPosts.aspx?postid=8678">编辑</a>&nbsp;<a href="http://www.cppblog.com/bourne/AddToFavorite.aspx?id=8678">收藏</a> <a href="http://www.cppblog.com/bourne/services/trackbacks/8678.aspx">引用</a> </div></div><img height="1" src="http://www.cppblog.com/bourne/aggbug/8678.html?webview=1" width="1">  <div id="AjaxHolder_UpdatePanel1"><a name="pagedcomment"></a><br><b>FeedBack:</b>  <div class="feedbackNoItems"></div> <div class="feedbackItem"> <div class="feedbackListSubtitle"> <div class="feedbacktitle"><a title="permalink: re: 微软VC++对友元类和模板的支持真的这么差吗？" href="http://www.cppblog.com/bourne/archive/2006/06/17/8678.aspx#8686">#</a>&nbsp;<a name="8686"></a>re: 微软VC++对友元类和模板的支持真的这么差吗？ 2006-06-18 15:01 <a id="AjaxHolder_Comments_CommentList_ctl00_NameLink" target="_blank">mroske</a></div> <div align="left">// 在 ChainNode 之前声明 Chain 。 <br>template&lt;class T&gt; <br>class Chain; <br><br>template&lt;class T&gt; <br>struct ChainNode <br>{ <br>friend class Chain&lt;T&gt;; // class Chain&lt;T&gt; 在没有声明之前 <br>// 不被发现。。。 <br>// 因为 friend class Chain&lt;T&gt; <br>// 不是声明 Chain 是类模板。 <br>// -- 以上个人之见。 <br>private: <br>T data; <br>ChainNode&lt;T&gt; *link; <br>}; <br><br>&nbsp; <a href="http://www.cppblog.com/bourne/archive/2006/06/17/8678.aspx#post">回复</a>&nbsp; <a title="查看该作者发表过的评论" href="http://www.cppblog.com/comment?author=mroske" target="_blank">更多评论</a><br><a id="AjaxHolder_Comments_CommentList_ctl00_DeleteLink" href="http://www.cppblog.com/"></a>&nbsp; <a id="AjaxHolder_Comments_CommentList_ctl00_EditLink"></a> </div></div> <div class="feedbackItem"> <div class="feedbackListSubtitle"> <div class="feedbacktitle"><a title="permalink: re: 微软VC++对友元类和模板的支持真的这么差吗？" href="http://www.cppblog.com/bourne/archive/2006/06/17/8678.aspx#8692">#</a>&nbsp;<a name="8692"></a>re: 微软VC++对友元类和模板的支持真的这么差吗？ 2006-06-18 21:59 <a id="AjaxHolder_Comments_CommentList_ctl01_NameLink" href="http://spaces.msn.com/cornerzhang" target="_blank">Corner</a></div> <div align="left">是啊！缺了template&lt;class T&gt; class Chain;的前向声明在template&lt;class T&gt; struct ChainNode前面.&nbsp; <a href="http://www.cppblog.com/bourne/archive/2006/06/17/8678.aspx#post">回复</a>&nbsp; <a title="查看该作者发表过的评论" href="http://www.cppblog.com/comment?author=Corner" target="_blank">更多评论</a><br><a id="AjaxHolder_Comments_CommentList_ctl01_DeleteLink" href="http://www.cppblog.com/"></a>&nbsp; <a id="AjaxHolder_Comments_CommentList_ctl01_EditLink"></a> </div></div> <div class="feedbackItem"> <div class="feedbackListSubtitle"> <div class="feedbacktitle"><a title="permalink: re: 微软VC++对友元类和模板的支持真的这么差吗？" href="http://www.cppblog.com/bourne/archive/2006/06/17/8678.aspx#8697">#</a>&nbsp;<a name="8697"></a>re: 微软VC++对友元类和模板的支持真的这么差吗？ 2006-06-19 09:59 <a id="AjaxHolder_Comments_CommentList_ctl02_NameLink" href="http://www.cppblog.com/bourne/" target="_blank">Bourne</a></div> <div align="left">试了一下，果然是这个错误，谢谢朋友的指点啊！&nbsp; <a href="http://www.cppblog.com/bourne/archive/2006/06/17/8678.aspx#post">回复</a>&nbsp; <a title="查看该作者发表过的评论" href="http://www.cppblog.com/comment?author=Bourne" target="_blank">更多评论</a><br><a id="AjaxHolder_Comments_CommentList_ctl02_DeleteLink" href="http://www.cppblog.com/"></a>&nbsp; <a id="AjaxHolder_Comments_CommentList_ctl02_EditLink"></a> </div></div> <div class="feedbackItem"> <div class="feedbackListSubtitle"> <div class="feedbacktitle"><a title="permalink: re: 微软VC++对友元类和模板的支持真的这么差吗？" href="http://www.cppblog.com/bourne/archive/2006/06/17/8678.aspx#44126">#</a>&nbsp;<a name="44126"></a>re: 微软VC++对友元类和模板的支持真的这么差吗？<a name="Post"></a> 2008-03-11 02:12 <a id="AjaxHolder_Comments_CommentList_ctl03_NameLink" href="http://WE" target="_blank">WR</a></div> <div align="left"><br>#include &lt;iostream.h&gt; <br><br>template &lt;typename T&gt; <br>class Chain; <br><br>template&lt;class T&gt; <br>class ChainNode <br>{ <br>friend class Chain&lt;T&gt;; <br>private: <br>T data; <br>ChainNode&lt;T&gt; *link; <br>}; <br><br>template&lt;class T&gt; <br>class Chain{ <br>public: <br>Chain() <br>{ <br>// first = 0; <br>} <br>~Chain(); <br><br>bool IsEmpty() const {return first == 0;} <br>int Length() const; <br>bool Find(int k, T&amp; x) const; <br>int Search(const T&amp; x) const; <br>Chain&lt;T&gt;&amp; Delete(int k, T&amp; x); <br>Chain&lt;T&gt;&amp; Insert(int k, const T&amp; x); <br>void Output(ostream&amp; out = cout) const; <br>private: <br><br>ChainNode&lt;T&gt; *first; // 指向第一个节点的指针 <br>};&nbsp;&nbsp; <a href="http://www.cppblog.com/bourne/archive/2006/06/17/8678.aspx#post">回复</a>&nbsp; <a title="查看该作者发表过的评论" href="http://www.cppblog.com/comment?author=WR" target="_blank">更多评论</a><br></div></div></div></div></div></div></div></div></form><img src ="http://www.cppblog.com/woaidongmao/aggbug/60542.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/woaidongmao/" target="_blank">肥仔</a> 2008-08-31 21:58 <a href="http://www.cppblog.com/woaidongmao/archive/2008/08/31/60542.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>一个模板巧妙技术，语法技巧</title><link>http://www.cppblog.com/woaidongmao/archive/2008/08/31/60541.html</link><dc:creator>肥仔</dc:creator><author>肥仔</author><pubDate>Sun, 31 Aug 2008 13:57:00 GMT</pubDate><guid>http://www.cppblog.com/woaidongmao/archive/2008/08/31/60541.html</guid><wfw:comment>http://www.cppblog.com/woaidongmao/comments/60541.html</wfw:comment><comments>http://www.cppblog.com/woaidongmao/archive/2008/08/31/60541.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/woaidongmao/comments/commentRss/60541.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/woaidongmao/services/trackbacks/60541.html</trackback:ping><description><![CDATA[<form id="Form1" name="Form1" action="http://www.cppblog.com/5051.html" method="post" _initialAction="5051.html"> <div id="centercontent"> <div class="post"> <p>研究Boost前，想深入了解一下模板技术，找来一本书《C++ Template:The Complete Guide》研究。<br>里面有这样一个小技巧，判断一个类中是否有某种类形。下面是代码：(Win 2K+ VS2003)<br></p> <div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"> <span style="color: #000000">#include </span> <span style="color: #000000">&lt;</span> <span style="color: #000000">iostream</span> <span style="color: #000000">&gt;</span> <span style="color: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"> <br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"> </span><span style="color: #008000">//</span> <span style="color: #008000"> 返回类型,大小分别为1、2</span> <span style="color: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"> </span><span style="color: #000000">typedef </span> <span style="color: #0000ff">char</span> <span style="color: #000000"> RT1;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top">typedef </span> <span style="color: #0000ff">struct</span> <span style="color: #000000"><br><img id="Codehighlighter1_71_85_Open_Image" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top"> <img id="Codehighlighter1_71_85_Closed_Image" style="display: none" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align="top"> </span><span id="Codehighlighter1_71_85_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"> </span><span id="Codehighlighter1_71_85_Open_Text"><span style="color: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp; </span> <span style="color: #0000ff">char</span> <span style="color: #000000"> a[</span> <span style="color: #000000">2</span> <span style="color: #000000">];<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top">}</span> </span><span style="color: #000000"> RT2;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"></span> <span style="color: #008000">//</span> <span style="color: #008000"> 选择这个版本将返回char,大小为1</span> <span style="color: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"> </span><span style="color: #000000">template</span> <span style="color: #000000">&lt;</span> <span style="color: #000000">typename T</span> <span style="color: #000000">&gt;</span> <span style="color: #000000"> RT1 test(typename T::X </span> <span style="color: #0000ff">const</span> <span style="color: #000000">*</span> <span style="color: #000000">)<br><img id="Codehighlighter1_167_193_Open_Image" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top"><img id="Codehighlighter1_167_193_Closed_Image" style="display: none" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align="top"></span> <span id="Codehighlighter1_167_193_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"> </span><span id="Codehighlighter1_167_193_Open_Text"><span style="color: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp; </span> <span style="color: #0000ff">int</span> <span style="color: #000000">&nbsp;&nbsp;&nbsp; dumy&nbsp;&nbsp;&nbsp; </span> <span style="color: #000000">=</span> <span style="color: #000000">&nbsp;</span> <span style="color: #000000">0</span> <span style="color: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp; dumy</span> <span style="color: #000000">++</span> <span style="color: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top">}</span> </span><span style="color: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"> <br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"> </span><span style="color: #008000">//</span> <span style="color: #008000"> 选择这个版本将返回char,大小为2</span> <span style="color: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"> </span><span style="color: #000000">template</span> <span style="color: #000000">&lt;</span> <span style="color: #000000">typename T</span> <span style="color: #000000">&gt;</span> <span style="color: #000000"> RT2 test(<img src="http://www.cppblog.com/Images/dot.gif">)<br><img id="Codehighlighter1_253_279_Open_Image" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top"><img id="Codehighlighter1_253_279_Closed_Image" style="display: none" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align="top"></span> <span id="Codehighlighter1_253_279_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"> </span><span id="Codehighlighter1_253_279_Open_Text"><span style="color: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp; </span> <span style="color: #0000ff">int</span> <span style="color: #000000">&nbsp;&nbsp;&nbsp; dumy&nbsp;&nbsp;&nbsp; </span> <span style="color: #000000">=</span> <span style="color: #000000">&nbsp;</span> <span style="color: #000000">0</span> <span style="color: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp; dumy</span> <span style="color: #000000">++</span> <span style="color: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top">}</span> </span><span style="color: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"> <br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"> </span><span style="color: #008000">//</span> <span style="color: #008000"> 依靠编译器自动选择test函数,然后依据返回类型判断是否含有X</span> <span style="color: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"> </span><span style="color: #000000">template</span> <span style="color: #000000">&lt;</span> <span style="color: #000000">typename T</span> <span style="color: #000000">&gt;</span> <span style="color: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"> </span><span style="color: #0000ff">bool</span> <span style="color: #000000"> type_has_member_type_X()<br><img id="Codehighlighter1_369_441_Open_Image" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top"><img id="Codehighlighter1_369_441_Closed_Image" style="display: none" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align="top"></span> <span id="Codehighlighter1_369_441_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"> </span><span id="Codehighlighter1_369_441_Open_Text"><span style="color: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp; </span> <span style="color: #0000ff">return</span> <span style="color: #000000"> (</span> <span style="color: #0000ff">sizeof</span> <span style="color: #000000">(test</span> <span style="color: #000000">&lt;</span> <span style="color: #000000">T</span> <span style="color: #000000">&gt;</span> <span style="color: #000000">(</span> <span style="color: #000000">0</span> <span style="color: #000000">)) </span> <span style="color: #000000">==</span> <span style="color: #000000">&nbsp;</span> <span style="color: #000000">1</span> <span style="color: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top">}</span> </span><span style="color: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"> <br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"> </span><span style="color: #008000">//</span> <span style="color: #008000"> 有X类型的类</span> <span style="color: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"> </span><span style="color: #0000ff">class</span> <span style="color: #000000"> HasX<br><img id="Codehighlighter1_465_491_Open_Image" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top"><img id="Codehighlighter1_465_491_Closed_Image" style="display: none" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align="top"></span> <span id="Codehighlighter1_465_491_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"> </span><span id="Codehighlighter1_465_491_Open_Text"><span style="color: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top"></span> <span style="color: #0000ff">public</span> <span style="color: #000000">:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp; </span> <span style="color: #0000ff">class</span> <span style="color: #000000"> X<br><img id="Codehighlighter1_485_488_Open_Image" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"><img id="Codehighlighter1_485_488_Closed_Image" style="display: none" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align="top">&nbsp;&nbsp;&nbsp; </span> <span id="Codehighlighter1_485_488_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"> </span><span id="Codehighlighter1_485_488_Open_Text"><span style="color: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top">&nbsp;&nbsp;&nbsp; }</span> </span><span style="color: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top">}</span> </span><span style="color: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"></span> <span style="color: #008000">//</span> <span style="color: #008000"> 无X类型的类</span> <span style="color: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"> </span><span style="color: #0000ff">class</span> <span style="color: #000000"> NonX<br><img id="Codehighlighter1_516_542_Open_Image" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top"><img id="Codehighlighter1_516_542_Closed_Image" style="display: none" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align="top"></span> <span id="Codehighlighter1_516_542_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"> </span><span id="Codehighlighter1_516_542_Open_Text"><span style="color: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top"></span> <span style="color: #0000ff">public</span> <span style="color: #000000">:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp; </span> <span style="color: #0000ff">class</span> <span style="color: #000000"> Y<br><img id="Codehighlighter1_536_539_Open_Image" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"><img id="Codehighlighter1_536_539_Closed_Image" style="display: none" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align="top">&nbsp;&nbsp;&nbsp; </span> <span id="Codehighlighter1_536_539_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"> </span><span id="Codehighlighter1_536_539_Open_Text"><span style="color: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top">&nbsp;&nbsp;&nbsp; }</span> </span><span style="color: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top">}</span> </span><span style="color: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"></span> <span style="color: #0000ff">int</span> <span style="color: #000000"> _tmain(</span> <span style="color: #0000ff">int</span> <span style="color: #000000"> argc, _TCHAR</span> <span style="color: #000000">*</span> <span style="color: #000000"> argv[])<br><img id="Codehighlighter1_583_934_Open_Image" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top"><img id="Codehighlighter1_583_934_Closed_Image" style="display: none" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align="top"></span> <span id="Codehighlighter1_583_934_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"> </span><span id="Codehighlighter1_583_934_Open_Text"><span style="color: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp; </span> <span style="color: #008000">//</span> <span style="color: #008000"> 编译器选择重载函数策略:选择类型最匹配版本<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp; </span> <span style="color: #008000">//</span> <span style="color: #008000"> 倾向于把0转化为常量空指针,所以选择返回为RT1版本</span> <span style="color: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top"> </span><span style="color: #000000">&nbsp;&nbsp;&nbsp; </span> <span style="color: #0000ff">if</span> <span style="color: #000000">(type_has_member_type_X</span> <span style="color: #000000">&lt;</span> <span style="color: #000000">HasX</span> <span style="color: #000000">&gt;</span> <span style="color: #000000">())<br><img id="Codehighlighter1_679_719_Open_Image" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"><img id="Codehighlighter1_679_719_Closed_Image" style="display: none" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align="top">&nbsp;&nbsp;&nbsp; </span> <span id="Codehighlighter1_679_719_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"> </span><span id="Codehighlighter1_679_719_Open_Text"><span style="color: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; std::cout </span> <span style="color: #000000">&lt;&lt;</span> <span style="color: #000000">&nbsp;</span> <span style="color: #000000">"</span> <span style="color: #000000">Has X</span> <span style="color: #000000">"</span> <span style="color: #000000">&nbsp;</span> <span style="color: #000000">&lt;&lt;</span> <span style="color: #000000"> std::endl;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top">&nbsp;&nbsp;&nbsp; }</span> </span><span style="color: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp; </span> <span style="color: #0000ff">else</span> <span style="color: #000000"><br><img id="Codehighlighter1_728_768_Open_Image" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"> <img id="Codehighlighter1_728_768_Closed_Image" style="display: none" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align="top">&nbsp;&nbsp;&nbsp; </span> <span id="Codehighlighter1_728_768_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"> </span><span id="Codehighlighter1_728_768_Open_Text"><span style="color: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; std::cout </span> <span style="color: #000000">&lt;&lt;</span> <span style="color: #000000">&nbsp;</span> <span style="color: #000000">"</span> <span style="color: #000000">Non X</span> <span style="color: #000000">"</span> <span style="color: #000000">&nbsp;</span> <span style="color: #000000">&lt;&lt;</span> <span style="color: #000000"> std::endl;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top">&nbsp;&nbsp;&nbsp; }</span> </span><span style="color: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top"> <br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp; </span> <span style="color: #008000">//</span> <span style="color: #008000"> 没有T::X,所以选择返回为RT2版本</span> <span style="color: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top"> </span><span style="color: #000000">&nbsp;&nbsp;&nbsp; </span> <span style="color: #0000ff">if</span> <span style="color: #000000">(type_has_member_type_X</span> <span style="color: #000000">&lt;</span> <span style="color: #000000">NonX</span> <span style="color: #000000">&gt;</span> <span style="color: #000000">())<br><img id="Codehighlighter1_832_872_Open_Image" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"><img id="Codehighlighter1_832_872_Closed_Image" style="display: none" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align="top">&nbsp;&nbsp;&nbsp; </span> <span id="Codehighlighter1_832_872_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"> </span><span id="Codehighlighter1_832_872_Open_Text"><span style="color: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; std::cout </span> <span style="color: #000000">&lt;&lt;</span> <span style="color: #000000">&nbsp;</span> <span style="color: #000000">"</span> <span style="color: #000000">Has X</span> <span style="color: #000000">"</span> <span style="color: #000000">&nbsp;</span> <span style="color: #000000">&lt;&lt;</span> <span style="color: #000000"> std::endl;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top">&nbsp;&nbsp;&nbsp; }</span> </span><span style="color: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp; </span> <span style="color: #0000ff">else</span> <span style="color: #000000"><br><img id="Codehighlighter1_881_921_Open_Image" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"> <img id="Codehighlighter1_881_921_Closed_Image" style="display: none" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align="top">&nbsp;&nbsp;&nbsp; </span> <span id="Codehighlighter1_881_921_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"> </span><span id="Codehighlighter1_881_921_Open_Text"><span style="color: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; std::cout </span> <span style="color: #000000">&lt;&lt;</span> <span style="color: #000000">&nbsp;</span> <span style="color: #000000">"</span> <span style="color: #000000">Non X</span> <span style="color: #000000">"</span> <span style="color: #000000">&nbsp;</span> <span style="color: #000000">&lt;&lt;</span> <span style="color: #000000"> std::endl;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top">&nbsp;&nbsp;&nbsp; }</span> </span><span style="color: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp; </span> <span style="color: #0000ff">return</span> <span style="color: #000000">&nbsp;</span> <span style="color: #000000">0</span> <span style="color: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top">}</span> </span></div>输出结果:<br>Has X<br>Non X  <div class="postDesc">posted on 2006-04-05 22:26 <a href="http://www.cppblog.com/wlwlxj/">万连文</a> 阅读(539) <a href="http://www.cppblog.com/#Post">评论(3)</a>&nbsp; <a href="http://www.cppblog.com/wlwlxj/admin/EditPosts.aspx?postid=5051">编辑</a>&nbsp;<a href="http://www.cppblog.com/wlwlxj/AddToFavorite.aspx?id=5051">收藏</a> <a href="http://www.cppblog.com/wlwlxj/services/trackbacks/5051.aspx">引用</a> 所属分类: <a href="http://www.cppblog.com/wlwlxj/category/1324.html">模板</a> </div></div><img height="1" src="http://www.cppblog.com/wlwlxj/aggbug/5051.html?webview=1" width="1">  <div id="AjaxHolder_UpdatePanel1"><a name="pagedcomment"></a><br><b>FeedBack:</b>  <div class="feedbackNoItems"></div> <div class="feedbackItem"> <div class="feedbackListTitle"><a title="permalink: re: 一个模板巧妙技术，语法技巧" href="http://www.cppblog.com/wlwlxj/archive/2006/04/05/5051.html#5055">#</a>&nbsp;<a name="5055"></a>re: 一个模板巧妙技术，语法技巧</div> <div class="feedbackListSubtitle">2006-04-06 00:23 | <a id="AjaxHolder_Comments_CommentList_ctl00_NameLink" target="_blank">dicklee</a><br> <div align="left">有个瑕疵，X若为引用类型则会返回不期望的值，例如： <br>class HasX <br>{ <br>public: <br>typedef int&amp; X; <br>}; <br>type_has_member_type_X &lt; HasX &gt;() <br>将返回false，类型和特征萃取时，引用类型总是比较麻烦，呵呵&nbsp; <a href="http://www.cppblog.com/wlwlxj/archive/2006/04/05/5051.html#post">回复</a>&nbsp; <a title="查看该作者发表过的评论" href="http://www.cppblog.com/comment?author=dicklee" target="_blank">更多评论</a><br><a id="AjaxHolder_Comments_CommentList_ctl00_DeleteLink" href="http://www.cppblog.com/"></a>&nbsp; <a id="AjaxHolder_Comments_CommentList_ctl00_EditLink"></a></div></div></div> <div class="feedbackItem"> <div class="feedbackListTitle"><a title="permalink: re: 一个模板巧妙技术，语法技巧" href="http://www.cppblog.com/wlwlxj/archive/2006/04/05/5051.html#5096">#</a>&nbsp;<a name="5096"></a>re: 一个模板巧妙技术，语法技巧</div> <div class="feedbackListSubtitle">2006-04-06 13:52 | <a id="AjaxHolder_Comments_CommentList_ctl01_NameLink" href="http://www.cppblog.com/wlwlxj/" target="_blank">万连文</a><br> <div align="left">@dicklee <br>不错，看来上面对模板了解深啊，现在才发现自己对编译器了解甚少！&nbsp; <a href="http://www.cppblog.com/wlwlxj/archive/2006/04/05/5051.html#post">回复</a>&nbsp; <a title="查看该作者发表过的评论" href="http://www.cppblog.com/comment?author=%e4%b8%87%e8%bf%9e%e6%96%87" target="_blank">更多评论</a><br><a id="AjaxHolder_Comments_CommentList_ctl01_DeleteLink" href="http://www.cppblog.com/"></a>&nbsp; <a id="AjaxHolder_Comments_CommentList_ctl01_EditLink"></a></div></div></div> <div class="feedbackItem"> <div class="feedbackListTitle"><a title="permalink: re: 一个模板巧妙技术，语法技巧" href="http://www.cppblog.com/wlwlxj/archive/2006/04/05/5051.html#30995">#</a>&nbsp;<a name="30995"></a>re: 一个模板巧妙技术，语法技巧<a name="Post"></a></div> <div class="feedbackListSubtitle">2007-08-28 09:49 | <a id="AjaxHolder_Comments_CommentList_ctl02_NameLink" target="_blank">100000</a><br> <div align="left">typedef char RT1; <br>typedef struct <br>{ <br>char a[ 2 ]; <br>} RT2; <br><br>template &lt; typename T &gt; <br>class NonRef{ <br><br>public: <br><br>typedef T NonRefX; <br><br>}; <br><br>template &lt; typename T &gt; <br>class NonRef&lt; T&amp; &gt;{ <br><br>public: <br><br>typedef T NonRefX; <br><br>}; <br><br>// 选择这个版本将返回char,大小为1 <br>template &lt; typename T &gt; RT1 test( typename NonRef&lt; typename T::X &gt;::NonRefX const * ) <br>{ <br>int dumy = 0 ; <br>dumy ++ ; <br>} <br><br><br>// 选择这个版本将返回char,大小为2 <br>template &lt; typename T &gt; RT2 test(...) <br>{ <br>int dumy = 0 ; <br>dumy ++ ; <br>} <br><br>// 依靠编译器自动选择test函数,然后依据返回类型判断是否含有X <br>template &lt; typename T &gt; <br>bool type_has_member_type_X() <br>{ <br>return ( sizeof (test &lt; T &gt; ( 0 )) == 1 ); <br>} <br><br>// 有X类型的类 <br>class HasX <br>{ <br>public : <br><br>typedef int&amp; X; <br><br>} ; <br><br>// 无X类型的类 <br>class NonX <br>{ <br>public : <br>class Y <br>{ <br>} ; <br>} ; <br><br><br>int _tmain(int argc, _TCHAR* argv[]) <br>{ <br>// 编译器选择重载函数策略:选择类型最匹配版本 <br>// 倾向于把0转化为常量空指针,所以选择返回为RT1版本 <br><br>if (type_has_member_type_X &lt; HasX &gt; ()) <br>{ <br>std::cout &lt;&lt; " Has X " &lt;&lt; std::endl; <br>} <br>else <br>{ <br>std::cout &lt;&lt; " Non X " &lt;&lt; std::endl; <br>} <br><br>// 没有T::X,所以选择返回为RT2版本 <br>if (type_has_member_type_X &lt; NonX &gt; ()) <br>{ <br>std::cout &lt;&lt; " Has X " &lt;&lt; std::endl; <br>} <br>else <br>{ <br>std::cout &lt;&lt; " Non X " &lt;&lt; std::endl; <br>} <br><br><br>return 0; <br>} <br>&nbsp; <a href="http://www.cppblog.com/wlwlxj/archive/2006/04/05/5051.html#post">回复</a>&nbsp; <a title="查看该作者发表过的评论" href="http://www.cppblog.com/comment?author=100000" target="_blank">更多评论</a><br></div></div></div></div></div></form><img src ="http://www.cppblog.com/woaidongmao/aggbug/60541.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/woaidongmao/" target="_blank">肥仔</a> 2008-08-31 21:57 <a href="http://www.cppblog.com/woaidongmao/archive/2008/08/31/60541.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于模板的类型参数</title><link>http://www.cppblog.com/woaidongmao/archive/2008/08/31/60539.html</link><dc:creator>肥仔</dc:creator><author>肥仔</author><pubDate>Sun, 31 Aug 2008 13:55:00 GMT</pubDate><guid>http://www.cppblog.com/woaidongmao/archive/2008/08/31/60539.html</guid><wfw:comment>http://www.cppblog.com/woaidongmao/comments/60539.html</wfw:comment><comments>http://www.cppblog.com/woaidongmao/archive/2008/08/31/60539.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/woaidongmao/comments/commentRss/60539.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/woaidongmao/services/trackbacks/60539.html</trackback:ping><description><![CDATA[<form id="Form1" name="Form1" action="http://www.cppblog.com/490.aspx" method="post" _initialAction="490.aspx"> <div id="main"> <div class="post"> <div class="postText"><font face="Verdana" size="2">看了cpunion写的IDL的代码,我知道了这样的用法:<br>在模板参数中,类型参数可以这样构造:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; template_class&lt; type( type1, type2, ... ) &gt; a_class;<br>比如,可以void( void ), void(), void( int ), 也可以int( void ), string( int )等等,编译器是将它们当作不同的类型的来处理的.对此,我写了一些代码作了一下测试(见文末).但我也仅仅是有一个感性的认识而已,对于其为什么可以这样(因为从未见哪本书上介绍过这样的用法),我一点也不知道.<br>希望大家帮我释疑,也希望cpunion来帮我一下,谢谢!<br><br> <div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"><span style="color: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top">#include </span><span style="color: #000000">&lt;</span><span style="color: #000000">iostream</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top">typedef </span><span style="color: #0000ff">void</span><span style="color: #000000">(</span><span style="color: #000000">*</span><span style="color: #000000">fun)(</span><span style="color: #0000ff">int</span><span style="color: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"></span><span style="color: #0000ff">using</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">namespace</span><span style="color: #000000"> std;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top">template</span><span style="color: #000000">&lt;</span><span style="color: #000000">&nbsp;<font color="#0000ff">typename</font> T </span><span style="color: #000000">&gt;</span><span style="color: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"></span><span style="color: #0000ff">struct</span><span style="color: #000000"> Base<br><img id="Codehighlighter1_105_214_Open_Image" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top"><img id="Codehighlighter1_105_214_Closed_Image" style="display: none" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align="top"></span><span id="Codehighlighter1_105_214_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id="Codehighlighter1_105_214_Open_Text"><span style="color: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff">void</span><span style="color: #000000"> test()<br><img id="Codehighlighter1_121_212_Open_Image" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"><img id="Codehighlighter1_121_212_Closed_Image" style="display: none" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align="top">&nbsp;&nbsp;&nbsp; </span><span id="Codehighlighter1_121_212_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id="Codehighlighter1_121_212_Open_Text"><span style="color: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cout </span><span style="color: #000000">&lt;&lt;</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">Base<t></span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">&lt;&lt;</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">\t=\t</span><span style="color: #000000">"</span><span style="color: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cout </span><span style="color: #000000">&lt;&lt;</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">Base&lt;</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">&lt;&lt;</span><span style="color: #000000">&nbsp;<font color="#0000ff">typeid</font>(T).name() </span><span style="color: #000000">&lt;&lt;</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">&gt;</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">&lt;&lt;</span><span style="color: #000000"> endl;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top">&nbsp;&nbsp;&nbsp; }</span></span><span style="color: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top">}</span></span><span style="color: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top">template</span><span style="color: #000000">&lt;&gt;</span><span style="color: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"></span><span style="color: #0000ff">struct</span><span style="color: #000000"> Base </span><span style="color: #000000">&lt;</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br><img id="Codehighlighter1_250_303_Open_Image" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top"><img id="Codehighlighter1_250_303_Closed_Image" style="display: none" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align="top"></span><span id="Codehighlighter1_250_303_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id="Codehighlighter1_250_303_Open_Text"><span style="color: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff">void</span><span style="color: #000000"> test()<br><img id="Codehighlighter1_266_301_Open_Image" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"><img id="Codehighlighter1_266_301_Closed_Image" style="display: none" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align="top">&nbsp;&nbsp;&nbsp; </span><span id="Codehighlighter1_266_301_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id="Codehighlighter1_266_301_Open_Text"><span style="color: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cout </span><span style="color: #000000">&lt;&lt;</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">Base<void></span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">&lt;&lt;</span><span style="color: #000000"> endl;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top">&nbsp;&nbsp;&nbsp; }</span></span><span style="color: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top">}</span></span><span style="color: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top">template</span><span style="color: #000000">&lt;&gt;</span><span style="color: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"></span><span style="color: #0000ff">struct</span><span style="color: #000000"> Base </span><span style="color: #000000">&lt;</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">( </span><span style="color: #0000ff">int</span><span style="color: #000000"> ) </span><span style="color: #000000">&gt;</span><span style="color: #000000"><br><img id="Codehighlighter1_346_404_Open_Image" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top"><img id="Codehighlighter1_346_404_Closed_Image" style="display: none" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align="top"></span><span id="Codehighlighter1_346_404_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id="Codehighlighter1_346_404_Open_Text"><span style="color: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff">void</span><span style="color: #000000"> test()<br><img id="Codehighlighter1_362_402_Open_Image" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"><img id="Codehighlighter1_362_402_Closed_Image" style="display: none" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align="top">&nbsp;&nbsp;&nbsp; </span><span id="Codehighlighter1_362_402_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id="Codehighlighter1_362_402_Open_Text"><span style="color: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cout </span><span style="color: #000000">&lt;&lt;</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">Base<void (INT)></span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">&lt;&lt;</span><span style="color: #000000"> endl;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top">&nbsp;&nbsp;&nbsp; }</span></span><span style="color: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top">}</span></span><span style="color: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top">template</span><span style="color: #000000">&lt;&gt;</span><span style="color: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"></span><span style="color: #0000ff">struct</span><span style="color: #000000"> Base </span><span style="color: #000000">&lt;</span><span style="color: #000000"> fun </span><span style="color: #000000">&gt;</span><span style="color: #000000"><br><img id="Codehighlighter1_439_491_Open_Image" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top"><img id="Codehighlighter1_439_491_Closed_Image" style="display: none" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align="top"></span><span id="Codehighlighter1_439_491_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id="Codehighlighter1_439_491_Open_Text"><span style="color: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff">void</span><span style="color: #000000"> test()<br><img id="Codehighlighter1_455_489_Open_Image" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"><img id="Codehighlighter1_455_489_Closed_Image" style="display: none" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align="top">&nbsp;&nbsp;&nbsp; </span><span id="Codehighlighter1_455_489_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id="Codehighlighter1_455_489_Open_Text"><span style="color: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cout </span><span style="color: #000000">&lt;&lt;</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">Base<fun></span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">&lt;&lt;</span><span style="color: #000000"> endl;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top">&nbsp;&nbsp;&nbsp; }</span></span><span style="color: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top">}</span></span><span style="color: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top">template</span><span style="color: #000000">&lt;&gt;</span><span style="color: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"></span><span style="color: #0000ff">struct</span><span style="color: #000000"> Base </span><span style="color: #000000">&lt;</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">( </span><span style="color: #0000ff">string</span><span style="color: #000000">, </span><span style="color: #0000ff">int</span><span style="color: #000000">, </span><span style="color: #0000ff">char</span><span style="color: #000000"> ) </span><span style="color: #000000">&gt;</span><span style="color: #000000"><br><img id="Codehighlighter1_547_616_Open_Image" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top"><img id="Codehighlighter1_547_616_Closed_Image" style="display: none" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align="top"></span><span id="Codehighlighter1_547_616_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id="Codehighlighter1_547_616_Open_Text"><span style="color: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff">void</span><span style="color: #000000"> test()<br><img id="Codehighlighter1_563_614_Open_Image" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"><img id="Codehighlighter1_563_614_Closed_Image" style="display: none" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align="top">&nbsp;&nbsp;&nbsp; </span><span id="Codehighlighter1_563_614_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id="Codehighlighter1_563_614_Open_Text"><span style="color: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cout </span><span style="color: #000000">&lt;&lt;</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">Base<int (STRING,INT,CHAR)></span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">&lt;&lt;</span><span style="color: #000000"> endl;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top">&nbsp;&nbsp;&nbsp; }</span></span><span style="color: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top">}</span></span><span style="color: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"></span><span style="color: #0000ff">int</span><span style="color: #000000"> main(</span><span style="color: #0000ff">int</span><span style="color: #000000"> argc, </span><span style="color: #0000ff">char</span><span style="color: #000000">*</span><span style="color: #000000"> argv[])<br><img id="Codehighlighter1_653_943_Open_Image" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top"><img id="Codehighlighter1_653_943_Closed_Image" style="display: none" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align="top"></span><span id="Codehighlighter1_653_943_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id="Codehighlighter1_653_943_Open_Text"><span style="color: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp; Base</span><span style="color: #000000">&lt;</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">&gt;</span><span style="color: #000000"> b_void;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp; Base</span><span style="color: #000000">&lt;</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">( </span><span style="color: #0000ff">int</span><span style="color: #000000"> ) </span><span style="color: #000000">&gt;</span><span style="color: #000000"> b_void_int;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp; b_void.test();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp; b_void_int.test();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp; Base</span><span style="color: #000000">&lt;</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">( </span><span style="color: #0000ff">string</span><span style="color: #000000">, </span><span style="color: #0000ff">int</span><span style="color: #000000">, </span><span style="color: #0000ff">char</span><span style="color: #000000"> ) </span><span style="color: #000000">&gt;</span><span style="color: #000000"> b_int;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp; Base</span><span style="color: #000000">&lt;</span><span style="color: #000000"> fun </span><span style="color: #000000">&gt;</span><span style="color: #000000"> b_fun;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp; b_int.test();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp; b_fun.test();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp; Base</span><span style="color: #000000">&lt;</span><span style="color: #000000"> Base</span><span style="color: #000000">&lt;</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">&gt;</span><span style="color: #000000"> ( Base </span><span style="color: #000000">&lt;</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000"> ( </span><span style="color: #0000ff">string</span><span style="color: #000000">, </span><span style="color: #0000ff">int</span><span style="color: #000000">, </span><span style="color: #0000ff">char</span><span style="color: #000000"> ) </span><span style="color: #000000">&gt;</span><span style="color: #000000"> ) </span><span style="color: #000000">&gt;</span><span style="color: #000000"> b_complex;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp; b_complex.test();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top">}</span></span><span style="color: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"></span></div></font></div> <div class="postfoot">posted on 2005-09-29 19:51 <a href="http://www.cppblog.com/kb/">可冰</a> 阅读(757) <a href="http://www.cppblog.com/#Post">评论(9)</a>&nbsp; <a href="http://www.cppblog.com/kb/admin/EditPosts.aspx?postid=490">编辑</a>&nbsp;<a href="http://www.cppblog.com/kb/AddToFavorite.aspx?id=490">收藏</a> <a href="http://www.cppblog.com/kb/services/trackbacks/490.aspx">引用</a> 所属分类: <a href="http://www.cppblog.com/kb/category/53.html">C++</a> </div></div><img height="1" src="http://www.cppblog.com/kb/aggbug/490.html?webview=1" width="1">  <div id="AjaxHolder_UpdatePanel1"><a name="pagedcomment"></a><a name="评论"><br> <div id="comments"> <h3>评论</h3> <div class="post"> <div class="postTitle"><a title="permalink: re: 关于模板的类型参数" href="http://www.cppblog.com/kb/archive/2005/09/29/490.aspx#492">#</a>&nbsp;<a name="492"></a>re: 关于模板的类型参数 <span>2005-09-29 21:16 </span><a id="AjaxHolder_Comments_CommentList_ctl00_NameLink" href="http://www.cppblog.com/cpunion" target="_blank">cpunion</a> </div> <div class="postText">模板的类型参数，只要是类型都是可以接受的。 <br><br>template &lt;class T&gt; <br>class Base <br>{ <br>}; <br>定义了一个类模板，后面都是它的偏特化。 <br><br>你的疑问应该是void(*)(int)类型和void(int)类型的区别吧？ <br><br>void(int)是一个函数类型，void(*)(int)是一个函数指针类型，函数类型仅在声明时有效，当把void(int)类型的函数作为一个值来传递时，它自动退化为void(*)(int)指针类型。 <br><br>关于这一点，最好是看刘未鹏对于boost::function源代码的解释，我也是从这里才知道有这种用法的。&nbsp; <a href="http://www.cppblog.com/kb/archive/2005/09/29/490.aspx#post">回复</a>&nbsp; <a title="查看该作者发表过的评论" href="http://www.cppblog.com/comment?author=cpunion" target="_blank">更多评论</a> <br><a id="AjaxHolder_Comments_CommentList_ctl00_DeleteLink" href="http://www.cppblog.com/"></a>&nbsp; <a id="AjaxHolder_Comments_CommentList_ctl00_EditLink"></a> </div></div><br> <div class="post"> <div class="postTitle"><a title="permalink: re: 关于模板的类型参数" href="http://www.cppblog.com/kb/archive/2005/09/29/490.aspx#493">#</a>&nbsp;<a name="493"></a>re: 关于模板的类型参数 <span>2005-09-29 21:23 </span><a id="AjaxHolder_Comments_CommentList_ctl01_NameLink" target="_blank">函数类型</a> </div> <div class="postText">void Fun(int); <br>cout &lt;&lt; typeid(void(int)).name() &lt;&lt; endl; <br>cout &lt;&lt; typeid(Fun).name() &lt;&lt; endl; <br>&nbsp; <a href="http://www.cppblog.com/kb/archive/2005/09/29/490.aspx#post">回复</a>&nbsp; <a title="查看该作者发表过的评论" href="http://www.cppblog.com/comment?author=%e5%87%bd%e6%95%b0%e7%b1%bb%e5%9e%8b" target="_blank">更多评论</a> <br><a id="AjaxHolder_Comments_CommentList_ctl01_DeleteLink" href="http://www.cppblog.com/"></a>&nbsp; <a id="AjaxHolder_Comments_CommentList_ctl01_EditLink"></a> </div></div><br> <div class="post"> <div class="postTitle"><a title="permalink: re: 关于模板的类型参数" href="http://www.cppblog.com/kb/archive/2005/09/29/490.aspx#495">#</a>&nbsp;<a name="495"></a>re: 关于模板的类型参数 <span>2005-09-29 21:39 </span><a id="AjaxHolder_Comments_CommentList_ctl02_NameLink" href="http://www.cppblog.com/cpunion" target="_blank">cpunion</a> </div> <div class="postText">typeid, sizeof, typeof(c++0x)都不取表达式的值，只提取类型。&nbsp; <a href="http://www.cppblog.com/kb/archive/2005/09/29/490.aspx#post">回复</a>&nbsp; <a title="查看该作者发表过的评论" href="http://www.cppblog.com/comment?author=cpunion" target="_blank">更多评论</a> <br><a id="AjaxHolder_Comments_CommentList_ctl02_DeleteLink" href="http://www.cppblog.com/"></a>&nbsp; <a id="AjaxHolder_Comments_CommentList_ctl02_EditLink"></a> </div></div><br> <div class="post"> <div class="postTitle"><a title="permalink: re: 关于模板的类型参数" href="http://www.cppblog.com/kb/archive/2005/09/29/490.aspx#496">#</a>&nbsp;<a name="496"></a>re: 关于模板的类型参数 <span>2005-09-29 22:57 </span><a id="AjaxHolder_Comments_CommentList_ctl03_NameLink" href="http://www.cppblog.com/kb/" target="_blank">可冰</a> </div> <div class="postText">void(int)原来是函数类型啊!从来没有见到过这样的类型啊. <br>你所说的"当把void(int)类型的函数作为一个值来传递时，它自动退化为void(*)(int)指针类型。"应该是指,用它来定义变量的时候,这个变量就成了函数指针类型的了?&nbsp; <a href="http://www.cppblog.com/kb/archive/2005/09/29/490.aspx#post">回复</a>&nbsp; <a title="查看该作者发表过的评论" href="http://www.cppblog.com/comment?author=%e5%8f%af%e5%86%b0" target="_blank">更多评论</a> <br><a id="AjaxHolder_Comments_CommentList_ctl03_DeleteLink" href="http://www.cppblog.com/"></a>&nbsp; <a id="AjaxHolder_Comments_CommentList_ctl03_EditLink"></a> </div></div><br> <div class="post"> <div class="postTitle"><a title="permalink: re: 关于模板的类型参数" href="http://www.cppblog.com/kb/archive/2005/09/29/490.aspx#499">#</a>&nbsp;<a name="499"></a>re: 关于模板的类型参数 <span>2005-09-29 23:08 </span><a id="AjaxHolder_Comments_CommentList_ctl04_NameLink" href="http://www.cppblog.com/cpunion" target="_blank">cpunion</a> </div> <div class="postText">函数类型可以用做声明，也可以表示函数代码块，不能直接用它声明一个变量，所以很少见。 <br><br>比如函数： <br><br>void func(int) <br>{ <br>} <br><br>func本身是函数类型，不过当作值来传递给一个void(*)(int)类型指针时，自动退化为指针类型，所以不需要加上&amp;符号，加上&amp;也是合法的。 <br><br>使用typeid, typeof都可以获取到函数类型。&nbsp; <a href="http://www.cppblog.com/kb/archive/2005/09/29/490.aspx#post">回复</a>&nbsp; <a title="查看该作者发表过的评论" href="http://www.cppblog.com/comment?author=cpunion" target="_blank">更多评论</a> <br><a id="AjaxHolder_Comments_CommentList_ctl04_DeleteLink" href="http://www.cppblog.com/"></a>&nbsp; <a id="AjaxHolder_Comments_CommentList_ctl04_EditLink"></a> </div></div><br> <div class="post"> <div class="postTitle"><a title="permalink: re: 关于模板的类型参数" href="http://www.cppblog.com/kb/archive/2005/09/29/490.aspx#500">#</a>&nbsp;<a name="500"></a>re: 关于模板的类型参数 <span>2005-09-29 23:11 </span><a id="AjaxHolder_Comments_CommentList_ctl05_NameLink" href="http://www.cppblog.com/kb/" target="_blank">可冰</a> </div> <div class="postText">我在模板中试了一下,确实用函数类型定义的变量成为了函数指针类型. <br>定义为: T var; <br>输出为: var: void (__thiscall Base&lt;void __cdecl(int)&gt;::*)(int) <br>T : void __cdecl(int) <br><br>但是在外部,定义这样的一个类型及变量: <br>typedef void MethodType (int); <br>MethodType method; <br><br>它们的类型居然是一样的,method在这儿并没有转化为函数指针类型. <br>输出类型如下: <br>void __cdecl(int) <br>void __cdecl(int) <br><br>这又是怎么回事?&nbsp; <a href="http://www.cppblog.com/kb/archive/2005/09/29/490.aspx#post">回复</a>&nbsp; <a title="查看该作者发表过的评论" href="http://www.cppblog.com/comment?author=%e5%8f%af%e5%86%b0" target="_blank">更多评论</a> <br><a id="AjaxHolder_Comments_CommentList_ctl05_DeleteLink" href="http://www.cppblog.com/"></a>&nbsp; <a id="AjaxHolder_Comments_CommentList_ctl05_EditLink"></a> </div></div><br> <div class="post"> <div class="postTitle"><a title="permalink: re: 关于模板的类型参数" href="http://www.cppblog.com/kb/archive/2005/09/29/490.aspx#504">#</a>&nbsp;<a name="504"></a>re: 关于模板的类型参数 <span>2005-09-29 23:40 </span><a id="AjaxHolder_Comments_CommentList_ctl06_NameLink" href="http://www.cppblog.com/cpunion" target="_blank">cpunion</a> </div> <div class="postText">在g++编译器下，T var;是不能编译通过的。 <br><br>typedef void MethodType (int); <br>MethodType method; <br><br>这个定义确实能够通过编译（我以前没这么测试过），因为method的是函数类型，而它没有实际定义，相当于写了一个函数声明，所以如果调用它，链接器将报错。 <br><br>这个功能本来是开放给编译器使用的，所以虽然能够定义，但无法操作它，你无法对它使用sizeof，无法对它取地址，只能对它使用typeid获取类型信息、使用typeof获取它的类型。 <br><br>int m; <br>typedef void MethodType (int); <br>MethodType method; <br>int n; <br><br>测试可以知道，n和m的地址相差是4字节（32位平台上），method并不真的定义了一个变量。 <br><br>应该是C＋＋给编译器定的标准，相当诡异。。&nbsp; <a href="http://www.cppblog.com/kb/archive/2005/09/29/490.aspx#post">回复</a>&nbsp; <a title="查看该作者发表过的评论" href="http://www.cppblog.com/comment?author=cpunion" target="_blank">更多评论</a> <br><a id="AjaxHolder_Comments_CommentList_ctl06_DeleteLink" href="http://www.cppblog.com/"></a>&nbsp; <a id="AjaxHolder_Comments_CommentList_ctl06_EditLink"></a> </div></div><br> <div class="post"> <div class="postTitle"><a title="permalink: re: 关于模板的类型参数" href="http://www.cppblog.com/kb/archive/2005/09/29/490.aspx#505">#</a>&nbsp;<a name="505"></a>re: 关于模板的类型参数 <span>2005-09-30 01:59 </span><a id="AjaxHolder_Comments_CommentList_ctl07_NameLink" target="_blank">说得对，仅仅是申明</a> </div> <div class="postText">typedef void MethodType (int); <br>MethodType method; <br>和 <br>extern void method(int); <br>基本上一样，另外，加上定义 <br>void method(int) <br>{ <br>} <br>可以 <br>method(0); <br>这样用了 <br>&nbsp; <a href="http://www.cppblog.com/kb/archive/2005/09/29/490.aspx#post">回复</a>&nbsp; <a title="查看该作者发表过的评论" href="http://www.cppblog.com/comment?author=%e8%af%b4%e5%be%97%e5%af%b9%ef%bc%8c%e4%bb%85%e4%bb%85%e6%98%af%e7%94%b3%e6%98%8e" target="_blank">更多评论</a> <br><a id="AjaxHolder_Comments_CommentList_ctl07_DeleteLink" href="http://www.cppblog.com/"></a>&nbsp; <a id="AjaxHolder_Comments_CommentList_ctl07_EditLink"></a> </div></div><br> <div class="post"> <div class="postTitle"><a title="permalink: re: 关于模板的类型参数" href="http://www.cppblog.com/kb/archive/2005/09/29/490.aspx#518">#</a>&nbsp;<a name="518"></a>re: 关于模板的类型参数<a name="Post"></a> <span>2005-09-30 20:51 </span><a id="AjaxHolder_Comments_CommentList_ctl08_NameLink" href="http://www.cppblog.com/kb/" target="_blank">可冰</a> </div> <div class="postText">[摘录]Boost源码剖析之:泛型函数指针类boost::function(修订版) <br>刘未鹏 /文 <br><br>或许你会对模板参数int(int)感到陌生，其实它是个函数型别——函数g的确切型别就是int(int)，而我们通常所看到的函数指针型别int (*)(int)则是&amp;g的型别。它们的区别与联系在于：当把g作为一个值进行拷贝的时候（例如，按值传参），其类型就会由int(int)退化为int(*)(int)，即从函数类型退化为函数指针类型——因为从语义上说，函数不能被“按值拷贝”，但身为函数指针的地址值则是可以被拷贝的。另一方面，如果g被绑定到引用，则其类型不会退化，仍保持函数类型。 <br>...... <br>请注意，函数类型乃是个极其特殊的类型，在大多数时候它都会退化为函数指针类型，以便满足拷贝语义，只有面对引用绑定的时候，能够维持原来的类型。当然，对于boost::function，总是按值拷贝。&nbsp; <a href="http://www.cppblog.com/kb/archive/2005/09/29/490.aspx#post">回复</a>&nbsp; <a title="查看该作者发表过的评论" href="http://www.cppblog.com/comment?author=%e5%8f%af%e5%86%b0" target="_blank">更多评论</a> <br><a id="AjaxHolder_Comments_CommentList_ctl08_DeleteLink" href="http://www.cppblog.com/"></a>&nbsp; <a id="AjaxHolder_Comments_CommentList_ctl08_EditLink"></a> </div></div></div></div></div></form><img src ="http://www.cppblog.com/woaidongmao/aggbug/60539.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/woaidongmao/" target="_blank">肥仔</a> 2008-08-31 21:55 <a href="http://www.cppblog.com/woaidongmao/archive/2008/08/31/60539.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>抑制模板代码膨胀的一种技术</title><link>http://www.cppblog.com/woaidongmao/archive/2008/08/31/60538.html</link><dc:creator>肥仔</dc:creator><author>肥仔</author><pubDate>Sun, 31 Aug 2008 13:54:00 GMT</pubDate><guid>http://www.cppblog.com/woaidongmao/archive/2008/08/31/60538.html</guid><wfw:comment>http://www.cppblog.com/woaidongmao/comments/60538.html</wfw:comment><comments>http://www.cppblog.com/woaidongmao/archive/2008/08/31/60538.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/woaidongmao/comments/commentRss/60538.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/woaidongmao/services/trackbacks/60538.html</trackback:ping><description><![CDATA[<form id="Form1" name="Form1" action="http://www.cppblog.com/4659.html" method="post" _initialAction="4659.html"> <div id="centercontent"> <div class="post"> <p>模板是一种源码复用技术,在某些情况下使用它可以使代码看起来非常优雅,著名的boost库就是模板发扬的典范.<br>然而模板也存在弊端,大量使用模板可能导致代码膨胀.下面介绍一种解决的方案:</p> <p>我们首先看一段一般代码:<br></p> <div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"> <span style="color: #000000">template</span> <span style="color: #000000">&lt;</span> <span style="color: #000000">typename T</span> <span style="color: #000000">&gt;</span> <span style="color: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"> </span><span style="color: #0000ff">class</span> <span style="color: #000000"> Vector<br><img id="Codehighlighter1_34_169_Open_Image" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top"><img id="Codehighlighter1_34_169_Closed_Image" style="display: none" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align="top"></span> <span id="Codehighlighter1_34_169_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"> </span><span id="Codehighlighter1_34_169_Open_Text"><span style="color: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top"></span> <span style="color: #0000ff">public</span> <span style="color: #000000">:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp; </span> <span style="color: #0000ff">virtual</span> <span style="color: #000000">&nbsp;</span> <span style="color: #0000ff">void</span> <span style="color: #000000"> Say()<br><img id="Codehighlighter1_65_167_Open_Image" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"><img id="Codehighlighter1_65_167_Closed_Image" style="display: none" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align="top">&nbsp;&nbsp;&nbsp; </span> <span id="Codehighlighter1_65_167_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"> </span><span id="Codehighlighter1_65_167_Open_Text"><span style="color: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span> <span style="color: #0000ff">const</span> <span style="color: #000000"> type_info</span> <span style="color: #000000">&amp;</span> <span style="color: #000000">&nbsp;&nbsp;&nbsp; t </span> <span style="color: #000000">=</span> <span style="color: #000000"> typeid(T);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; std::cout </span> <span style="color: #000000">&lt;&lt;</span> <span style="color: #000000">&nbsp;</span> <span style="color: #000000">"</span> <span style="color: #000000">Vector&lt;</span> <span style="color: #000000">"</span> <span style="color: #000000">&nbsp;</span> <span style="color: #000000">&lt;&lt;</span> <span style="color: #000000"> t.name() </span> <span style="color: #000000">&lt;&lt;</span> <span style="color: #000000">&nbsp;</span> <span style="color: #000000">"</span> <span style="color: #000000">&gt;::Hello</span> <span style="color: #000000">"</span> <span style="color: #000000">&nbsp;</span> <span style="color: #000000">&lt;&lt;</span> <span style="color: #000000"> std::endl;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top">&nbsp;&nbsp;&nbsp; }</span> </span><span style="color: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top">}</span> </span><span style="color: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"></span> <span style="color: #008000">//</span> <span style="color: #008000"> 特例化</span> <span style="color: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"> </span><span style="color: #000000">template</span> <span style="color: #000000">&lt;&gt;</span> <span style="color: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"> </span><span style="color: #0000ff">class</span> <span style="color: #000000">&nbsp; Vector</span> <span style="color: #000000">&lt;</span> <span style="color: #0000ff">void</span> <span style="color: #000000">*&gt;</span> <span style="color: #000000"><br><img id="Codehighlighter1_212_300_Open_Image" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top"> <img id="Codehighlighter1_212_300_Closed_Image" style="display: none" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align="top"> </span><span id="Codehighlighter1_212_300_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"> </span><span id="Codehighlighter1_212_300_Open_Text"><span style="color: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top"></span> <span style="color: #0000ff">public</span> <span style="color: #000000">:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp; </span> <span style="color: #0000ff">virtual</span> <span style="color: #000000">&nbsp;</span> <span style="color: #0000ff">void</span> <span style="color: #000000"> Say()<br><img id="Codehighlighter1_243_298_Open_Image" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"><img id="Codehighlighter1_243_298_Closed_Image" style="display: none" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align="top">&nbsp;&nbsp;&nbsp; </span> <span id="Codehighlighter1_243_298_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"> </span><span id="Codehighlighter1_243_298_Open_Text"><span style="color: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; std::cout </span> <span style="color: #000000">&lt;&lt;</span> <span style="color: #000000">&nbsp;</span> <span style="color: #000000">"</span> <span style="color: #000000">Vector&lt;void*&gt;::Hello</span> <span style="color: #000000">"</span> <span style="color: #000000">&nbsp;</span> <span style="color: #000000">&lt;&lt;</span> <span style="color: #000000"> std::endl;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top">&nbsp;&nbsp;&nbsp; }</span> </span><span style="color: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top">}</span> </span><span style="color: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"></span> <span style="color: #0000ff">int</span> <span style="color: #000000"> _tmain(</span> <span style="color: #0000ff">int</span> <span style="color: #000000"> argc, _TCHAR</span> <span style="color: #000000">*</span> <span style="color: #000000"> argv[])<br><img id="Codehighlighter1_341_441_Open_Image" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top"><img id="Codehighlighter1_341_441_Closed_Image" style="display: none" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align="top"></span> <span id="Codehighlighter1_341_441_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"> </span><span id="Codehighlighter1_341_441_Open_Text"><span style="color: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp; Vector</span> <span style="color: #000000">&lt;</span> <span style="color: #0000ff">int</span> <span style="color: #000000">*&gt;</span> <span style="color: #000000">&nbsp;&nbsp;&nbsp; pIntVec;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp; pIntVec.Say();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp; Vector</span> <span style="color: #000000">&lt;</span> <span style="color: #0000ff">double</span> <span style="color: #000000">*&gt;</span> <span style="color: #000000">&nbsp;&nbsp;&nbsp; pDoubleVec;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp; pDoubleVec.Say();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp; </span> <span style="color: #0000ff">return</span> <span style="color: #000000">&nbsp;</span> <span style="color: #000000">0</span> <span style="color: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top">}</span> </span></div> <p><br>输出:<br>Vector&lt;int *&gt;::Hello<br>Vector&lt;double *&gt;::Hello<br>从这里,我们可以看出程序在运行的过程中生产了两分Vector的代码(int*和double*),尽管这里有特例化,然而类型不匹配,编译器在编译过程中无法定位到特例化版本.如果这个Vector被滥用的化,我想即使是一个中等规模的程序也可能耗费成兆字节的代码控件.</p> <p>我们必须寻找一种中间桥梁使编译器在编译过程中定位到void*的特例化版本.按照模板选择策略,编译器总是选择最特例化的模板,我们可以通过一个中间的模板联系起上面两个版本的模板.下面看一段代码:<br></p> <div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"> <span style="color: #000000">template</span> <span style="color: #000000">&lt;</span> <span style="color: #000000">typename T</span> <span style="color: #000000">&gt;</span> <span style="color: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"> </span><span style="color: #0000ff">class</span> <span style="color: #000000"> Vector<br><img id="Codehighlighter1_34_115_Open_Image" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top"><img id="Codehighlighter1_34_115_Closed_Image" style="display: none" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align="top"></span> <span id="Codehighlighter1_34_115_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"> </span><span id="Codehighlighter1_34_115_Open_Text"><span style="color: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top"></span> <span style="color: #0000ff">public</span> <span style="color: #000000">:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp; </span> <span style="color: #0000ff">virtual</span> <span style="color: #000000">&nbsp;</span> <span style="color: #0000ff">void</span> <span style="color: #000000"> Say()<br><img id="Codehighlighter1_65_113_Open_Image" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"><img id="Codehighlighter1_65_113_Closed_Image" style="display: none" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align="top">&nbsp;&nbsp;&nbsp; </span> <span id="Codehighlighter1_65_113_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"> </span><span id="Codehighlighter1_65_113_Open_Text"><span style="color: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; std::cout </span> <span style="color: #000000">&lt;&lt;</span> <span style="color: #000000">&nbsp;</span> <span style="color: #000000">"</span> <span style="color: #000000">Vector::Hello</span> <span style="color: #000000">"</span> <span style="color: #000000">&nbsp;</span> <span style="color: #000000">&lt;&lt;</span> <span style="color: #000000"> std::endl;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top">&nbsp;&nbsp;&nbsp; }</span> </span><span style="color: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top">}</span> </span><span style="color: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"></span> <span style="color: #008000">//</span> <span style="color: #008000"> 特例化</span> <span style="color: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"> </span><span style="color: #000000">template</span> <span style="color: #000000">&lt;&gt;</span> <span style="color: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"> </span><span style="color: #0000ff">class</span> <span style="color: #000000">&nbsp; Vector</span> <span style="color: #000000">&lt;</span> <span style="color: #0000ff">void</span> <span style="color: #000000">*&gt;</span> <span style="color: #000000"><br><img id="Codehighlighter1_158_246_Open_Image" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top"> <img id="Codehighlighter1_158_246_Closed_Image" style="display: none" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align="top"> </span><span id="Codehighlighter1_158_246_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"> </span><span id="Codehighlighter1_158_246_Open_Text"><span style="color: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top"></span> <span style="color: #0000ff">public</span> <span style="color: #000000">:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp; </span> <span style="color: #0000ff">virtual</span> <span style="color: #000000">&nbsp;</span> <span style="color: #0000ff">void</span> <span style="color: #000000"> Say()<br><img id="Codehighlighter1_189_244_Open_Image" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"><img id="Codehighlighter1_189_244_Closed_Image" style="display: none" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align="top">&nbsp;&nbsp;&nbsp; </span> <span id="Codehighlighter1_189_244_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"> </span><span id="Codehighlighter1_189_244_Open_Text"><span style="color: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; std::cout </span> <span style="color: #000000">&lt;&lt;</span> <span style="color: #000000">&nbsp;</span> <span style="color: #000000">"</span> <span style="color: #000000">Vector&lt;void*&gt;::Hello</span> <span style="color: #000000">"</span> <span style="color: #000000">&nbsp;</span> <span style="color: #000000">&lt;&lt;</span> <span style="color: #000000"> std::endl;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top">&nbsp;&nbsp;&nbsp; }</span> </span><span style="color: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top">}</span> </span><span style="color: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"></span> <span style="color: #008000">//</span> <span style="color: #008000"> 特例化</span> <span style="color: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"> </span><span style="color: #000000">template</span> <span style="color: #000000">&lt;</span> <span style="color: #000000">typename T</span> <span style="color: #000000">&gt;</span> <span style="color: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"> </span><span style="color: #0000ff">class</span> <span style="color: #000000"> Vector</span> <span style="color: #000000">&lt;</span> <span style="color: #000000">T</span> <span style="color: #000000">*&gt;</span> <span style="color: #000000"> : </span> <span style="color: #0000ff">public</span> <span style="color: #000000"> Vector</span> <span style="color: #000000">&lt;</span> <span style="color: #0000ff">void</span> <span style="color: #000000">*&gt;</span> <span style="color: #000000"><br><img id="Codehighlighter1_318_320_Open_Image" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top"> <img id="Codehighlighter1_318_320_Closed_Image" style="display: none" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align="top"> </span><span id="Codehighlighter1_318_320_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"> </span><span id="Codehighlighter1_318_320_Open_Text"><span style="color: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top">}</span> </span><span style="color: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"></span> <span style="color: #0000ff">int</span> <span style="color: #000000"> _tmain(</span> <span style="color: #0000ff">int</span> <span style="color: #000000"> argc, _TCHAR</span> <span style="color: #000000">*</span> <span style="color: #000000"> argv[])<br><img id="Codehighlighter1_361_461_Open_Image" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top"><img id="Codehighlighter1_361_461_Closed_Image" style="display: none" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align="top"></span> <span id="Codehighlighter1_361_461_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"> </span><span id="Codehighlighter1_361_461_Open_Text"><span style="color: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp; Vector</span> <span style="color: #000000">&lt;</span> <span style="color: #0000ff">int</span> <span style="color: #000000">*&gt;</span> <span style="color: #000000">&nbsp;&nbsp;&nbsp; pIntVec;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp; pIntVec.Say();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp; Vector</span> <span style="color: #000000">&lt;</span> <span style="color: #0000ff">double</span> <span style="color: #000000">*&gt;</span> <span style="color: #000000">&nbsp;&nbsp;&nbsp; pDoubleVec;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp; pDoubleVec.Say();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp; </span> <span style="color: #0000ff">return</span> <span style="color: #000000">&nbsp;</span> <span style="color: #000000">0</span> <span style="color: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top">}</span> </span></div> <p><br>输出:<br>Vector&lt;void*&gt;::Hello<br>Vector&lt;void*&gt;::Hello<br>从这里,我们可以看出程序在运行过程中全部使用Vector&lt;void*&gt;的版本.class Vector&lt;T*&gt;模板便是关键的环节.编译器在编译过程中,由于class Vector&lt;T*&gt;比class Vector更特例化,所以遇到Vector&lt;int*&gt;和Vector&lt;double*&gt;时都选择class Vector&lt;T*&gt;,而class Vector&lt;T*&gt;继承Vector&lt;void*&gt;,一个更加特例化版本,所以编译器不再产生新的模板而采用Vector&lt;void*&gt;这个最特例化版本,这样所有指针模板都归结到Vector&lt;void*&gt;,而class Vector&lt;T*&gt;为用户提供了一个精美而且安全的界面,而Vector&lt;void*&gt;作为底层实现细节被隐藏.</p> <p>以上代码在VC 7.1(VS2003)中编译通过,由于VC6对模板支持不好,所以模板的高级用法一般不要在VC6中使用. <br><a href="http://www.cppblog.com/files/wlwlxj/template.rar">下载演示代码</a></p> <div class="postDesc">posted on 2006-03-27 18:54 <a href="http://www.cppblog.com/wlwlxj/">万连文</a> 阅读(629) <a href="http://www.cppblog.com/#Post">评论(7)</a>&nbsp; <a href="http://www.cppblog.com/wlwlxj/admin/EditPosts.aspx?postid=4659">编辑</a>&nbsp;<a href="http://www.cppblog.com/wlwlxj/AddToFavorite.aspx?id=4659">收藏</a> <a href="http://www.cppblog.com/wlwlxj/services/trackbacks/4659.aspx">引用</a> 所属分类: <a href="http://www.cppblog.com/wlwlxj/category/1324.html">模板</a> </div></div><img height="1" src="http://www.cppblog.com/wlwlxj/aggbug/4659.html?webview=1" width="1">  <div id="AjaxHolder_UpdatePanel1"><a name="pagedcomment"></a><br><b>FeedBack:</b>  <div class="feedbackNoItems"></div> <div class="feedbackItem"> <div class="feedbackListTitle"><a title="permalink: re: 抑制模板代码膨胀的一种技术" href="http://www.cppblog.com/wlwlxj/archive/2006/03/27/4659.html#4660">#</a>&nbsp;<a name="4660"></a>re: 抑制模板代码膨胀的一种技术</div> <div class="feedbackListSubtitle">2006-03-27 20:08 | <a id="AjaxHolder_Comments_CommentList_ctl00_NameLink" target="_blank">vender</a><br> <div align="left">不要这么别扭吧，直接偏特化好了 <br>template&lt;typename T&gt; <br>class Vector&lt;T*&gt; <br>{ <br>public: <br>virtual void Say() <br>{ <br>std::cout &lt;&lt; "Vector&lt;void*&gt;::Hello" &lt;&lt; std::endl; <br>} <br>}; <br>&nbsp; <a href="http://www.cppblog.com/wlwlxj/archive/2006/03/27/4659.html#post">回复</a>&nbsp; <a title="查看该作者发表过的评论" href="http://www.cppblog.com/comment?author=vender" target="_blank">更多评论</a><br><a id="AjaxHolder_Comments_CommentList_ctl00_DeleteLink" href="http://www.cppblog.com/"></a>&nbsp; <a id="AjaxHolder_Comments_CommentList_ctl00_EditLink"></a></div></div></div> <div class="feedbackItem"> <div class="feedbackListTitle"><a title="permalink: re: 抑制模板代码膨胀的一种技术" href="http://www.cppblog.com/wlwlxj/archive/2006/03/27/4659.html#4661">#</a>&nbsp;<a name="4661"></a>re: 抑制模板代码膨胀的一种技术</div> <div class="feedbackListSubtitle">2006-03-27 20:15 | <a id="AjaxHolder_Comments_CommentList_ctl01_NameLink" target="_blank">vender</a><br> <div align="left">而且你提到的这个“技巧”还是无法避免代码膨胀 <br><br>由于此例过于简单，打开优化的编译器有可能仅仅产生一份代码，但原则上（例如不打开优化等）Vector&lt;int*&gt;和Vector&lt;double*&gt;还是会产生两份代码&nbsp; <a href="http://www.cppblog.com/wlwlxj/archive/2006/03/27/4659.html#post">回复</a>&nbsp; <a title="查看该作者发表过的评论" href="http://www.cppblog.com/comment?author=vender" target="_blank">更多评论</a><br><a id="AjaxHolder_Comments_CommentList_ctl01_DeleteLink" href="http://www.cppblog.com/"></a>&nbsp; <a id="AjaxHolder_Comments_CommentList_ctl01_EditLink"></a></div></div></div> <div class="feedbackItem"> <div class="feedbackListTitle"><a title="permalink: re: 抑制模板代码膨胀的一种技术" href="http://www.cppblog.com/wlwlxj/archive/2006/03/27/4659.html#4680">#</a>&nbsp;<a name="4680"></a>re: 抑制模板代码膨胀的一种技术</div> <div class="feedbackListSubtitle">2006-03-28 11:25 | <a id="AjaxHolder_Comments_CommentList_ctl02_NameLink" href="http://www.cppblog.com/wlwlxj/" target="_blank">万连文</a><br> <div align="left">你指的麻烦我主要是为了演示效果，看编译器到底调用哪个版本， <br>你指的过于简单也没有道理，举一反三，两个难道不能代表问题吗？？如果不能我可以写3个，并且我没有打开任何优化器，结果显示确实是一份代码。顺便提一下，这个技术是看C++ program language(C++之父)里面提到的，感觉很好玩，所以动手测试了一下，发现真可以运做。&nbsp; <a href="http://www.cppblog.com/wlwlxj/archive/2006/03/27/4659.html#post">回复</a>&nbsp; <a title="查看该作者发表过的评论" href="http://www.cppblog.com/comment?author=%e4%b8%87%e8%bf%9e%e6%96%87" target="_blank">更多评论</a><br><a id="AjaxHolder_Comments_CommentList_ctl02_DeleteLink" href="http://www.cppblog.com/"></a>&nbsp; <a id="AjaxHolder_Comments_CommentList_ctl02_EditLink"></a></div></div></div> <div class="feedbackItem"> <div class="feedbackListTitle"><a title="permalink: re: 抑制模板代码膨胀的一种技术" href="http://www.cppblog.com/wlwlxj/archive/2006/03/27/4659.html#4681">#</a>&nbsp;<a name="4681"></a>re: 抑制模板代码膨胀的一种技术</div> <div class="feedbackListSubtitle">2006-03-28 11:41 | <a id="AjaxHolder_Comments_CommentList_ctl03_NameLink" href="http://www.cppblog.com/sandy/" target="_blank">小明</a><br> <div align="left">我觉得vendor兄说的有道理阿，直接对T*进行偏特话就ok了。多一个void *的版本有什么意义呢？&nbsp; <a href="http://www.cppblog.com/wlwlxj/archive/2006/03/27/4659.html#post">回复</a>&nbsp; <a title="查看该作者发表过的评论" href="http://www.cppblog.com/comment?author=%e5%b0%8f%e6%98%8e" target="_blank">更多评论</a><br><a id="AjaxHolder_Comments_CommentList_ctl03_DeleteLink" href="http://www.cppblog.com/"></a>&nbsp; <a id="AjaxHolder_Comments_CommentList_ctl03_EditLink"></a></div></div></div> <div class="feedbackItem"> <div class="feedbackListTitle"><a title="permalink: re: 抑制模板代码膨胀的一种技术" href="http://www.cppblog.com/wlwlxj/archive/2006/03/27/4659.html#4682">#</a>&nbsp;<a name="4682"></a>re: 抑制模板代码膨胀的一种技术</div> <div class="feedbackListSubtitle">2006-03-28 11:48 | <a id="AjaxHolder_Comments_CommentList_ctl04_NameLink" href="http://www.cppblog.com/wlwlxj/" target="_blank">万连文</a><br> <div align="left">如果没有void *版本，你可以把 <br>public: <br>virtual void Say() <br>{ <br>std::cout &lt;&lt; "Vector::Hello" &lt;&lt; std::endl; <br>} <br>放到 <br>// 特例化 <br>template&lt;typename T&gt; <br>class Vector&lt;T*&gt; : public Vector&lt;void*&gt; <br>{ <br>}; <br>看下结果是不是产生两份代码&nbsp; <a href="http://www.cppblog.com/wlwlxj/archive/2006/03/27/4659.html#post">回复</a>&nbsp; <a title="查看该作者发表过的评论" href="http://www.cppblog.com/comment?author=%e4%b8%87%e8%bf%9e%e6%96%87" target="_blank">更多评论</a><br><a id="AjaxHolder_Comments_CommentList_ctl04_DeleteLink" href="http://www.cppblog.com/"></a>&nbsp; <a id="AjaxHolder_Comments_CommentList_ctl04_EditLink"></a></div></div></div> <div class="feedbackItem"> <div class="feedbackListTitle"><a title="permalink: re: 抑制模板代码膨胀的一种技术" href="http://www.cppblog.com/wlwlxj/archive/2006/03/27/4659.html#4683">#</a>&nbsp;<a name="4683"></a>re: 抑制模板代码膨胀的一种技术</div> <div class="feedbackListSubtitle">2006-03-28 11:50 | <a id="AjaxHolder_Comments_CommentList_ctl05_NameLink" href="http://www.cppblog.com/wlwlxj/" target="_blank">万连文</a><br> <div align="left">最终目的就是让所有指针模板使用&lt;void *&gt;那一份代码，这样减少代码膨胀&nbsp; <a href="http://www.cppblog.com/wlwlxj/archive/2006/03/27/4659.html#post">回复</a>&nbsp; <a title="查看该作者发表过的评论" href="http://www.cppblog.com/comment?author=%e4%b8%87%e8%bf%9e%e6%96%87" target="_blank">更多评论</a><br><a id="AjaxHolder_Comments_CommentList_ctl05_DeleteLink" href="http://www.cppblog.com/"></a>&nbsp; <a id="AjaxHolder_Comments_CommentList_ctl05_EditLink"></a></div></div></div> <div class="feedbackItem"> <div class="feedbackListTitle"><a title="permalink: re: 抑制模板代码膨胀的一种技术" href="http://www.cppblog.com/wlwlxj/archive/2006/03/27/4659.html#4735">#</a>&nbsp;<a name="4735"></a>re: 抑制模板代码膨胀的一种技术<a name="Post"></a></div> <div class="feedbackListSubtitle">2006-03-29 15:05 | <a id="AjaxHolder_Comments_CommentList_ctl06_NameLink" href="http://www.cppblog.com/wlwlxj/" target="_blank">万连文</a><br> <div align="left">不好意思，今天再次体会了一下，上面示例和解释存在问题： <br>在特例化的例子里面确实生成了2个版本的类&lt;double*&gt;和&lt;int*&gt;，这种技术减少代码主要表现在函数体公用上面，比如一个20行的函数pushback,实例化20次(20个指针版本)就是400行代码，如果公用&lt;void*&gt;版本，假设每个调用&lt;void*&gt;版本是4行，加上&lt;void*&gt;版本的20行将是20*4+20=100行，确实减少不少代码。 <br>不知道这次理解是否正确。&nbsp; <a href="http://www.cppblog.com/wlwlxj/archive/2006/03/27/4659.html#post">回复</a>&nbsp; <a title="查看该作者发表过的评论" href="http://www.cppblog.com/comment?author=%e4%b8%87%e8%bf%9e%e6%96%87" target="_blank">更多评论</a><br></div></div></div></div></div></form><img src ="http://www.cppblog.com/woaidongmao/aggbug/60538.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/woaidongmao/" target="_blank">肥仔</a> 2008-08-31 21:54 <a href="http://www.cppblog.com/woaidongmao/archive/2008/08/31/60538.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>什么元素可以作为模板参数的实参</title><link>http://www.cppblog.com/woaidongmao/archive/2008/08/31/60537.html</link><dc:creator>肥仔</dc:creator><author>肥仔</author><pubDate>Sun, 31 Aug 2008 13:53:00 GMT</pubDate><guid>http://www.cppblog.com/woaidongmao/archive/2008/08/31/60537.html</guid><wfw:comment>http://www.cppblog.com/woaidongmao/comments/60537.html</wfw:comment><comments>http://www.cppblog.com/woaidongmao/archive/2008/08/31/60537.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/woaidongmao/comments/commentRss/60537.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/woaidongmao/services/trackbacks/60537.html</trackback:ping><description><![CDATA[<form id="Form1" name="Form1" action="http://www.cppblog.com/25264.html" method="post" _initialAction="25264.html"> <table class="Framework" cellspacing="0" cellpadding="0" width="100%"> <tbody> <tr> <td class="MainCell"> <div id="main"> <div class="post"> <div class="postbody">在C++中模板分为两大类别：类模板和函数模板。这两种类别的模板在语法形式上是相同<br>的，只是各自存在一些特别的约束。那么什么样的C++元素可以作为实参来替换模板中的形参<br>呢？这里又主要分成两大类实参类型：<br>&nbsp;&nbsp;&nbsp; 1. 类型实参<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 类型实参实际上就是C++中间的各种各样的数据类型，包括POD类型和类类型。比如：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; char、int、int*、int&amp;、float和用户定义的类型。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; 2. 非类型实参<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 非类型实际上就是值的意思，而要作为模板实参的值就必须是一个常量值，更准确<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 的说就必须是一个在编译期能够确定的值（简称编译期常量），然而编译期常量在<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; C++中包含了非常广泛的概念，也不是所有的编译期常量都可以作为模板的实参的，<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 也就是仅仅只有编译期常量的一个子集可以作为模板实参，那么什么编译期常量可<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 以作为模板实参呢？主要有三种类型的编译期常量：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; a. 整型常量<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在C++中所谓的整型包括char、short、int、long、long long、上述类型的<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 无符号类型、wchar_t、enum类型。其中要注意的是float和double类型是不<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 可以作模板实参的（在C++0x标准中会改变这一状况）。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; b. 函数地址<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 函数地址主要包括非成员函数地址、成员函数地址、静态成员函数地址。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; c. 具有外部引用的字符串数组<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 什么是具有外部引用的字符串数组呢？就是具有如下形式：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; extern char cstr[]; // 可以初始化，如：extern char cstr[] = ""<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // char也可以是wchar_t<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 需要注意的是extern char *cstr;所声名的是一个指针而不是一个数组，所<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 以不能够用作模板的实参。那么在作为模板实参的时候是采用了cstr所包含<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 的字符串值作为模版实参的吗，其实不是，虽然cstr是一个字符串，其实在<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 作为模板实参是仅仅用到了cstr的地址，也就是说如下的定义是合法的：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; extern char cstr1[] = "cstr";<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; extern char cstr2[] = "cstr";<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; template&lt;char *V&gt; struct CTemplateValue {};<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 或者 template&lt;char V[]&gt; struct CTemplateValue {};<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; template&lt;&gt; struct CTemplateValue&lt;cstr1&gt; {};<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; template&lt;&gt; struct CTemplateValue&lt;cstr2&gt; {};<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 上面的代码中，cstr1和cstr2都包含有相同的字符串值，但是在作为模板实参<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 时并没有参考cstr1和cstr2的内容，而是依赖于其地址，所以可以进行模板的<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 特化，而不出现重复特化的编译时错误。&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 总的来说这里上面的三种常量都是编译期常量，对于第一种情况是比较好理解的，而<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 对于第二三种请款可能就不那么直观了，为什么函数地址和外部引用的字符串是编译<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 期常量呢？首先我们来解释一下编译器在编译函数和全局外部引用的变量时会如何处<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 理这两者的地址，以使得其他的代码或模块能够顺利地找到该地址并调用函数或引用<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 变量。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 首先可以肯定的是编译器必须为函数和全局外部引用的变量生成唯一的入口地址，否<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 则就无法引用了；<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 其次编译器会生成什么样的地址呢？地址分为：物理地址（PA）和虚拟地址（RVA），<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 目前编译器一般不会生成物理内存地址的，因为基本上所有的程序在操作系统调度运<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 行时均不可能保证该物理内存地址可以被分配给该程序使用（可能已经被其他的程序<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 占用了），那么现在的编译器均会选择生成RVA地址，其实RVA地址是相对于程序载入<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 首地址的一个偏移常量（offset），那么操作系统在载入程序时仅仅需要修改程序的<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 载入首地址就可以完成程序的载入，而程序内部在调用一个函数或引用变量时会采用<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 首地址+RVA地址的方法来完成引用，这样一来RVA就成为了一个编译期的整型常量了，<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 所以函数地址和全局外部引用字符串的地址就成为了编译期的常量，可以作为模板实<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 参了。那为什么必须是外部引用的字符串数组呢？内部引用的字符串数组不可以么？<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 如果对此有兴趣可以关注后续相关内外部引用的讨论blog。 <br><br></div></div> <div id="AjaxHolder_UpdatePanel1"><a name="pagedcomment"></a> <h3>Feedback</h3> <div class="post"> <div class="posthead"> <h2><a title="permalink: re: 什么元素可以作为模板参数的实参" href="http://www.cppblog.com/chemz/archive/2007/06/01/25264.html#25268">#</a>&nbsp;<a name="25268"></a>re: 什么元素可以作为模板参数的实参&nbsp; <a href="http://www.cppblog.com/chemz/archive/2007/06/01/25264.html#post">回复</a>&nbsp; <a title="查看该作者发表过的评论" href="http://www.cppblog.com/comment?author=walkspeed" target="_blank">更多评论</a> <a id="AjaxHolder_Comments_CommentList_ctl00_DeleteLink" href="http://www.cppblog.com/"></a>&nbsp; <a id="AjaxHolder_Comments_CommentList_ctl00_EditLink"></a> </h2>2007-06-01 12:29 by <a id="AjaxHolder_Comments_CommentList_ctl00_NameLink" href="http://www.cppblog.com/walkspeed/" target="_blank">walkspeed</a> </div> <div class="postbody">快出后续呀。<br><br>如果推论的话，内部字符串是个非编译器常量啦。<br><br>这种分析很透彻，不光停留在表面上，而且讲清楚了其在编译时的特性。模板本来就是用来控制编译期的。所以对编译器在编译期的了解越深刻，也容易理解模板编程。<br><br>非类型实际上就是值的意思，而要作为模板实参的值就必须是一个常量值，更准确<br>的说就必须是一个在编译期能够确定的值（简称编译期常量）。记住这句话</div></div> <div class="post"> <div class="posthead"> <h2><a title="permalink: re: 什么元素可以作为模板参数的实参" href="http://www.cppblog.com/chemz/archive/2007/06/01/25264.html#25476">#</a>&nbsp;<a name="25476"></a>re: 什么元素可以作为模板参数的实参<a name="Post"></a>&nbsp; <a href="http://www.cppblog.com/chemz/archive/2007/06/01/25264.html#post">回复</a>&nbsp; <a title="查看该作者发表过的评论" href="http://www.cppblog.com/comment?author=picasa" target="_blank">更多评论</a> <a id="AjaxHolder_Comments_CommentList_ctl01_DeleteLink" href="http://www.cppblog.com/"></a>&nbsp; <a id="AjaxHolder_Comments_CommentList_ctl01_EditLink"></a> </h2>2007-06-04 14:08 by <a id="AjaxHolder_Comments_CommentList_ctl01_NameLink" href="http://www.picsa.cn/" target="_blank">picasa</a> </div> <div class="postbody">分析的挺好</div></div></div></div></td></tr></tbody></table></form><img src ="http://www.cppblog.com/woaidongmao/aggbug/60537.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/woaidongmao/" target="_blank">肥仔</a> 2008-08-31 21:53 <a href="http://www.cppblog.com/woaidongmao/archive/2008/08/31/60537.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++类模板的三种特化</title><link>http://www.cppblog.com/woaidongmao/archive/2008/08/31/60536.html</link><dc:creator>肥仔</dc:creator><author>肥仔</author><pubDate>Sun, 31 Aug 2008 13:51:00 GMT</pubDate><guid>http://www.cppblog.com/woaidongmao/archive/2008/08/31/60536.html</guid><wfw:comment>http://www.cppblog.com/woaidongmao/comments/60536.html</wfw:comment><comments>http://www.cppblog.com/woaidongmao/archive/2008/08/31/60536.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/woaidongmao/comments/commentRss/60536.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/woaidongmao/services/trackbacks/60536.html</trackback:ping><description><![CDATA[<form id="Form1" name="Form1" action="http://www.cppblog.com/27496.aspx" method="post" _initialAction="27496.aspx"> <div id="centercontent"> <div class="post"> <p>&nbsp; <br></p> <p>&nbsp; 说起C++的模板及模板特化， 相信很多人都很熟悉 ，但是说到模板特化的几种类型，相信了解的人就不是很多。我这里归纳了针对一个模板参数的类模板特化的几种类型， 一是特化为绝对类型； 二是特化为引用，指针类型；三是特化为另外一个类模板。<br> 这里用一个简单的例子来说明这三种情况：</p> <div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><span style="color: #008000">//</span><span style="color: #008000"> general version</span><span style="color: #008000"><br></span><span style="color: #000000">template</span><span style="color: #000000">&lt;</span><span style="color: #0000ff">class</span><span style="color: #000000"> T</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br></span><span style="color: #0000ff">class</span><span style="color: #000000"> Compare<br>{<br></span><span style="color: #0000ff">public</span><span style="color: #000000">:<br>&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff">static</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">bool</span><span style="color: #000000"> IsEqual(</span><span style="color: #0000ff">const</span><span style="color: #000000"> T</span><span style="color: #000000">&amp;</span><span style="color: #000000"> lh, </span><span style="color: #0000ff">const</span><span style="color: #000000"> T</span><span style="color: #000000">&amp;</span><span style="color: #000000"> rh)<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff">return</span><span style="color: #000000"> lh </span><span style="color: #000000">==</span><span style="color: #000000"> rh;<br>&nbsp;&nbsp;&nbsp; }<br>};</span></div> <p>这是一个用于比较的类模板，里面可以有多种用于比较的函数， 以IsEqual为例。<br>&nbsp;<br><strong>一、特化为绝对类型<br></strong>也就是说直接为某个特定类型做特化，这是我们最常见的一种特化方式， 如特化为float, double等</p> <div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><span style="color: #008000">//</span><span style="color: #008000"> specialize for float</span><span style="color: #008000"><br></span><span style="color: #000000">template</span><span style="color: #000000">&lt;&gt;</span><span style="color: #000000"><br></span><span style="color: #0000ff">class</span><span style="color: #000000"> Compare</span><span style="color: #000000">&lt;</span><span style="color: #0000ff">float</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br>{<br></span><span style="color: #0000ff">public</span><span style="color: #000000">:<br>&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff">static</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">bool</span><span style="color: #000000"> IsEqual(</span><span style="color: #0000ff">const</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">float</span><span style="color: #000000">&amp;</span><span style="color: #000000"> lh, </span><span style="color: #0000ff">const</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">float</span><span style="color: #000000">&amp;</span><span style="color: #000000"> rh)<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff">return</span><span style="color: #000000"> abs(lh </span><span style="color: #000000">-</span><span style="color: #000000"> rh) </span><span style="color: #000000">&lt;</span><span style="color: #000000"> 10e</span><span style="color: #000000">-</span><span style="color: #000000">3</span><span style="color: #000000">;<br>&nbsp;&nbsp;&nbsp; }<br>};<br><br></span><span style="color: #008000">//</span><span style="color: #008000"> specialize for double</span><span style="color: #008000"><br></span><span style="color: #000000">template</span><span style="color: #000000">&lt;&gt;</span><span style="color: #000000"><br></span><span style="color: #0000ff">class</span><span style="color: #000000"> Compare</span><span style="color: #000000">&lt;</span><span style="color: #0000ff">double</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br>{<br></span><span style="color: #0000ff">public</span><span style="color: #000000">:<br>&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff">static</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">bool</span><span style="color: #000000"> IsEqual(</span><span style="color: #0000ff">const</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">double</span><span style="color: #000000">&amp;</span><span style="color: #000000"> lh, </span><span style="color: #0000ff">const</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">double</span><span style="color: #000000">&amp;</span><span style="color: #000000"> rh)<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff">return</span><span style="color: #000000"> abs(lh </span><span style="color: #000000">-</span><span style="color: #000000"> rh) </span><span style="color: #000000">&lt;</span><span style="color: #000000"> 10e</span><span style="color: #000000">-</span><span style="color: #000000">6</span><span style="color: #000000">;<br>&nbsp;&nbsp;&nbsp; }<br>};<br><br></span></div> <p><br>&nbsp;<br><strong>二、特化为引用，指针类型<br></strong>这种特化我最初是在stl源码的的iterator_traits特化中发现的， 如下：</p> <div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><span style="color: #000000">template </span><span style="color: #000000">&lt;</span><span style="color: #0000ff">class</span><span style="color: #000000"> _Iterator</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br></span><span style="color: #0000ff">struct</span><span style="color: #000000"> iterator_traits {<br>&nbsp; typedef typename _Iterator::iterator_category iterator_category;<br>&nbsp; typedef typename _Iterator::value_type&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; value_type;<br>&nbsp; typedef typename _Iterator::difference_type&nbsp;&nbsp; difference_type;<br>&nbsp; typedef typename _Iterator::pointer&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pointer;<br>&nbsp; typedef typename _Iterator::reference&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; reference;<br>};<br><br></span><span style="color: #008000">//</span><span style="color: #008000"> specialize for _Tp*</span><span style="color: #008000"><br></span><span style="color: #000000">template </span><span style="color: #000000">&lt;</span><span style="color: #0000ff">class</span><span style="color: #000000"> _Tp</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br></span><span style="color: #0000ff">struct</span><span style="color: #000000"> iterator_traits</span><span style="color: #000000">&lt;</span><span style="color: #000000">_Tp</span><span style="color: #000000">*&gt;</span><span style="color: #000000"> {<br>&nbsp; typedef random_access_iterator_tag iterator_category;<br>&nbsp; typedef _Tp&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; value_type;<br>&nbsp; typedef ptrdiff_t&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; difference_type;<br>&nbsp; typedef _Tp</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pointer;<br>&nbsp; typedef _Tp</span><span style="color: #000000">&amp;</span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; reference;<br>};<br><br></span><span style="color: #008000">//</span><span style="color: #008000"> specialize for const _Tp*</span><span style="color: #008000"><br></span><span style="color: #000000">template </span><span style="color: #000000">&lt;</span><span style="color: #0000ff">class</span><span style="color: #000000"> _Tp</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br></span><span style="color: #0000ff">struct</span><span style="color: #000000"> iterator_traits</span><span style="color: #000000">&lt;</span><span style="color: #0000ff">const</span><span style="color: #000000"> _Tp</span><span style="color: #000000">*&gt;</span><span style="color: #000000"> {<br>&nbsp; typedef random_access_iterator_tag iterator_category;<br>&nbsp; typedef _Tp&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; value_type;<br>&nbsp; typedef ptrdiff_t&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; difference_type;<br>&nbsp; typedef </span><span style="color: #0000ff">const</span><span style="color: #000000"> _Tp</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pointer;<br>&nbsp; typedef </span><span style="color: #0000ff">const</span><span style="color: #000000"> _Tp</span><span style="color: #000000">&amp;</span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; reference;<br>};<br><br></span></div> <p>&nbsp;</p> <p> 当然，除了T*, 我们也可以将T特化为 const T*, T&amp;, const T&amp;等，以下还是以T*为例：</p> <div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><span style="color: #008000">//</span><span style="color: #008000"> specialize for T*</span><span style="color: #008000"><br></span><span style="color: #000000">template</span><span style="color: #000000">&lt;</span><span style="color: #0000ff">class</span><span style="color: #000000"> T</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br></span><span style="color: #0000ff">class</span><span style="color: #000000"> Compare</span><span style="color: #000000">&lt;</span><span style="color: #000000">T</span><span style="color: #000000">*&gt;</span><span style="color: #000000"><br>{<br></span><span style="color: #0000ff">public</span><span style="color: #000000">:<br>&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff">static</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">bool</span><span style="color: #000000"> IsEqual(</span><span style="color: #0000ff">const</span><span style="color: #000000"> T</span><span style="color: #000000">*</span><span style="color: #000000"> lh, </span><span style="color: #0000ff">const</span><span style="color: #000000"> T</span><span style="color: #000000">*</span><span style="color: #000000"> rh)<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff">return</span><span style="color: #000000"> Compare</span><span style="color: #000000">&lt;</span><span style="color: #000000">T</span><span style="color: #000000">&gt;</span><span style="color: #000000">::IsEqual(</span><span style="color: #000000">*</span><span style="color: #000000">lh, </span><span style="color: #000000">*</span><span style="color: #000000">rh);<br>&nbsp;&nbsp;&nbsp; }<br>};</span></div> <p>这种特化其实是就不是一种绝对的特化， 它只是对类型做了某些限定，但仍然保留了其一定的模板性，这种特化给我们提供了极大的方便， 如这里， 我们就不需要对int*, float*, double*等等类型分别做特化了。<br></p> <p><strong>三、特化为另外一个类模板</strong></p> <p>这其实是第二种方式的扩展，其实也是对类型做了某种限定，而不是绝对化为某个具体类型，如下：<br></p> <div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><span style="color: #008000">//</span><span style="color: #008000"> specialize for vector&lt;T&gt;</span><span style="color: #008000"><br></span><span style="color: #000000">template</span><span style="color: #000000">&lt;</span><span style="color: #0000ff">class</span><span style="color: #000000"> T</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br></span><span style="color: #0000ff">class</span><span style="color: #000000"> Compare</span><span style="color: #000000">&lt;</span><span style="color: #000000">vector</span><span style="color: #000000">&lt;</span><span style="color: #000000">T</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br>{<br></span><span style="color: #0000ff">public</span><span style="color: #000000">:<br>&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff">static</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">bool</span><span style="color: #000000"> IsEqual(</span><span style="color: #0000ff">const</span><span style="color: #000000"> vector</span><span style="color: #000000">&lt;</span><span style="color: #000000">T</span><span style="color: #000000">&gt;&amp;</span><span style="color: #000000"> lh, </span><span style="color: #0000ff">const</span><span style="color: #000000"> vector</span><span style="color: #000000">&lt;</span><span style="color: #000000">T</span><span style="color: #000000">&gt;&amp;</span><span style="color: #000000"> rh)<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff">if</span><span style="color: #000000">(lh.size() </span><span style="color: #000000">!=</span><span style="color: #000000"> rh.size()) </span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">false</span><span style="color: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff">else</span><span style="color: #000000"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff">for</span><span style="color: #000000">(</span><span style="color: #0000ff">int</span><span style="color: #000000"> i </span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">; i </span><span style="color: #000000">&lt;</span><span style="color: #000000"> lh.size(); </span><span style="color: #000000">++</span><span style="color: #000000">i)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff">if</span><span style="color: #000000">(lh[i] </span><span style="color: #000000">!=</span><span style="color: #000000"> rh[i]) </span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">false</span><span style="color: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">true</span><span style="color: #000000">;<br>&nbsp;&nbsp;&nbsp; }<br>};<br></span></div> <p><br>这就把IsEqual的参数限定为一种vector类型， 但具体是vector&lt;int&gt;还是vector&lt;float&gt;， 我们可以不关心， 因为对于这两种类型，我们的处理方式是一样的，我们可以把这种方式称为“半特化”。</p> <p>当然， 我们可以将其“半特化”为任何我们自定义的模板类类型：</p> <div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><span style="color: #008000">//</span><span style="color: #008000"> specialize for any template class type</span><span style="color: #008000"><br></span><span style="color: #000000">template </span><span style="color: #000000">&lt;</span><span style="color: #0000ff">class</span><span style="color: #000000"> T1</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;<br></span><span style="color: #0000ff">struct</span><span style="color: #000000"> SpecializedType<br>{<br>&nbsp;&nbsp;&nbsp; T1 x1;<br>&nbsp;&nbsp;&nbsp; T1 x2;<br>};<br>template </span><span style="color: #000000">&lt;</span><span style="color: #0000ff">class</span><span style="color: #000000"> T</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br></span><span style="color: #0000ff">class</span><span style="color: #000000"> Compare</span><span style="color: #000000">&lt;</span><span style="color: #000000">SpecializedType</span><span style="color: #000000">&lt;</span><span style="color: #000000">T</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br>{<br></span><span style="color: #0000ff">public</span><span style="color: #000000">:<br>&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff">static</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">bool</span><span style="color: #000000"> IsEqual(</span><span style="color: #0000ff">const</span><span style="color: #000000"> SpecializedType</span><span style="color: #000000">&lt;</span><span style="color: #000000">T</span><span style="color: #000000">&gt;&amp;</span><span style="color: #000000"> lh, </span><span style="color: #0000ff">const</span><span style="color: #000000"> SpecializedType</span><span style="color: #000000">&lt;</span><span style="color: #000000">T</span><span style="color: #000000">&gt;&amp;</span><span style="color: #000000"> rh)<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff">return</span><span style="color: #000000"> Compare</span><span style="color: #000000">&lt;</span><span style="color: #000000">T</span><span style="color: #000000">&gt;</span><span style="color: #000000">::IsEqual(lh.x1 </span><span style="color: #000000">+</span><span style="color: #000000"> lh.x2, rh.x1 </span><span style="color: #000000">+</span><span style="color: #000000"> rh.x2);<br>&nbsp;&nbsp;&nbsp; }<br>};<br></span></div> <p><br> 这就是三种类型的模板特化， 我们可以这么使用这个Compare类：</p> <div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><span style="color: #000000">&nbsp;&nbsp; </span><span style="color: #008000">//</span><span style="color: #008000"> int</span><span style="color: #008000"><br></span><span style="color: #000000">&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff">int</span><span style="color: #000000"> i1 </span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">10</span><span style="color: #000000">;<br>&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff">int</span><span style="color: #000000"> i2 </span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">10</span><span style="color: #000000">;<br>&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff">bool</span><span style="color: #000000"> r1 </span><span style="color: #000000">=</span><span style="color: #000000"> Compare</span><span style="color: #000000">&lt;</span><span style="color: #0000ff">int</span><span style="color: #000000">&gt;</span><span style="color: #000000">::IsEqual(i1, i2);<br><br>&nbsp;&nbsp;&nbsp; </span><span style="color: #008000">//</span><span style="color: #008000"> float</span><span style="color: #008000"><br></span><span style="color: #000000">&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff">float</span><span style="color: #000000"> f1 </span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">10</span><span style="color: #000000">;<br>&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff">float</span><span style="color: #000000"> f2 </span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">10</span><span style="color: #000000">;<br>&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff">bool</span><span style="color: #000000"> r2 </span><span style="color: #000000">=</span><span style="color: #000000"> Compare</span><span style="color: #000000">&lt;</span><span style="color: #0000ff">float</span><span style="color: #000000">&gt;</span><span style="color: #000000">::IsEqual(f1, f2);<br><br>&nbsp;&nbsp;&nbsp; </span><span style="color: #008000">//</span><span style="color: #008000"> double</span><span style="color: #008000"><br></span><span style="color: #000000">&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff">double</span><span style="color: #000000"> d1 </span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">10</span><span style="color: #000000">;<br>&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff">double</span><span style="color: #000000"> d2 </span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">10</span><span style="color: #000000">;<br>&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff">bool</span><span style="color: #000000"> r3 </span><span style="color: #000000">=</span><span style="color: #000000"> Compare</span><span style="color: #000000">&lt;</span><span style="color: #0000ff">double</span><span style="color: #000000">&gt;</span><span style="color: #000000">::IsEqual(d1, d2);<br><br>&nbsp;&nbsp;&nbsp; </span><span style="color: #008000">//</span><span style="color: #008000"> pointer</span><span style="color: #008000"><br></span><span style="color: #000000">&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff">int</span><span style="color: #000000">*</span><span style="color: #000000"> p1 </span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">&amp;</span><span style="color: #000000">i1;<br>&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff">int</span><span style="color: #000000">*</span><span style="color: #000000"> p2 </span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">&amp;</span><span style="color: #000000">i2;<br>&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff">bool</span><span style="color: #000000"> r4 </span><span style="color: #000000">=</span><span style="color: #000000"> Compare</span><span style="color: #000000">&lt;</span><span style="color: #0000ff">int</span><span style="color: #000000">*&gt;</span><span style="color: #000000">::IsEqual(p1, p2);<br><br>&nbsp;&nbsp;&nbsp; </span><span style="color: #008000">//</span><span style="color: #008000"> vector&lt;T&gt;</span><span style="color: #008000"><br></span><span style="color: #000000">&nbsp;&nbsp;&nbsp; vector</span><span style="color: #000000">&lt;</span><span style="color: #0000ff">int</span><span style="color: #000000">&gt;</span><span style="color: #000000"> v1;<br>&nbsp;&nbsp;&nbsp; v1.push_back(</span><span style="color: #000000">1</span><span style="color: #000000">);<br>&nbsp;&nbsp;&nbsp; v1.push_back(</span><span style="color: #000000">2</span><span style="color: #000000">);<br><br>&nbsp;&nbsp;&nbsp; vector</span><span style="color: #000000">&lt;</span><span style="color: #0000ff">int</span><span style="color: #000000">&gt;</span><span style="color: #000000"> v2;<br>&nbsp;&nbsp;&nbsp; v2.push_back(</span><span style="color: #000000">1</span><span style="color: #000000">);<br>&nbsp;&nbsp;&nbsp; v2.push_back(</span><span style="color: #000000">2</span><span style="color: #000000">);<br>&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff">bool</span><span style="color: #000000"> r5 </span><span style="color: #000000">=</span><span style="color: #000000"> Compare</span><span style="color: #000000">&lt;</span><span style="color: #000000">vector</span><span style="color: #000000">&lt;</span><span style="color: #0000ff">int</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">&gt;</span><span style="color: #000000">::IsEqual(v1, v2);<br><br>&nbsp;&nbsp;&nbsp; </span><span style="color: #008000">//</span><span style="color: #008000"> custom template class </span><span style="color: #008000"><br></span><span style="color: #000000">&nbsp;&nbsp;&nbsp; SpecializedType</span><span style="color: #000000">&lt;</span><span style="color: #0000ff">float</span><span style="color: #000000">&gt;</span><span style="color: #000000"> s1 </span><span style="color: #000000">=</span><span style="color: #000000"> {</span><span style="color: #000000">10.1f</span><span style="color: #000000">,</span><span style="color: #000000">10.2f</span><span style="color: #000000">};<br>&nbsp;&nbsp;&nbsp; SpecializedType</span><span style="color: #000000">&lt;</span><span style="color: #0000ff">float</span><span style="color: #000000">&gt;</span><span style="color: #000000"> s2 </span><span style="color: #000000">=</span><span style="color: #000000"> {</span><span style="color: #000000">10.3f</span><span style="color: #000000">,</span><span style="color: #000000">10.0f</span><span style="color: #000000">};<br>&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff">bool</span><span style="color: #000000"> r6 </span><span style="color: #000000">=</span><span style="color: #000000"> Compare</span><span style="color: #000000">&lt;</span><span style="color: #000000">SpecializedType</span><span style="color: #000000">&lt;</span><span style="color: #0000ff">float</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">&gt;</span><span style="color: #000000">::IsEqual(s1, s2);<br></span></div><br><br>注：感谢longshanks对于本文中"类模板"与"模板类"概念的澄清，已更正 (2007-7-16)  <div class="postDesc">posted on 2007-07-04 21:40 <a href="http://www.cppblog.com/SmartPtr/">SmartPtr</a> 阅读(1842) <a href="http://www.cppblog.com/#Post">评论(10)</a>&nbsp; <a href="http://www.cppblog.com/SmartPtr/admin/EditPosts.aspx?postid=27496">编辑</a>&nbsp;<a href="http://www.cppblog.com/SmartPtr/AddToFavorite.aspx?id=27496">收藏</a> <a href="http://www.cppblog.com/SmartPtr/services/trackbacks/27496.aspx">引用</a> 所属分类: <a href="http://www.cppblog.com/SmartPtr/category/4632.html">06. 程序语言</a> </div></div><img height="1" src="http://www.cppblog.com/SmartPtr/aggbug/27496.html?webview=1" width="1">  <div id="AjaxHolder_UpdatePanel1"><a name="pagedcomment"></a><br><b>FeedBack:</b>  <div class="feedbackNoItems"></div> <div class="feedbackItem"> <div class="feedbackListTitle"><a title="permalink: re: C++模板类的三种特化[未登录]" href="http://www.cppblog.com/SmartPtr/archive/2007/07/04/27496.aspx#27519">#</a>&nbsp;<a name="27519"></a>re: C++模板类的三种特化[未登录]</div> <div class="feedbackListSubtitle">2007-07-05 11:23 | <a id="AjaxHolder_Comments_CommentList_ctl00_NameLink" target="_blank">yong</a><br> <div align="left">第二和第三种实际上就是template的"偏特化"或叫"部分特化"。这个概念不是什么新鲜的东东~ 呵呵&nbsp; <a href="http://www.cppblog.com/SmartPtr/archive/2007/07/04/27496.aspx#post">回复</a>&nbsp; <a title="查看该作者发表过的评论" href="http://www.cppblog.com/comment?author=yong" target="_blank">更多评论</a><br><a id="AjaxHolder_Comments_CommentList_ctl00_DeleteLink" href="http://www.cppblog.com/"></a>&nbsp; <a id="AjaxHolder_Comments_CommentList_ctl00_EditLink"></a></div></div></div> <div class="feedbackItem"> <div class="feedbackListTitle"><a title="permalink: re: C++模板类的三种特化" href="http://www.cppblog.com/SmartPtr/archive/2007/07/04/27496.aspx#27521">#</a>&nbsp;<a name="27521"></a>re: C++模板类的三种特化</div> <div class="feedbackListSubtitle">2007-07-05 11:53 | <a id="AjaxHolder_Comments_CommentList_ctl01_NameLink" href="http://www.cppblog.com/SmartPtr/" target="_blank">SmartPtr</a><br> <div align="left">从广义上来讲， 我觉得可以把这种情形归入模板偏特化。 <br>但是根据我们一般的理解，模板的偏特化是指需要根据模板的某些但不是全部的参数进行特化， 如下: <br>template&lt;class T1, class T2&gt; <br>class A <br>{ <br>} <br><br>template&lt;class T1&gt; <br>class A&lt;T1, int&gt; <br>{ <br>} <br><br>说实话， 我第一次发现第二和第三种用法时， 还是觉得挺新鲜的，这到底是属于全特化还是偏特化， 我也说不清楚， 但这也不重要，只要我们知道有这种用法，能应用它就行了&nbsp; <a href="http://www.cppblog.com/SmartPtr/archive/2007/07/04/27496.aspx#post">回复</a>&nbsp; <a title="查看该作者发表过的评论" href="http://www.cppblog.com/comment?author=SmartPtr" target="_blank">更多评论</a><br><a id="AjaxHolder_Comments_CommentList_ctl01_DeleteLink" href="http://www.cppblog.com/"></a>&nbsp; <a id="AjaxHolder_Comments_CommentList_ctl01_EditLink"></a></div></div></div> <div class="feedbackItem"> <div class="feedbackListTitle"><a title="permalink: re: C++模板类的三种特化" href="http://www.cppblog.com/SmartPtr/archive/2007/07/04/27496.aspx#27532">#</a>&nbsp;<a name="27532"></a>re: C++模板类的三种特化</div> <div class="feedbackListSubtitle">2007-07-05 15:57 | <a id="AjaxHolder_Comments_CommentList_ctl02_NameLink" href="http://www.cppblog.com/walkspeed/" target="_blank">walkspeed</a><br> <div align="left">模板有两种特化，全特化和偏特化（局部特化）<br>模板函数只能全特化，没有偏特化（以后可能有）。<br>模板类是可以全特化和偏特化的。<br><br>全特化，就是模板中模板参数全被指定为确定的类型。<br>全特化也就是定义了一个全新的类型，全特化的类中的函数可以与模板类不一样。<br><br>偏特化，就是模板中的模板参数没有被全部确定，需要编译器在编译时进行确定。<br><br>在类型上加上const、&amp;、*（ cosnt int、int&amp;、int*、等等）并没有产生新的类型。只是类型被修饰了。模板在编译时，可以得到这些修饰信息。<br><br>以上的2、3就是偏特化。&nbsp; <a href="http://www.cppblog.com/SmartPtr/archive/2007/07/04/27496.aspx#post">回复</a>&nbsp; <a title="查看该作者发表过的评论" href="http://www.cppblog.com/comment?author=walkspeed" target="_blank">更多评论</a><br><a id="AjaxHolder_Comments_CommentList_ctl02_DeleteLink" href="http://www.cppblog.com/"></a>&nbsp; <a id="AjaxHolder_Comments_CommentList_ctl02_EditLink"></a></div></div></div> <div class="feedbackItem"> <div class="feedbackListTitle"><a title="permalink: re: C++模板类的三种特化" href="http://www.cppblog.com/SmartPtr/archive/2007/07/04/27496.aspx#27534">#</a>&nbsp;<a name="27534"></a>re: C++模板类的三种特化</div> <div class="feedbackListSubtitle">2007-07-05 16:03 | <a id="AjaxHolder_Comments_CommentList_ctl03_NameLink" href="http://www.cppblog.com/walkspeed/" target="_blank">walkspeed</a><br> <div align="left">模板的特化是非常有用的。它像一个在编译期的条件判断。当编译器在编译时找到了符合的特化实现，就会使用这个特化实现。这就叫编译器多态（或者叫静态多态）。这种东西对编写基础库是很有用的。这也就是为何c++的基础库大量使用了模板技术，而且大量使用了特化，特别是偏特化。<br><br>在泛型中，利用特化类得到类新的特性，以便找到最适合这种特性的实现。而这一切都是在编译时完成。&nbsp; <a href="http://www.cppblog.com/SmartPtr/archive/2007/07/04/27496.aspx#post">回复</a>&nbsp; <a title="查看该作者发表过的评论" href="http://www.cppblog.com/comment?author=walkspeed" target="_blank">更多评论</a><br><a id="AjaxHolder_Comments_CommentList_ctl03_DeleteLink" href="http://www.cppblog.com/"></a>&nbsp; <a id="AjaxHolder_Comments_CommentList_ctl03_EditLink"></a></div></div></div> <div class="feedbackItem"> <div class="feedbackListTitle"><a title="permalink: re: C++模板类的三种特化" href="http://www.cppblog.com/SmartPtr/archive/2007/07/04/27496.aspx#27546">#</a>&nbsp;<a name="27546"></a>re: C++模板类的三种特化</div> <div class="feedbackListSubtitle">2007-07-05 17:30 | <a id="AjaxHolder_Comments_CommentList_ctl04_NameLink" href="http://www.cppblog.com/SmartPtr/" target="_blank">SmartPtr</a><br> <div align="left">谢谢walkspeed的回复， 我想对于全特化和偏特化这么理解应该是正确的， 就是全特化后确定了一个真正的类型， 而偏特化后其实还是一个原类型， 这样的话， 以上2， 3的确属于偏特化。 <br>模板的运用的确很广，无论模板元编程中的将计算提前到编译器，还是编译器多态（或者叫静态多态）， 都是非常漂亮聪明的应用， 在&lt;&lt;Modern C++ Design&gt;&gt;有着极好的体现。&nbsp; <a href="http://www.cppblog.com/SmartPtr/archive/2007/07/04/27496.aspx#post">回复</a>&nbsp; <a title="查看该作者发表过的评论" href="http://www.cppblog.com/comment?author=SmartPtr" target="_blank">更多评论</a><br><a id="AjaxHolder_Comments_CommentList_ctl04_DeleteLink" href="http://www.cppblog.com/"></a>&nbsp; <a id="AjaxHolder_Comments_CommentList_ctl04_EditLink"></a></div></div></div> <div class="feedbackItem"> <div class="feedbackListTitle"><a title="permalink: re: C++模板类的三种特化[未登录]" href="http://www.cppblog.com/SmartPtr/archive/2007/07/04/27496.aspx#28130">#</a>&nbsp;<a name="28130"></a>re: C++模板类的三种特化[未登录]</div> <div class="feedbackListSubtitle">2007-07-16 16:11 | <a id="AjaxHolder_Comments_CommentList_ctl05_NameLink" target="_blank">longshanks</a><br> <div align="left">如果这样分的话，还应该有第四种特化： <br>template&lt;typename T1, typename T2&gt; <br>class X {...}; <br><br>template&lt;typename T&gt; <br>class X&lt;T, int&gt; {...}; <br>以及2、3、4的混合 <br>template&lt;typename T&gt; <br>class X&lt;T, T*&gt; {...} <br>template&lt;typename T&gt; <br>class X&lt;vector&lt;T&gt;, T&amp;&gt; {...}; <br>... <br>更极端的，这样的特化是否该归为第5类呢： <br>template&lt;typename T&gt; <br>class Y; <br>template&lt;typename R, typename P1, typename P2&gt; <br>class Y&lt;R (P1, P2)&gt; {...};//针对带两个参数，有返回值的函数类型特化 <br><br>实际上，3仅仅是局部特化结合template-template parameter的一个应用。算不上一“种”特化。 <br>总的来说，还是C++标准中的分类更加清晰。 <br><br>另外，根据C++标准术语，应该是“类模板”（class template），而不是“模板类”。一般认为，“模板类”是模板实例化（特化）后的类： <br>vector&lt;int&gt;&nbsp; <a href="http://www.cppblog.com/SmartPtr/archive/2007/07/04/27496.aspx#post">回复</a>&nbsp; <a title="查看该作者发表过的评论" href="http://www.cppblog.com/comment?author=longshanks" target="_blank">更多评论</a><br><a id="AjaxHolder_Comments_CommentList_ctl05_DeleteLink" href="http://www.cppblog.com/"></a>&nbsp; <a id="AjaxHolder_Comments_CommentList_ctl05_EditLink"></a></div></div></div> <div class="feedbackItem"> <div class="feedbackListTitle"><a title="permalink: re: C++模板类的三种特化" href="http://www.cppblog.com/SmartPtr/archive/2007/07/04/27496.aspx#28150">#</a>&nbsp;<a name="28150"></a>re: C++模板类的三种特化</div> <div class="feedbackListSubtitle">2007-07-16 21:26 | <a id="AjaxHolder_Comments_CommentList_ctl06_NameLink" href="http://www.cppblog.com/SmartPtr/" target="_blank">SmartPtr</a><br> <div align="left">to longshanks <br><br>本文的目的其实并不是试图对C++的模板特化做一下全面的分类， 而是针对自己所遇到的，觉得比较有意思的，对于一个模板参数所能够做到的特化，并不想对C++中的全特化，偏特化有所混淆。当然，之间也得到了大家不少有价值的看法。尤其对于您所举的这个例子： <br>template&lt;typename T&gt; <br>class Y; <br>template&lt;typename R, typename P1, typename P2&gt; <br>class Y&lt;R (P1, P2)&gt; {...};//针对带两个参数，有返回值的函数类型特化 <br><br>是我之前所没有想到的，我只考虑了数据类型并没有考虑到函数类型，但是我想参考针对数据类型所做的分类，可以得到函数类型对应平行的分类。比如对于这个例子，应该可以理解为第三种：特化为另外一个类（函数）模板。 <br><br>PS： <br>谢谢关于模板类，类模板概念的澄清，原文已修改&nbsp; <a href="http://www.cppblog.com/SmartPtr/archive/2007/07/04/27496.aspx#post">回复</a>&nbsp; <a title="查看该作者发表过的评论" href="http://www.cppblog.com/comment?author=SmartPtr" target="_blank">更多评论</a><br><a id="AjaxHolder_Comments_CommentList_ctl06_DeleteLink" href="http://www.cppblog.com/"></a>&nbsp; <a id="AjaxHolder_Comments_CommentList_ctl06_EditLink"></a></div></div></div> <div class="feedbackItem"> <div class="feedbackListTitle"><a title="permalink: re: C++类模板的三种特化" href="http://www.cppblog.com/SmartPtr/archive/2007/07/04/27496.aspx#28351">#</a>&nbsp;<a name="28351"></a>re: C++类模板的三种特化</div> <div class="feedbackListSubtitle">2007-07-19 14:11 | <a id="AjaxHolder_Comments_CommentList_ctl07_NameLink" target="_blank">shen126</a><br> <div align="left">template&lt;class T&gt; <br>class Compare&lt;T*&gt; <br>{ <br>public: <br>static bool IsEqual(const T* lh, const T* rh) <br>{ <br>return Compare&lt;T&gt;::IsEqual(*lh, *rh); <br>} <br>}; <br><br>int _tmain(int argc, _TCHAR* argv[]) <br>{ <br><br>system("pause"); <br>return 0; <br>} <br>----- <br>为什么这段代码在VS2005里编译出错了呢，难道不支持，还是需要打开什么特殊开关符吗？ <br>&nbsp; <a href="http://www.cppblog.com/SmartPtr/archive/2007/07/04/27496.aspx#post">回复</a>&nbsp; <a title="查看该作者发表过的评论" href="http://www.cppblog.com/comment?author=shen126" target="_blank">更多评论</a><br><a id="AjaxHolder_Comments_CommentList_ctl07_DeleteLink" href="http://www.cppblog.com/"></a>&nbsp; <a id="AjaxHolder_Comments_CommentList_ctl07_EditLink"></a></div></div></div> <div class="feedbackItem"> <div class="feedbackListTitle"><a title="permalink: re: C++类模板的三种特化" href="http://www.cppblog.com/SmartPtr/archive/2007/07/04/27496.aspx#28352">#</a>&nbsp;<a name="28352"></a>re: C++类模板的三种特化</div> <div class="feedbackListSubtitle">2007-07-19 14:12 | <a id="AjaxHolder_Comments_CommentList_ctl08_NameLink" target="_blank">shen126</a><br> <div align="left">Error 1 error C2143: syntax error : missing ';' before '&lt;' e:\vs_projects\stltest1\stltest1\stltest1.cpp 7 <br>&nbsp; <a href="http://www.cppblog.com/SmartPtr/archive/2007/07/04/27496.aspx#post">回复</a>&nbsp; <a title="查看该作者发表过的评论" href="http://www.cppblog.com/comment?author=shen126" target="_blank">更多评论</a><br><a id="AjaxHolder_Comments_CommentList_ctl08_DeleteLink" href="http://www.cppblog.com/"></a>&nbsp; <a id="AjaxHolder_Comments_CommentList_ctl08_EditLink"></a></div></div></div> <div class="feedbackItem"> <div class="feedbackListTitle"><a title="permalink: re: C++类模板的三种特化" href="http://www.cppblog.com/SmartPtr/archive/2007/07/04/27496.aspx#28393">#</a>&nbsp;<a name="28393"></a>re: C++类模板的三种特化<a name="Post"></a></div> <div class="feedbackListSubtitle">2007-07-20 01:03 | <a id="AjaxHolder_Comments_CommentList_ctl09_NameLink" href="http://www.cppblog.com/SmartPtr/" target="_blank">SmartPtr</a><br> <div align="left">template&lt;class T&gt; <br>class Compare&lt;T*&gt; <br>{ <br>public: <br>static bool IsEqual(const T* lh, const T* rh) <br>{ <br>return Compare&lt;T&gt;::IsEqual(*lh, *rh); <br>} <br>}; <br>是模板特化， 你当然需要在之前定义其泛化版本&nbsp; <a href="http://www.cppblog.com/SmartPtr/archive/2007/07/04/27496.aspx#post">回复</a>&nbsp; <a title="查看该作者发表过的评论" href="http://www.cppblog.com/comment?author=SmartPtr" target="_blank">更多评论</a><br><a id="AjaxHolder_Comments_CommentList_ctl09_DeleteLink" href="http://www.cppblog.com/"></a>&nbsp; <a id="AjaxHolder_Comments_CommentList_ctl09_EditLink"></a></div></div></div></div></div></form><img src ="http://www.cppblog.com/woaidongmao/aggbug/60536.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/woaidongmao/" target="_blank">肥仔</a> 2008-08-31 21:51 <a href="http://www.cppblog.com/woaidongmao/archive/2008/08/31/60536.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>过度使用C++模板(overdoing C++ templates)</title><link>http://www.cppblog.com/woaidongmao/archive/2008/08/31/60534.html</link><dc:creator>肥仔</dc:creator><author>肥仔</author><pubDate>Sun, 31 Aug 2008 13:50:00 GMT</pubDate><guid>http://www.cppblog.com/woaidongmao/archive/2008/08/31/60534.html</guid><wfw:comment>http://www.cppblog.com/woaidongmao/comments/60534.html</wfw:comment><comments>http://www.cppblog.com/woaidongmao/archive/2008/08/31/60534.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/woaidongmao/comments/commentRss/60534.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/woaidongmao/services/trackbacks/60534.html</trackback:ping><description><![CDATA[<p>大约每隔十年，都会出现一个编程新概念，宣布自己是以往概念的继承者。我们也再一次相信，从今往后软件比以前更可靠，更容易build，或者更有意思(没有人相信它会比以前更小或者更快)。在70年代，有结构编程；在80年代，开始了面向对象编程；从90年代中期，出现了范型编程(generic programming)。范型编程得名于其用模板而使代码重用的高效技术(范型类和范型函数)。  <p>模板类和模板函数都是非常有用的工具。例如sqr()函数可以计算平方数，任何定义了乘法运算的数据类型（数字，矩阵）都适用。标准容器类(如list)都是模板，这样对于每个新类型无需重写了，这正是使用旧版的C++时真正头疼的事情，因此我认为ISO的标准是个伟大的进步。然而，在这个过程中有些东西用得过头了。  <p>例如：标准库中得string 和iostream 都是使用"character traits"类型作为参数。这意味着同一个basic_string&lt;&gt;类可以用于ASCII字符串，也可用于Unicode，甚至用于火星人的三字节字符串（原则虽然如此，但许多版本都只是实现了ASCII字符串，看起来有点滑稽）。标准要求这些常用类必须实现成模板形式，而这些类几乎涉及到所有C++应用。  <p>但是这对性能和调试会带来许多麻烦。下面几个试验解释了这个问题（本试验使用的编译器为VC++6.0)。编译器同时支持新风格的iostream（使用模板）和经典风格的iostream, 因此我们能比较他们二者的版本实现。第一个测试程序当然是使用"Hello, Word"了，新风格的编译时间是经典风格的2倍。另一个更正规的例子大约有200行，每行输出10个变量用于计数。这个测试程序最显著的结论是编译速度：新风格版本花了10秒编译完成，而旧版本只使用了1.5秒。10秒时间可并不少，可以完成很多事情。另外，新风格版本的可执行文件的大小为115K，而旧版本只有70K。你的测试数据可能有些出入，但是整体结论是一样的：当使用新版本时，会有更慢的编译速度和更大的可执行文件。这并不是因为微软公司编译器的问题，使用GCC测试也会得到同样的结论。  <p>当然，和过去不一样，可执行文件的大小并不是那么重要，现在，可编程设备种类正快速增长，包括许多信息应用，如遥控、手机、智能冰箱、基于蓝牙技术的咖啡机等等，在这些应用中内存近几年都会是十分宝贵的资源。使用标准iostream 而产生的额外的二进制文件，来源于内联了整个模板类的代码，要是没有code bload工具，你很难优化那些重要的操作。对我来说，编译时间问题更严重一些，因为这样意味着更长的等待，从而失去了开发中非常重要原则：互动原则。  <p>现在我们来考虑调试的问题。标准库中string 类的模板实现非常聪明，但并不适合于调试。你会面临使用超长名字的编译器和调试器的信息： <pre>class std::basic_string&lt;char,struct std::char_traits&lt;char&gt;,class std::allocator&lt;char&gt;&gt;</pre><pre></pre>
<p>同样对于非常有用的容器 map &lt; string,string &gt; , 你可以去想象其复杂性。这些名字太长了，以至于产生数十个内部名字被截断的警告。对于初学者来说，std::string 应该设计得尽可能透明，而不应该让他们面临许多语言内置得一些特性。当输出了编译错误信息后，在技术上讲，应该是可以查找到所有的 typedef 。我在 UnderC 项目中就试图这么做。Verity Stob 建议编写一个后置的处理器来翻译这些错误信息，我倒希望这是她这么做只是开个玩笑。如果不使用这么复杂的类型，这个问题就会容易处理的多。我在C++开发上的秘诀就是（我首次坦诚的公开这个秘密): 在稍微大一点的工程中使用一个兼容的string 类来替换std::string 的头文件. 有时我会重新build 这些标准的头文件，用来检测是否我的库还能正常使用，但让其他人为如何提高其性能而努力。 
<p>当然，在许多应用中我们都需要这种std::string提供的灵活性，例如，需要同时处理ASCII 和Unicode字符串，或者需要定制自己的allocator 等等。但这并不是普遍需求(通常程序员要么只处理ASCII，要么只处理Unicode ), 看起来对于程序员承担这种范型机制有些不公平。这种机制确实让标准库的设计者觉得很有意思，但增加了应用开发程序员使用的复杂度。这似乎颠倒了这个原则：良好的标准库设计应该隐藏其实现的复杂度，而让用户直接使用。但std::string 对其实现的复杂度隐藏得并不够，导致在用户使用过程中不断的遇到设计中的问题。我们不能要求标准库的用户都是专家。标准坚持要求这种特定的实现方式，和标准库的设计初衷相违背，其初衷是只提供公共的接口和包含一些特定功能的类库。自然，这种范型模板对于那些真正去要他们的人是一直有效的。 
<p>这些细节考虑同样应用于标准容器，例如list&lt;&gt;容器，list 有一些额外的默认模板参数，用于定义了默认的allocator。当然自己定义allocator 十分有用，但绝大多数人不需要自己去实现。这些泛化的版本完全可以作为单独的模板提供。我承认这样做会让标准库的设计在技术上变得没有以前有意思，但这些库在设计之初就应该考虑到最终用户。篡改一下C++的颂歌：用户不应该为他们不需要的东西买单。 
<p>当我们不需要模板的时候，我们不得不使用模板。除此之外，在C＋＋中用范型编程还会遇到另一个的问题。大多数人都同意，标准的algorithm 十分有用。如果你有一个整型的vector, 你可以直接使用下面的语句来排序： <pre>sort(v.begin(),v.end());</pre><pre></pre>
<p>因为int型数据的比较函数时内联的，而且这种范型算法比旧版本的qsort()函数速度还快，也更容易使用，特别是使用用户自定义类型的vector. copy()函数也可以在任何时候高效率地拷贝任何数据。 
<p>但有些应用理解起来十分晦涩： <pre>copy_if(v.begin(),v.end(),ostream_iterator&lt;int&gt;(cout) bind2nd(greater&lt;int&gt;(),7));</pre><pre></pre>
<p>如果要写得严格一点，每个名字都应该加上std::前缀，这里假定所有变量都是使用全局命名空间，或单独使用命令或用其他方法。用Stroustrup (C++的创始人)的例子更容易说明问题，这个例子把所有的整型数输出到终端： <pre>vector&lt;int&gt;::iterator li;
for (li = v.begin(); li != v.end(); ++li)
if (*li &gt; 7) cout &lt;&lt; *li;</pre><pre></pre>
<p>Stroustrup 告诉我们如果使用显示的循环是"麻烦而又容易产生错误", 但我看不出使用第一个版本有什么优势。显然，人们能习惯这种方式，人类的适应性很强，作为专业人士，我们也不得不学习这个新概念。但是，这样做并没有减少多少麻烦，而且我们可以证明这样做可读性更差，更不灵活。同时，它还会限制你的设计。例如，假设我们有一个Shape * 的指针list, 我们可以通过下面的调用方式来画出他们自己的形状： <pre>for_each(ls.begin(),ls.end(),
bind2nd(mem_fun(&amp;Shape::draw),canvas));</pre><pre></pre>
<p>也可以选择这种方式： <pre>ShapeList::iterator li;
for (li = ls.begin(); li != ls.end(); ++li)
(*li)-&gt;draw(canvas);</pre><pre></pre>
<p>现在假设我需要修改我的设计，我只想画那些满足某种要求的图形（而且不希望把这些需求包在shape类里面), 那么我只需要在显式的循环中增加一条if条件语句。如果要使用范型概念，我唯一能想到的方式定义一个函数，然后使用for_each()算法。使用设计模式一书中的术语，第一个例子是一个内部迭代器(internal iterator)，第二个例子式一个外部跌倒器(external iterator). 作者认为C++ 并不擅长使用内部迭代器，我想我们还是应该考虑语言的局限性。其实问题在于在C++中过度应用范型概念--从而导致不必要的难度。C++ 完全不支持一般的匿名函数(anonymous functions)如LIST, SmallTalk, Ruby等。C++中的匿名函数或许看起来和下面一样，可能某天有人会实现它： <pre>for_each(ls.begin(),ls.end(),
void lambda(Shape *p) { p-&gt;draw(canvas); }); </pre><pre></pre>
<p>C++ 是一种不可思议的编程语言，小到手机，大到跨国际网络，都有其应用。它非常灵活，能够支持多种编程风格，但这种灵活同样也是其问题所在。编程的艺术在于为特定的问题选择合适编程风格，就像老师总提醒写作文是要选择好的风格一样。我并不想诋毁 C++ 标准库，这里面包含了许多人的辛勤劳动，并为大家提供了一个公共平台。我对于这个标准的态度是，它和范型编程联系过于紧密，从而变成了在说明什么风格是好的编程风格(例如，算法中明显倾向于不要使用显式循环), 同时它也让程序员们不得不介入一些实现细节(如basic_string&lt;&gt;)，这样做让人们更加觉得C++ 是只是内核工程师们的编程语言。 </p><img src ="http://www.cppblog.com/woaidongmao/aggbug/60534.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/woaidongmao/" target="_blank">肥仔</a> 2008-08-31 21:50 <a href="http://www.cppblog.com/woaidongmao/archive/2008/08/31/60534.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>模板参数名命名惯例</title><link>http://www.cppblog.com/woaidongmao/archive/2008/08/31/60535.html</link><dc:creator>肥仔</dc:creator><author>肥仔</author><pubDate>Sun, 31 Aug 2008 13:50:00 GMT</pubDate><guid>http://www.cppblog.com/woaidongmao/archive/2008/08/31/60535.html</guid><wfw:comment>http://www.cppblog.com/woaidongmao/comments/60535.html</wfw:comment><comments>http://www.cppblog.com/woaidongmao/archive/2008/08/31/60535.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/woaidongmao/comments/commentRss/60535.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/woaidongmao/services/trackbacks/60535.html</trackback:ping><description><![CDATA[<form id="Form1" name="Form1" action="http://www.cppblog.com/TemplateParameterNames.html" method="post" _initialAction="TemplateParameterNames.html"> <div id="main"> <div class="post"> <div class="postText">模板参数名命名惯例<br><br>以下模板参数名命名惯例来自于stlsoft，详细说明于《Extended STL》。<br><br>模板参数一般是一个或者两个大写字母，<br>例如T（type/value-type）、S（sequence/string）、<br>C（container/character）、VP（value policy type）等等。<br><br>这样做有两个原因。<br><br>首先，全大写字母的单词可能被宏定义。<br>相反，宏定义一般不会仅有一个或两个字符。<br>所以模板参数和宏定义没有命名冲突。<br><br>（我们不应该自定义特别短的宏。<br>如果一个库定义了一两个字符的短宏，<br>一般来说，它绝不会是一个可靠的库。）<br><br>第二，我们将在类中定义成员类型，其名字必须不同于模板参数名。<br><br>以下代码中，成员类型和模板参数同名，无法通过编译：<br><br><span style="font-family: courier new">template &lt;typename iterator&gt;</span><br style="font-family: courier new"><span style="font-family: courier new">struct thing</span><br style="font-family: courier new"><span style="font-family: courier new">{</span><br style="font-family: courier new"><span style="font-family: courier new">&nbsp;&nbsp;&nbsp; typedef iterator iterator; // Compile error</span><br style="font-family: courier new"><span style="font-family: courier new">};</span><br><br>必须如下代码更改：<br><br><span style="font-family: courier new">template &lt;typename I&gt;</span><br style="font-family: courier new"><span style="font-family: courier new">struct thing</span><br style="font-family: courier new"><span style="font-family: courier new">{</span><br style="font-family: courier new"><span style="font-family: courier new">&nbsp;&nbsp;&nbsp; typedef I iterator;</span><br style="font-family: courier new"><span style="font-family: courier new">};</span><br><br>在定义模板类时，有一个惯例，<br>即一开始就以上面短小的模板参数名为基础，<br>定义各个成员类型。<br><br><br>查看StlPort代码：<br><br><span style="font-family: courier new">template &lt;class _Key, class _Tp, ...&gt;</span><br style="font-family: courier new"><span style="font-family: courier new">class map</span><br style="font-family: courier new"><span style="font-family: courier new">{</span><br style="font-family: courier new"><span style="font-family: courier new">&nbsp; typedef map&lt;_Key, _Tp, _Compare, _Alloc&gt; _Self;</span><br style="font-family: courier new"><span style="font-family: courier new">public:</span><br style="font-family: courier new"><span style="font-family: courier new">&nbsp; typedef _Key&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; key_type;</span><br style="font-family: courier new"><span style="font-family: courier new">&nbsp; typedef _Tp&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; data_type;</span><br style="font-family: courier new"><span style="font-family: courier new">&nbsp; typedef _Tp&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mapped_type;</span><br style="font-family: courier new"><span style="font-family: courier new">&nbsp; typedef pair&lt;const _Key, _Tp&gt; value_type;</span><br style="font-family: courier new"><span style="font-family: courier new">&nbsp; typedef _Compare&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; key_compare;</span><br style="font-family: courier new"><br style="font-family: courier new"><span style="font-family: courier new">&nbsp; ...</span><br style="font-family: courier new"><span style="font-family: courier new">}</span><br><br>其模板参数命名的原则是一致的：较短，然后立即定义较长的类型名。<br>用前导下划线防止命名冲突。<br><br>（转载请注明来源于金庆的专栏） <br></div> <div class="postfoot">posted on 2008-04-21 17:25 <a href="http://www.cppblog.com/jinq0123/">金庆</a> 阅读(1380) <a href="http://www.cppblog.com/#Post">评论(10)</a>&nbsp; <a href="http://www.cppblog.com/jinq0123/admin/EditPosts.aspx?postid=47742">编辑</a>&nbsp;<a href="http://www.cppblog.com/jinq0123/AddToFavorite.aspx?id=47742">收藏</a> <a href="http://www.cppblog.com/jinq0123/services/trackbacks/47742.aspx">引用</a> 所属分类: <a href="http://www.cppblog.com/jinq0123/category/5137.html">1. C/C++</a> </div></div><img height="1" src="http://www.cppblog.com/jinq0123/aggbug/47742.html?webview=1" width="1">  <div id="AjaxHolder_UpdatePanel1"><a name="pagedcomment"></a><a name="评论"><br> <div id="comments"> <h3>评论</h3> <div class="post"> <div class="postTitle"><a title="permalink: re: 模板参数名命名惯例" href="http://www.cppblog.com/jinq0123/archive/2008/04/21/TemplateParameterNames.html#47755">#</a>&nbsp;<a name="47755"></a>re: 模板参数名命名惯例 <span>2008-04-21 19:34 </span><a id="AjaxHolder_Comments_CommentList_ctl00_NameLink" href="http://www.cnitlblog.com/cockerel" target="_blank">踏雪赤兔</a> </div> <div class="postText">没必要为你那些过时的宏定义搞成这样吧，这样严重地损害了代码可读性。 <br>P.S.：与其参考stlsoft，还不如参考SGI STL更好吧，这也是侯捷的选择&nbsp; <a href="http://www.cppblog.com/jinq0123/archive/2008/04/21/TemplateParameterNames.html#post">回复</a>&nbsp; <a title="查看该作者发表过的评论" href="http://www.cppblog.com/comment?author=%e8%b8%8f%e9%9b%aa%e8%b5%a4%e5%85%94" target="_blank">更多评论</a> <br><a id="AjaxHolder_Comments_CommentList_ctl00_DeleteLink" href="http://www.cppblog.com/"></a>&nbsp; <a id="AjaxHolder_Comments_CommentList_ctl00_EditLink"></a> </div></div><br> <div class="post"> <div class="postTitle"><a title="permalink: re: 模板参数名命名惯例" href="http://www.cppblog.com/jinq0123/archive/2008/04/21/TemplateParameterNames.html#47756">#</a>&nbsp;<a name="47756"></a>re: 模板参数名命名惯例 <span>2008-04-21 19:56 </span><a id="AjaxHolder_Comments_CommentList_ctl01_NameLink" href="http://www.cppblog.com/firectrl/" target="_blank">王晓轩</a> </div> <div class="postText">同意楼上的，SGI 的STL实现可以说是可读性最好的～～ <br>&nbsp; <a href="http://www.cppblog.com/jinq0123/archive/2008/04/21/TemplateParameterNames.html#post">回复</a>&nbsp; <a title="查看该作者发表过的评论" href="http://www.cppblog.com/comment?author=%e7%8e%8b%e6%99%93%e8%bd%a9" target="_blank">更多评论</a> <br><a id="AjaxHolder_Comments_CommentList_ctl01_DeleteLink" href="http://www.cppblog.com/"></a>&nbsp; <a id="AjaxHolder_Comments_CommentList_ctl01_EditLink"></a> </div></div><br> <div class="post"> <div class="postTitle"><a title="permalink: re: 模板参数名命名惯例" href="http://www.cppblog.com/jinq0123/archive/2008/04/21/TemplateParameterNames.html#47766">#</a>&nbsp;<a name="47766"></a>re: 模板参数名命名惯例 <span>2008-04-21 22:12 </span><a id="AjaxHolder_Comments_CommentList_ctl02_NameLink" href="http://www.cppblog.com/feng/" target="_blank">Wang Feng</a> </div> <div class="postText">说起宏定义，其实在文件前面定义，用完了之后在文件最后取消是个很好的习惯<br>比如<br><br>#define PI 3.1415926535897932384626433<br>.....<br><br>#undef PI&nbsp; <a href="http://www.cppblog.com/jinq0123/archive/2008/04/21/TemplateParameterNames.html#post">回复</a>&nbsp; <a title="查看该作者发表过的评论" href="http://www.cppblog.com/comment?author=Wang+Feng" target="_blank">更多评论</a> <br><a id="AjaxHolder_Comments_CommentList_ctl02_DeleteLink" href="http://www.cppblog.com/"></a>&nbsp; <a id="AjaxHolder_Comments_CommentList_ctl02_EditLink"></a> </div></div><br> <div class="post"> <div class="postTitle"><a title="permalink: re: 模板参数名命名惯例" href="http://www.cppblog.com/jinq0123/archive/2008/04/21/TemplateParameterNames.html#47784">#</a>&nbsp;<a name="47784"></a>re: 模板参数名命名惯例 <span>2008-04-22 08:38 </span><a id="AjaxHolder_Comments_CommentList_ctl03_NameLink" href="http://www.cppblog.com/kevinlynx/" target="_blank">Kevin Lynx</a> </div> <div class="postText">原来模板中会优先使用宏。 <br><br>说实话，作为开源fans，我有点看不惯“（转载请注明来源于金庆的专栏）”这句话。个人感受。&nbsp; <a href="http://www.cppblog.com/jinq0123/archive/2008/04/21/TemplateParameterNames.html#post">回复</a>&nbsp; <a title="查看该作者发表过的评论" href="http://www.cppblog.com/comment?author=Kevin+Lynx" target="_blank">更多评论</a> <br><a id="AjaxHolder_Comments_CommentList_ctl03_DeleteLink" href="http://www.cppblog.com/"></a>&nbsp; <a id="AjaxHolder_Comments_CommentList_ctl03_EditLink"></a> </div></div><br> <div class="post"> <div class="postTitle"><a title="permalink: re: 模板参数名命名惯例" href="http://www.cppblog.com/jinq0123/archive/2008/04/21/TemplateParameterNames.html#47793">#</a>&nbsp;<a name="47793"></a>re: 模板参数名命名惯例 <span>2008-04-22 09:38 </span><a id="AjaxHolder_Comments_CommentList_ctl04_NameLink" href="http://www.cppblog.com/jinq0123/" target="_blank">金庆</a> </div> <div class="postText">@踏雪赤兔<br>SGI STL与StlPort的代码是很相似的，如上述map的定义几乎一样，只是stlport多了些对平台的判断，移植性好点。应该不算“严重地损害了代码可读性”。&nbsp; <a href="http://www.cppblog.com/jinq0123/archive/2008/04/21/TemplateParameterNames.html#post">回复</a>&nbsp; <a title="查看该作者发表过的评论" href="http://www.cppblog.com/comment?author=%e9%87%91%e5%ba%86" target="_blank">更多评论</a> <br><a id="AjaxHolder_Comments_CommentList_ctl04_DeleteLink" href="http://www.cppblog.com/"></a>&nbsp; <a id="AjaxHolder_Comments_CommentList_ctl04_EditLink"></a> </div></div><br> <div class="post"> <div class="postTitle"><a title="permalink: re: 模板参数名命名惯例" href="http://www.cppblog.com/jinq0123/archive/2008/04/21/TemplateParameterNames.html#47794">#</a>&nbsp;<a name="47794"></a>re: 模板参数名命名惯例 <span>2008-04-22 09:43 </span><a id="AjaxHolder_Comments_CommentList_ctl05_NameLink" href="http://www.cppblog.com/jinq0123/" target="_blank">金庆</a> </div> <div class="postText">@Wang Feng<br>取消宏定义是一种方法，这样该宏只能用于当前文件。&nbsp; <a href="http://www.cppblog.com/jinq0123/archive/2008/04/21/TemplateParameterNames.html#post">回复</a>&nbsp; <a title="查看该作者发表过的评论" href="http://www.cppblog.com/comment?author=%e9%87%91%e5%ba%86" target="_blank">更多评论</a> <br><a id="AjaxHolder_Comments_CommentList_ctl05_DeleteLink" href="http://www.cppblog.com/"></a>&nbsp; <a id="AjaxHolder_Comments_CommentList_ctl05_EditLink"></a> </div></div><br> <div class="post"> <div class="postTitle"><a title="permalink: re: 模板参数名命名惯例" href="http://www.cppblog.com/jinq0123/archive/2008/04/21/TemplateParameterNames.html#47797">#</a>&nbsp;<a name="47797"></a>re: 模板参数名命名惯例 <span>2008-04-22 09:52 </span><a id="AjaxHolder_Comments_CommentList_ctl06_NameLink" href="http://www.cppblog.com/jinq0123/" target="_blank">金庆</a> </div> <div class="postText">@Kevin Lynx<br>我的观点是，开源需要亮出自己的名号．<br>"转载请注明来源于金庆的专栏"是为了方便读者找到原文出处．&nbsp; <a href="http://www.cppblog.com/jinq0123/archive/2008/04/21/TemplateParameterNames.html#post">回复</a>&nbsp; <a title="查看该作者发表过的评论" href="http://www.cppblog.com/comment?author=%e9%87%91%e5%ba%86" target="_blank">更多评论</a> <br><a id="AjaxHolder_Comments_CommentList_ctl06_DeleteLink" href="http://www.cppblog.com/"></a>&nbsp; <a id="AjaxHolder_Comments_CommentList_ctl06_EditLink"></a> </div></div><br> <div class="post"> <div class="postTitle"><a title="permalink: re: 模板参数名命名惯例" href="http://www.cppblog.com/jinq0123/archive/2008/04/21/TemplateParameterNames.html#47812">#</a>&nbsp;<a name="47812"></a>re: 模板参数名命名惯例 <span>2008-04-22 13:19 </span><a id="AjaxHolder_Comments_CommentList_ctl07_NameLink" href="http://www.cppblog.com/eXile/" target="_blank">eXile</a> </div> <div class="postText">我觉得作为开源的fans，应该更加注重版权的意识。&nbsp; <a href="http://www.cppblog.com/jinq0123/archive/2008/04/21/TemplateParameterNames.html#post">回复</a>&nbsp; <a title="查看该作者发表过的评论" href="http://www.cppblog.com/comment?author=eXile" target="_blank">更多评论</a> <br><a id="AjaxHolder_Comments_CommentList_ctl07_DeleteLink" href="http://www.cppblog.com/"></a>&nbsp; <a id="AjaxHolder_Comments_CommentList_ctl07_EditLink"></a> </div></div><br> <div class="post"> <div class="postTitle"><a title="permalink: re: 模板参数名命名惯例" href="http://www.cppblog.com/jinq0123/archive/2008/04/21/TemplateParameterNames.html#47868">#</a>&nbsp;<a name="47868"></a>re: 模板参数名命名惯例 <span>2008-04-23 09:08 </span><a id="AjaxHolder_Comments_CommentList_ctl08_NameLink" href="http://www.cppblog.com/kevinlynx/" target="_blank">Kevin Lynx</a> </div> <div class="postText">@金庆 <br>这样的话我还是很赞同的。&nbsp; <a href="http://www.cppblog.com/jinq0123/archive/2008/04/21/TemplateParameterNames.html#post">回复</a>&nbsp; <a title="查看该作者发表过的评论" href="http://www.cppblog.com/comment?author=Kevin+Lynx" target="_blank">更多评论</a> <br><a id="AjaxHolder_Comments_CommentList_ctl08_DeleteLink" href="http://www.cppblog.com/"></a>&nbsp; <a id="AjaxHolder_Comments_CommentList_ctl08_EditLink"></a> </div></div><br> <div class="post"> <div class="postTitle"><a title="permalink: re: 模板参数名命名惯例" href="http://www.cppblog.com/jinq0123/archive/2008/04/21/TemplateParameterNames.html#48141">#</a>&nbsp;<a name="48141"></a>re: 模板参数名命名惯例<a name="Post"></a> <span>2008-04-25 17:22 </span><a id="AjaxHolder_Comments_CommentList_ctl09_NameLink" href="http://www.cppblog.com/ant" target="_blank">#Ant</a> </div> <div class="postText">SGI STL的可读性还是最好的，Wang Feng说的那种宏定义方法也是boost库里面经常用的。&nbsp; <a href="http://www.cppblog.com/jinq0123/archive/2008/04/21/TemplateParameterNames.html#post">回复</a>&nbsp; <a title="查看该作者发表过的评论" href="http://www.cppblog.com/comment?author=%23Ant" target="_blank">更多评论</a> <br></div></div></div></div></div></form><img src ="http://www.cppblog.com/woaidongmao/aggbug/60535.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/woaidongmao/" target="_blank">肥仔</a> 2008-08-31 21:50 <a href="http://www.cppblog.com/woaidongmao/archive/2008/08/31/60535.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>error C2899: 不能在模板声明之外使用类型名称 ?!!</title><link>http://www.cppblog.com/woaidongmao/archive/2008/08/31/60533.html</link><dc:creator>肥仔</dc:creator><author>肥仔</author><pubDate>Sun, 31 Aug 2008 13:48:00 GMT</pubDate><guid>http://www.cppblog.com/woaidongmao/archive/2008/08/31/60533.html</guid><wfw:comment>http://www.cppblog.com/woaidongmao/comments/60533.html</wfw:comment><comments>http://www.cppblog.com/woaidongmao/archive/2008/08/31/60533.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/woaidongmao/comments/commentRss/60533.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/woaidongmao/services/trackbacks/60533.html</trackback:ping><description><![CDATA[<form id="Form1" name="Form1" action="http://www.cppblog.com/414.html" method="post" _initialAction="414.html"> <div id="main"> <div class="post"> <div class="postText"><font face="Verdana" size="2">前天碰到一个问题,当时想着挺纳闷的,不知道是什么原因.对"不能在模板声明之外使用类型名称"这样的提示你会想到是什么?我在无意中按F1键看到MSDN中的描述才明白是typename关键字用错了,是看它的英文描述才知道的:"<strong>typename cannot be used outside a template declaration</strong>".真想不到typename会翻译为类型名称.看来,以后有莫名其妙的错误还是得看英文的帮助文档啊,不过最好一开始就有英文版的VS.NET.<br>以下是具体的描述:</font><br><br> <div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><font size="2"><font face="Verdana"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"><span style="color: #0000ff">namespace</span></font></font><font size="2"><font face="Verdana"><span style="color: #000000"> code<br><img id="Codehighlighter1_15_664_Open_Image" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top"><img id="Codehighlighter1_15_664_Closed_Image" style="display: none" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align="top"></span><span id="Codehighlighter1_15_664_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span></font></font><span id="Codehighlighter1_15_664_Open_Text"><font size="2"><font face="Verdana"><span style="color: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top"><br><img id="Codehighlighter1_32_49_Open_Image" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"><img id="Codehighlighter1_32_49_Closed_Image" style="display: none" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align="top"></span><span style="color: #0000ff">enum</span><span style="color: #000000"> CodeType </span><span id="Codehighlighter1_32_49_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id="Codehighlighter1_32_49_Open_Text"><span style="color: #000000">{ UTF_8, UNICODE }</span></span></font></font><font size="2"><font face="Verdana"><span style="color: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">template</span><span style="color: #000000">&lt;</span><span style="color: #000000"> CodeType srcT, CodeType desT </span><span style="color: #000000">&gt;</span></font></font><span style="color: #000000"><br><font face="Verdana" size="2"><img id="Codehighlighter1_112_113_Open_Image" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"><img id="Codehighlighter1_112_113_Closed_Image" style="display: none" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align="top"></font></span><font size="2"><font face="Verdana"><span style="color: #0000ff">struct</span><span style="color: #000000"> ConvertType</span><span id="Codehighlighter1_112_113_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id="Codehighlighter1_112_113_Open_Text"><span style="color: #000000">{}</span></span></font></font><font size="2"><font face="Verdana"><span style="color: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">template</span><span style="color: #000000">&lt;&gt;</span></font></font><span style="color: #000000"><br><font face="Verdana" size="2"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top"></font></span><font size="2"><font face="Verdana"><span style="color: #0000ff">struct</span><span style="color: #000000"> ConvertType </span><span style="color: #000000">&lt;</span><span style="color: #000000"> UTF_8, UNICODE </span><span style="color: #000000">&gt;</span></font></font><span style="color: #000000"><br><font face="Verdana" size="2"><img id="Codehighlighter1_166_217_Open_Image" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"><img id="Codehighlighter1_166_217_Closed_Image" style="display: none" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align="top"></font></span><span id="Codehighlighter1_166_217_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><font face="Verdana" size="2"><img src="http://www.cppblog.com/Images/dot.gif"></font></span><span id="Codehighlighter1_166_217_Open_Text"><font size="2"><font face="Verdana"><span style="color: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp; typedef </span><span style="color: #0000ff">char</span></font></font><span style="color: #000000"><font face="Verdana" size="2"> srcType;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp; typedef wchar_t desType;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top">}</font></span></span><font size="2"><font face="Verdana"><span style="color: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">template</span><span style="color: #000000">&lt;</span><span style="color: #000000"> CodeType srcT, CodeType desT </span><span style="color: #000000">&gt;</span></font></font><span style="color: #000000"><br><font face="Verdana" size="2"><img id="Codehighlighter1_277_278_Open_Image" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"><img id="Codehighlighter1_277_278_Closed_Image" style="display: none" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align="top"></font></span><font size="2"><font face="Verdana"><span style="color: #0000ff">struct</span><span style="color: #000000"> Convert </span><span id="Codehighlighter1_277_278_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id="Codehighlighter1_277_278_Open_Text"><span style="color: #000000">{}</span></span></font></font><font size="2"><font face="Verdana"><span style="color: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">template</span><span style="color: #000000">&lt;&gt;</span></font></font><span style="color: #000000"><br><font face="Verdana" size="2"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top"></font></span><font size="2"><font face="Verdana"><span style="color: #0000ff">struct</span><span style="color: #000000"> Convert</span><span style="color: #000000">&lt;</span><span style="color: #000000"> UTF_8, UNICODE </span><span style="color: #000000">&gt;</span></font></font><span style="color: #000000"><br><font face="Verdana" size="2"><img id="Codehighlighter1_326_660_Open_Image" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"><img id="Codehighlighter1_326_660_Closed_Image" style="display: none" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align="top"></font></span><span id="Codehighlighter1_326_660_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><font face="Verdana" size="2"><img src="http://www.cppblog.com/Images/dot.gif"></font></span><span id="Codehighlighter1_326_660_Open_Text"><font size="2"><font face="Verdana"><span style="color: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp; </span><span style="color: #008000">//</span><span style="color: #008000">error C2899: 不能在模板声明之外使用类型名称</span></font></font><span style="color: #008000"><br><font face="Verdana" size="2"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top"></font></span><font size="2"><font face="Verdana"><span style="color: #000000">&nbsp;&nbsp;&nbsp; typedef typename ConvertType</span><span style="color: #000000">&lt;</span><span style="color: #000000"> UTF_8, UNICODE </span><span style="color: #000000">&gt;</span><span style="color: #000000">::srcType srcType;&nbsp;&nbsp;&nbsp; </span><span style="color: #008000">//</span><span style="color: #008000">!</span></font></font><span style="color: #008000"><br><font face="Verdana" size="2"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top"></font></span><font size="2"><font face="Verdana"><span style="color: #000000">&nbsp;&nbsp;&nbsp; typedef typename ConvertType</span><span style="color: #000000">&lt;</span><span style="color: #000000"> UTF_8, UNICODE </span><span style="color: #000000">&gt;</span><span style="color: #000000">::desType desType;&nbsp;&nbsp;&nbsp; </span><span style="color: #008000">//</span><span style="color: #008000">!</span></font></font><span style="color: #008000"><br><font face="Verdana" size="2"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top"></font></span><span style="color: #000000"><font face="Verdana" size="2"><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top">}</font></span></span><span style="color: #000000"><font face="Verdana" size="2">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top">}</font></span></span><font size="2"><font face="Verdana"><span style="color: #000000">&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">namespace code</span></font></font><span style="color: #008000"><br><font face="Verdana" size="2"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"></font></span><span style="color: #000000"><br><font face="Verdana" size="2"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"><br><img id="Codehighlighter1_685_1207_Open_Image" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top"><img id="Codehighlighter1_685_1207_Closed_Image" style="display: none" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align="top"></font></span><span id="Codehighlighter1_685_1207_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><font face="Verdana" size="2">/**/</font></span><span id="Codehighlighter1_685_1207_Open_Text"><span style="color: #008000"><font face="Verdana" size="2">/*</font></span><span style="color: #008000"><br><font face="Verdana" size="2"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">这里根本不需要typename.<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">typename除用在模板声明中外,只能用于说明模板类的成员是一个类型.<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">例如:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">template<typename &#160;T> class X {};<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">// Another way<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">template<class &#160;T> struct X {<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp; typedef double DoubleType;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp; typename X<t>::DoubleType a;&nbsp;&nbsp; // T::A is a type<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">};<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">而如果不是模板类,则不能用typename.这时,它并不是多余的,而是一定不能要的.<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">例如:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">template&lt;&gt; struct X&lt; X<int> &gt; {<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp; typename X<int>::DoubleType a;&nbsp;&nbsp;&nbsp; //Error! X<int> is not a generic class<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp; X<int>::DoubleType b;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //OK!<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">};<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">我前面的代码也是这样的情况,ConvertType&lt; UTF_8, UNICODE &gt;已经是一个具体的类了,不要是模板类,所以ConvertType&lt; UTF_8, UNICODE &gt;::srcType前不能加typename.<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top"></font></span><span style="color: #008000"><font face="Verdana" size="2">*/</font></span></span></div></div> <div class="postfoot">posted on 2005-09-24 15:49 <a href="http://www.cppblog.com/kb/">可冰</a> 阅读(462) <a href="http://www.cppblog.com/#Post">评论(5)</a>&nbsp; <a href="http://www.cppblog.com/kb/admin/EditPosts.aspx?postid=414">编辑</a>&nbsp;<a href="http://www.cppblog.com/kb/AddToFavorite.aspx?id=414">收藏</a> <a href="http://www.cppblog.com/kb/services/trackbacks/414.aspx">引用</a> 所属分类: <a href="http://www.cppblog.com/kb/category/53.html">C++</a> </div></div><img height="1" src="http://www.cppblog.com/kb/aggbug/414.html?webview=1" width="1">  <div id="AjaxHolder_UpdatePanel1"><a name="pagedcomment"></a><a name="评论"><br> <div id="comments"> <h3>评论</h3> <div class="post"> <div class="postTitle"><a title="permalink: re: error C2899: 不能在模板声明之外使用类型名称 ?!!" href="http://www.cppblog.com/kb/archive/2008/01/03/414.html#3646">#</a>&nbsp;<a name="3646"></a>re: error C2899: 不能在模板声明之外使用类型名称 ?!! <span>2006-03-02 17:01 </span><a id="AjaxHolder_Comments_CommentList_ctl00_NameLink" target="_blank">yajun</a> </div> <div class="postText">这是VC得一个bug, 再VC7.1以后就可以用了。 <br>你没有用错，是微软错了。&nbsp; <a href="http://www.cppblog.com/kb/archive/2008/01/03/414.html#post">回复</a>&nbsp; <a title="查看该作者发表过的评论" href="http://www.cppblog.com/comment?author=yajun" target="_blank">更多评论</a> <br><a id="AjaxHolder_Comments_CommentList_ctl00_DeleteLink" href="http://www.cppblog.com/"></a>&nbsp; <a id="AjaxHolder_Comments_CommentList_ctl00_EditLink"></a> </div></div><br> <div class="post"> <div class="postTitle"><a title="permalink: re: error C2899: 不能在模板声明之外使用类型名称 ?!!" href="http://www.cppblog.com/kb/archive/2008/01/03/414.html#3661">#</a>&nbsp;<a name="3661"></a>re: error C2899: 不能在模板声明之外使用类型名称 ?!! <span>2006-03-02 22:57 </span><a id="AjaxHolder_Comments_CommentList_ctl01_NameLink" href="http://www.cppblog.com/kb/" target="_blank">可冰</a> </div> <div class="postText">是吗? <br>我没有在其它编译器下测试,只是看了它的错误说明,我还以为真是这样的呢. <br>我完了再试一下吧. <br>谢谢了!&nbsp; <a href="http://www.cppblog.com/kb/archive/2008/01/03/414.html#post">回复</a>&nbsp; <a title="查看该作者发表过的评论" href="http://www.cppblog.com/comment?author=%e5%8f%af%e5%86%b0" target="_blank">更多评论</a> <br><a id="AjaxHolder_Comments_CommentList_ctl01_DeleteLink" href="http://www.cppblog.com/"></a>&nbsp; <a id="AjaxHolder_Comments_CommentList_ctl01_EditLink"></a> </div></div><br> <div class="post"> <div class="postTitle"><a title="permalink: re: error C2899: 不能在模板声明之外使用类型名称 ?!!" href="http://www.cppblog.com/kb/archive/2008/01/03/414.html#3662">#</a>&nbsp;<a name="3662"></a>re: error C2899: 不能在模板声明之外使用类型名称 ?!! <span>2006-03-02 23:08 </span><a id="AjaxHolder_Comments_CommentList_ctl02_NameLink" href="http://www.cppblog.com/kb/" target="_blank">可冰</a> </div> <div class="postText">看来还是知识不过硬啊! <br>&nbsp; <a href="http://www.cppblog.com/kb/archive/2008/01/03/414.html#post">回复</a>&nbsp; <a title="查看该作者发表过的评论" href="http://www.cppblog.com/comment?author=%e5%8f%af%e5%86%b0" target="_blank">更多评论</a> <br><a id="AjaxHolder_Comments_CommentList_ctl02_DeleteLink" href="http://www.cppblog.com/"></a>&nbsp; <a id="AjaxHolder_Comments_CommentList_ctl02_EditLink"></a> </div></div><br> <div class="post"> <div class="postTitle"><a title="permalink: re: error C2899: 不能在模板声明之外使用类型名称 ?!!" href="http://www.cppblog.com/kb/archive/2008/01/03/414.html#12863">#</a>&nbsp;<a name="12863"></a>re: error C2899: 不能在模板声明之外使用类型名称 ?!! <span>2006-09-23 22:55 </span><a id="AjaxHolder_Comments_CommentList_ctl03_NameLink" target="_blank">x</a> </div> <div class="postText">这个也不能算bug 只是vc60附带的编译器对标准支持不够 到其后的版本ms碰到“正确”的语句会说明这个市为了遵从标准 要你写个typename&nbsp; <a href="http://www.cppblog.com/kb/archive/2008/01/03/414.html#post">回复</a>&nbsp; <a title="查看该作者发表过的评论" href="http://www.cppblog.com/comment?author=x" target="_blank">更多评论</a> <br><a id="AjaxHolder_Comments_CommentList_ctl03_DeleteLink" href="http://www.cppblog.com/"></a>&nbsp; <a id="AjaxHolder_Comments_CommentList_ctl03_EditLink"></a> </div></div><br> <div class="post"> <div class="postTitle"><a title="permalink: re: error C2899: 不能在模板声明之外使用类型名称 ?!!" href="http://www.cppblog.com/kb/archive/2008/01/03/414.html#40303">#</a>&nbsp;<a name="40303"></a>re: error C2899: 不能在模板声明之外使用类型名称 ?!!<a name="Post"></a> <span>2008-01-03 12:12 </span><a id="AjaxHolder_Comments_CommentList_ctl04_NameLink" href="http://yangmi0313@126.com" target="_blank">yangmi0313@126.com</a> </div> <div class="postText">我用VS2005怎么也有这个错误。&nbsp; <a href="http://www.cppblog.com/kb/archive/2008/01/03/414.html#post">回复</a>&nbsp; <a title="查看该作者发表过的评论" href="http://www.cppblog.com/comment?author=yangmi0313%40126.com" target="_blank">更多评论</a> <br></div></div></div></div></div></form><img src ="http://www.cppblog.com/woaidongmao/aggbug/60533.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/woaidongmao/" target="_blank">肥仔</a> 2008-08-31 21:48 <a href="http://www.cppblog.com/woaidongmao/archive/2008/08/31/60533.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>VS 2005模板的一个问题及解决方案</title><link>http://www.cppblog.com/woaidongmao/archive/2008/08/31/60531.html</link><dc:creator>肥仔</dc:creator><author>肥仔</author><pubDate>Sun, 31 Aug 2008 13:44:00 GMT</pubDate><guid>http://www.cppblog.com/woaidongmao/archive/2008/08/31/60531.html</guid><wfw:comment>http://www.cppblog.com/woaidongmao/comments/60531.html</wfw:comment><comments>http://www.cppblog.com/woaidongmao/archive/2008/08/31/60531.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/woaidongmao/comments/commentRss/60531.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/woaidongmao/services/trackbacks/60531.html</trackback:ping><description><![CDATA[<form id="Form1" name="Form1" action="http://www.cppblog.com/42813.html" method="post" _initialAction="42813.html"> <div id="main"> <div class="post"> <div class="postText">我也不知道这个能不能算是2005的bug吧，反正我是想不太明白。<br>今天在对我的pool使用policy的设计的时候发现的。<br><br> <div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><span style="color: #008000">//</span><span style="color: #008000">前面代码省略</span><span style="color: #008000"><br></span><span style="color: #000000"><br></span><span style="color: #0000ff">struct</span><span style="color: #000000"> single_thread<br>{<br>&nbsp; template</span><span style="color: #000000">&lt;</span><span style="color: #0000ff">class</span><span style="color: #000000"> T</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">struct</span><span style="color: #000000"> thread_safe_type<br>&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp; typedef boost::add_volatile</span><span style="color: #000000">&lt;</span><span style="color: #000000">T</span><span style="color: #000000">&gt;</span><span style="color: #000000"> result;<br>&nbsp; }<br>};<br><br>template</span><span style="color: #000000">&lt;</span><span style="color: #0000ff">class</span><span style="color: #000000"> ThreadingModel</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br></span><span style="color: #0000ff">struct</span><span style="color: #000000"> pool : </span><span style="color: #0000ff">private</span><span style="color: #000000"> ThreadingModel<br>{<br>&nbsp; typedef typename ThreadingModel::thread_safe_type</span><span style="color: #000000">&lt;</span><span style="color: #000000">size_t</span><span style="color: #000000">&gt;</span><span style="color: #000000">::result index_t;//其实有没有typename都一样。<br>&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">other public members</span><span style="color: #008000"><br></span><span style="color: #000000"><br></span><span style="color: #0000ff">private</span><span style="color: #000000">:<br> index_t first_free_;<br>};</span></div>看起来这段代码是完全能正常工作的，是吧。可是很不幸的是这代码在2005上没法正常通过。<br>解决的方法很简单：<br>typedef ThreadingModel TM;<br>typedef TM::thread_safe_type&lt;size_t&gt;::result index_t;<br>就可以大功告成了。不知道是不是typename的问题。但是从编译器的出错提示来看并不能和简单的typename的问题混为一谈。另外，如果这个thread_safe_type不是模板而只是一个普通的struct或者typedef的话，也是没有这个问题的。<br><br>如果有知道这个问题出现的根本原因的，请指教。<br><br></div> <div class="postfoot">posted on 2008-02-16 21:45 <a href="http://www.cppblog.com/lingjingqiu/">空明流转</a> 阅读(1054) <a href="http://www.cppblog.com/#Post">评论(6)</a>&nbsp; <a href="http://www.cppblog.com/lingjingqiu/admin/EditPosts.aspx?postid=42813">编辑</a>&nbsp;<a href="http://www.cppblog.com/lingjingqiu/AddToFavorite.aspx?id=42813">收藏</a> <a href="http://www.cppblog.com/lingjingqiu/services/trackbacks/42813.aspx">引用</a> </div></div><img height="1" src="http://www.cppblog.com/lingjingqiu/aggbug/42813.html?webview=1" width="1">  <div id="AjaxHolder_UpdatePanel1"><a name="pagedcomment"></a><a name="feedback"><br> <div id="comments"> <h3>评论</h3> <div class="post"> <div class="postTitle"><a title="permalink: re: VS 2005模板的一个问题及解决方案" href="http://www.cppblog.com/lingjingqiu/archive/2008/02/16/42813.html#42822">#</a>&nbsp;<a name="42822"></a>re: VS 2005模板的一个问题及解决方案 2008-02-17 00:49 <a id="AjaxHolder_Comments_CommentList_ctl00_NameLink" href="http://www.cppblog.com/eXile/" target="_blank">eXile</a> </div> <div class="postText">正确的写法，使用template关键字，应该改成这样： <br><br>template&lt;class ThreadingModel&gt; <br>struct pool : private ThreadingModel <br>{ <br>typedef typename ThreadingModel::template thread_safe_type&lt;size_t&gt;::result index_t; <br>//other public members <br><br>private: <br>index_t first_free_; <br>}; <br>&nbsp; <a href="http://www.cppblog.com/lingjingqiu/archive/2008/02/16/42813.html#post">回复</a>&nbsp; <a title="查看该作者发表过的评论" href="http://www.cppblog.com/comment?author=eXile" target="_blank">更多评论</a> <br><a id="AjaxHolder_Comments_CommentList_ctl00_DeleteLink" href="http://www.cppblog.com/"></a>&nbsp; <a id="AjaxHolder_Comments_CommentList_ctl00_EditLink"></a> </div></div><br> <div class="post"> <div class="postTitle"><a title="permalink: re: VS 2005模板的一个问题及解决方案" href="http://www.cppblog.com/lingjingqiu/archive/2008/02/16/42813.html#42827">#</a>&nbsp;<a name="42827"></a>re: VS 2005模板的一个问题及解决方案 2008-02-17 11:42 <a id="AjaxHolder_Comments_CommentList_ctl01_NameLink" href="http://www.cppblog.com/lingjingqiu/" target="_blank">空明流转</a> </div> <div class="postText">呵呵，楼上没跑过吧？这样也是不行的。否则我也不会说这个究竟是bug或者是别的什么。@eXile<br>&nbsp; <a href="http://www.cppblog.com/lingjingqiu/archive/2008/02/16/42813.html#post">回复</a>&nbsp; <a title="查看该作者发表过的评论" href="http://www.cppblog.com/comment?author=%e7%a9%ba%e6%98%8e%e6%b5%81%e8%bd%ac" target="_blank">更多评论</a> <br><a id="AjaxHolder_Comments_CommentList_ctl01_DeleteLink" href="http://www.cppblog.com/"></a>&nbsp; <a id="AjaxHolder_Comments_CommentList_ctl01_EditLink"></a> </div></div><br> <div class="post"> <div class="postTitle"><a title="permalink: re: VS 2005模板的一个问题及解决方案" href="http://www.cppblog.com/lingjingqiu/archive/2008/02/16/42813.html#42830">#</a>&nbsp;<a name="42830"></a>re: VS 2005模板的一个问题及解决方案 2008-02-17 13:07 <a id="AjaxHolder_Comments_CommentList_ctl02_NameLink" href="http://www.cppblog.com/eXile/" target="_blank">eXile</a> </div> <div class="postText">刚才试了一下, 没有问题, 我用的是VC2005 (SP1)&nbsp; <a href="http://www.cppblog.com/lingjingqiu/archive/2008/02/16/42813.html#post">回复</a>&nbsp; <a title="查看该作者发表过的评论" href="http://www.cppblog.com/comment?author=eXile" target="_blank">更多评论</a> <br><a id="AjaxHolder_Comments_CommentList_ctl02_DeleteLink" href="http://www.cppblog.com/"></a>&nbsp; <a id="AjaxHolder_Comments_CommentList_ctl02_EditLink"></a> </div></div><br> <div class="post"> <div class="postTitle"><a title="permalink: re: VS 2005模板的一个问题及解决方案" href="http://www.cppblog.com/lingjingqiu/archive/2008/02/16/42813.html#42832">#</a>&nbsp;<a name="42832"></a>re: VS 2005模板的一个问题及解决方案 2008-02-17 13:08 <a id="AjaxHolder_Comments_CommentList_ctl03_NameLink" href="http://www.cppblog.com/eXile/" target="_blank">eXile</a> </div> <div class="postText">一定要有typename, 不然通不过编译....&nbsp; <a href="http://www.cppblog.com/lingjingqiu/archive/2008/02/16/42813.html#post">回复</a>&nbsp; <a title="查看该作者发表过的评论" href="http://www.cppblog.com/comment?author=eXile" target="_blank">更多评论</a> <br><a id="AjaxHolder_Comments_CommentList_ctl03_DeleteLink" href="http://www.cppblog.com/"></a>&nbsp; <a id="AjaxHolder_Comments_CommentList_ctl03_EditLink"></a> </div></div><br> <div class="post"> <div class="postTitle"><a title="permalink: re: VS 2005模板的一个问题及解决方案" href="http://www.cppblog.com/lingjingqiu/archive/2008/02/16/42813.html#42834">#</a>&nbsp;<a name="42834"></a>re: VS 2005模板的一个问题及解决方案 2008-02-17 13:32 <a id="AjaxHolder_Comments_CommentList_ctl04_NameLink" href="http://www.cppblog.com/lingjingqiu/" target="_blank">空明流转</a> </div> <div class="postText">@eXile<br>typename我倒没丢，丢的是那个template。3Q<br>&nbsp; <a href="http://www.cppblog.com/lingjingqiu/archive/2008/02/16/42813.html#post">回复</a>&nbsp; <a title="查看该作者发表过的评论" href="http://www.cppblog.com/comment?author=%e7%a9%ba%e6%98%8e%e6%b5%81%e8%bd%ac" target="_blank">更多评论</a> <br><a id="AjaxHolder_Comments_CommentList_ctl04_DeleteLink" href="http://www.cppblog.com/"></a>&nbsp; <a id="AjaxHolder_Comments_CommentList_ctl04_EditLink"></a> </div></div><br> <div class="post"> <div class="postTitle"><a title="permalink: re: VS 2005模板的一个问题及解决方案" href="http://www.cppblog.com/lingjingqiu/archive/2008/02/16/42813.html#47880">#</a>&nbsp;<a name="47880"></a>re: VS 2005模板的一个问题及解决方案<a name="Post"></a> 2008-04-23 11:19 <a id="AjaxHolder_Comments_CommentList_ctl05_NameLink" href="http://www.cppblog.com/mzty/" target="_blank">梦在天涯</a> </div> <div class="postText">因为result编译器不知道是static变量还是类型，所以必须要typename来申明是类型！&nbsp; <a href="http://www.cppblog.com/lingjingqiu/archive/2008/02/16/42813.html#post">回复</a>&nbsp; <a title="查看该作者发表过的评论" href="http://www.cppblog.com/comment?author=%e6%a2%a6%e5%9c%a8%e5%a4%a9%e6%b6%af" target="_blank">更多评论</a> <br><a id="AjaxHolder_Comments_CommentList_ctl05_DeleteLink" href="http://www.cppblog.com/"></a>&nbsp; <a id="AjaxHolder_Comments_CommentList_ctl05_EditLink"></a> </div></div></div></div></div></form><img src ="http://www.cppblog.com/woaidongmao/aggbug/60531.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/woaidongmao/" target="_blank">肥仔</a> 2008-08-31 21:44 <a href="http://www.cppblog.com/woaidongmao/archive/2008/08/31/60531.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>分析stl function objects模块</title><link>http://www.cppblog.com/woaidongmao/archive/2008/08/31/60529.html</link><dc:creator>肥仔</dc:creator><author>肥仔</author><pubDate>Sun, 31 Aug 2008 13:42:00 GMT</pubDate><guid>http://www.cppblog.com/woaidongmao/archive/2008/08/31/60529.html</guid><wfw:comment>http://www.cppblog.com/woaidongmao/comments/60529.html</wfw:comment><comments>http://www.cppblog.com/woaidongmao/archive/2008/08/31/60529.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/woaidongmao/comments/commentRss/60529.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/woaidongmao/services/trackbacks/60529.html</trackback:ping><description><![CDATA[<form id="Form1" name="Form1" action="http://www.cppblog.com/44362.html" method="post" _initialAction="44362.html"> <div id="main"> <div class="post"> <p style="font-size: 10pt">从SGI的STl文档来看，STL functor(function object)模块主要分为两个部分：预先定义的functor<br>以及functor adaptors。除此之外，为了使客端程序员写出适用于functor adaptor的functor，STL<br>又定义了一系列基本上只包含typedef的空类型(例如unary_function)。用户只需要派生这些类，即<br>可让自己写的functor被functor adaptor使用。以下称类基类型为base functor。</p> <p style="font-size: 10pt">base functor包括: unary_function, binary_function,分别表示只有一个参数的函数和有两个参数<br>的函数。实际上STL里还有一个所谓的generator，代表没有参数的函数。因为STL泛型算法一般最多<br>只会使用两个参数的函数，所以这里并没有定义更多参数的base functor。</p> <p style="font-size: 10pt">可被functor adaptor使用的functor又称为adaptable function，根据参数的个数，会被命名为诸如<br>adaptable unary function, adaptable binary function。</p> <p style="font-size: 10pt">一个返回值为bool的functor又被称为predicate，可被用于functor adaptor的predicate被称为<br>adaptable predicate。其实所谓的adaptable，只需要在类型内部typedef一些类型即可，一般包括<br>first_argument_type, second_argument_type, result_type。functor adaptor会使用这些定义。</p> <p style="font-size: 10pt">预定义的functors都是些很简单的functor，基本上就是封装诸如plus, minus, equal_to之类的算术<br>运算，列举一个predefined functor的代码：<br>&nbsp; </p> <div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"><span style="color: #000000">template </span><span style="color: #000000">&lt;</span><span style="color: #0000ff">class</span><span style="color: #000000"> _Tp</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top">&nbsp; </span><span style="color: #0000ff">struct</span><span style="color: #000000"> plus : </span><span style="color: #0000ff">public</span><span style="color: #000000"> binary_function</span><span style="color: #000000">&lt;</span><span style="color: #000000">_Tp, _Tp, _Tp</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br><img id="Codehighlighter1_77_189_Open_Image" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top"><img id="Codehighlighter1_77_189_Closed_Image" style="display: none" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align="top">&nbsp; </span><span id="Codehighlighter1_77_189_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id="Codehighlighter1_77_189_Open_Text"><span style="color: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp; _Tp </span><span style="color: #0000ff">operator</span><span style="color: #000000">()(</span><span style="color: #0000ff">const</span><span style="color: #000000"> _Tp</span><span style="color: #000000">&amp;</span><span style="color: #000000"> __x, </span><span style="color: #0000ff">const</span><span style="color: #000000"> _Tp</span><span style="color: #000000">&amp;</span><span style="color: #000000"> __y) </span><span style="color: #0000ff">const</span><span style="color: #000000">&nbsp;&nbsp; <br><img id="Codehighlighter1_145_181_Open_Image" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"><img id="Codehighlighter1_145_181_Closed_Image" style="display: none" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp; </span><span id="Codehighlighter1_145_181_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id="Codehighlighter1_145_181_Open_Text"><span style="color: #000000">{ <br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff">return</span><span style="color: #000000"> __x </span><span style="color: #000000">+</span><span style="color: #000000"> __y; <br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp; }</span></span><span style="color: #000000">&nbsp;&nbsp;&nbsp; <br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top">&nbsp; }</span></span><span style="color: #000000">;</span></div> <p style="font-size: 10pt"><br>因为从binary_function(即我所谓的base functor)派生，因此这些predefined functor也是adaptable <br>function。</p> <p style="font-size: 10pt">functor adaptors里有很多有趣的东西，其实functor adaptor也是一些functor(从SGI的观点来看，一般<br>的C函数，函数指针都算作functor)。所不同的是，他们通常会适配(adapt)一种functor到另一种。例如：<br>std::binder1st，严格地说它是一个函数模板，它会把一个adaptable binary function转换为一个<br>adaptable unary function，并绑定一个参数。又如: std::ptr_fun，它会将一个只有一个参数的C函数<br>适配成一个pointer_to_unary_function的functor。</p> <p style="font-size: 10pt">下面列举一些具体的代码：<br>关于base functor，基本上就只有unary_function, binary_function :<br>&nbsp; </p> <div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"><span style="color: #000000">template </span><span style="color: #000000">&lt;</span><span style="color: #0000ff">class</span><span style="color: #000000"> _Arg, </span><span style="color: #0000ff">class</span><span style="color: #000000"> _Result</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top">&nbsp; </span><span style="color: #0000ff">struct</span><span style="color: #000000"> unary_function<br><img id="Codehighlighter1_63_157_Open_Image" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top"><img id="Codehighlighter1_63_157_Closed_Image" style="display: none" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align="top">&nbsp; </span><span id="Codehighlighter1_63_157_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id="Codehighlighter1_63_157_Open_Text"><span style="color: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; typedef _Arg argument_type;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; typedef _Result result_type; <br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top">&nbsp; }</span></span><span style="color: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top">&nbsp; </span></div> <p style="font-size: 10pt"><br>关于predefined functor，如之前列举的plus一样，再列举一个：<br></p> <div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"><span style="color: #000000">template </span><span style="color: #000000">&lt;</span><span style="color: #0000ff">class</span><span style="color: #000000"> _Tp</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top">&nbsp;</span><span style="color: #0000ff">struct</span><span style="color: #000000"> greater : </span><span style="color: #0000ff">public</span><span style="color: #000000"> binary_function</span><span style="color: #000000">&lt;</span><span style="color: #000000">_Tp, _Tp, </span><span style="color: #0000ff">bool</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br><img id="Codehighlighter1_79_194_Open_Image" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top"><img id="Codehighlighter1_79_194_Closed_Image" style="display: none" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align="top">&nbsp;</span><span id="Codehighlighter1_79_194_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id="Codehighlighter1_79_194_Open_Text"><span style="color: #000000">{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff">bool</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">operator</span><span style="color: #000000">()(</span><span style="color: #0000ff">const</span><span style="color: #000000"> _Tp</span><span style="color: #000000">&amp;</span><span style="color: #000000"> __x, </span><span style="color: #0000ff">const</span><span style="color: #000000"> _Tp</span><span style="color: #000000">&amp;</span><span style="color: #000000"> __y) </span><span style="color: #0000ff">const</span><span style="color: #000000"><br><img id="Codehighlighter1_151_187_Open_Image" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"><img id="Codehighlighter1_151_187_Closed_Image" style="display: none" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp; </span><span id="Codehighlighter1_151_187_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id="Codehighlighter1_151_187_Open_Text"><span style="color: #000000">{ <br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff">return</span><span style="color: #000000"> __x </span><span style="color: #000000">&gt;</span><span style="color: #000000"> __y; <br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp; }</span></span><span style="color: #000000">&nbsp;&nbsp;&nbsp; <br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top"> }</span></span><span style="color: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"></span></div> <p style="font-size: 10pt">&nbsp;<br>关于functor adaptors，也是我觉得比较有趣的部分，多列举几个：<br></p> <div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"><span style="color: #000000">template </span><span style="color: #000000">&lt;</span><span style="color: #0000ff">class</span><span style="color: #000000"> _Operation, </span><span style="color: #0000ff">class</span><span style="color: #000000"> _Tp</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top">&nbsp; inline binder1st</span><span style="color: #000000">&lt;</span><span style="color: #000000">_Operation</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top">&nbsp; bind1st(</span><span style="color: #0000ff">const</span><span style="color: #000000"> _Operation</span><span style="color: #000000">&amp;</span><span style="color: #000000"> __fn, </span><span style="color: #0000ff">const</span><span style="color: #000000"> _Tp</span><span style="color: #000000">&amp;</span><span style="color: #000000"> __x)<br><img id="Codehighlighter1_122_252_Open_Image" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top"><img id="Codehighlighter1_122_252_Closed_Image" style="display: none" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align="top">&nbsp; </span><span id="Codehighlighter1_122_252_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id="Codehighlighter1_122_252_Open_Text"><span style="color: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; typedef typename _Operation::first_argument_type _Arg1_type;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff">return</span><span style="color: #000000"> binder1st</span><span style="color: #000000">&lt;</span><span style="color: #000000">_Operation</span><span style="color: #000000">&gt;</span><span style="color: #000000">(__fn, _Arg1_type(__x));<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top">&nbsp; }</span></span><span style="color: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top">&nbsp; </span></div> <p style="font-size: 10pt">&nbsp; <br>bind1st返回的binder1st定义为：<br></p> <div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"><span style="color: #000000"> template </span><span style="color: #000000">&lt;</span><span style="color: #0000ff">class</span><span style="color: #000000"> _Operation</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top">&nbsp; </span><span style="color: #0000ff">class</span><span style="color: #000000"> binder1st : </span><span style="color: #0000ff">public</span><span style="color: #000000"> unary_function</span><span style="color: #000000">&lt;</span><span style="color: #000000">typename _Operation::second_argument_type, <br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top">&nbsp; typename _Operation::result_type</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br><img id="Codehighlighter1_153_710_Open_Image" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top"><img id="Codehighlighter1_153_710_Closed_Image" style="display: none" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align="top">&nbsp; </span><span id="Codehighlighter1_153_710_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id="Codehighlighter1_153_710_Open_Text"><span style="color: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp; </span><span style="color: #0000ff">protected</span><span style="color: #000000">:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; _Operation op;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; typename _Operation::first_argument_type value;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp; </span><span style="color: #0000ff">public</span><span style="color: #000000">:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; binder1st(</span><span style="color: #0000ff">const</span><span style="color: #000000"> _Operation</span><span style="color: #000000">&amp;</span><span style="color: #000000"> __x, </span><span style="color: #0000ff">const</span><span style="color: #000000"> typename _Operation::first_argument_type</span><span style="color: #000000">&amp;</span><span style="color: #000000"> __y): <br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; op(__x), value(__y) <br><img id="Codehighlighter1_382_383_Open_Image" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"><img id="Codehighlighter1_382_383_Closed_Image" style="display: none" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span id="Codehighlighter1_382_383_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id="Codehighlighter1_382_383_Open_Text"><span style="color: #000000">{}</span></span><span style="color: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; typename _Operation::result_type <br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff">operator</span><span style="color: #000000">()(</span><span style="color: #0000ff">const</span><span style="color: #000000"> typename _Operation::second_argument_type</span><span style="color: #000000">&amp;</span><span style="color: #000000"> __x) </span><span style="color: #0000ff">const</span><span style="color: #000000"><br><img id="Codehighlighter1_508_550_Open_Image" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"><img id="Codehighlighter1_508_550_Closed_Image" style="display: none" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span id="Codehighlighter1_508_550_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id="Codehighlighter1_508_550_Open_Text"><span style="color: #000000">{ <br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff">return</span><span style="color: #000000"> op(value, __x); <br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span></span><span style="color: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp; typename _Operation::result_type <br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff">operator</span><span style="color: #000000">()(typename _Operation::second_argument_type</span><span style="color: #000000">&amp;</span><span style="color: #000000"> __x) </span><span style="color: #0000ff">const</span><span style="color: #000000"><br><img id="Codehighlighter1_666_706_Open_Image" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"><img id="Codehighlighter1_666_706_Closed_Image" style="display: none" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp; </span><span id="Codehighlighter1_666_706_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id="Codehighlighter1_666_706_Open_Text"><span style="color: #000000">{ <br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff">return</span><span style="color: #000000"> op(value, __x); <br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp; }</span></span><span style="color: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top">&nbsp; }</span></span><span style="color: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"></span></div> <p style="font-size: 10pt">&nbsp;<br>值得一提的是，ptr_fun以及相关的pointer_to_unary_function, pointer_to_binary_function，基本上<br>就是用来绑定C函数的组件，不过这里采用了很基础的模板技术，因此只实现了绑定一个参数和两个参数<br>的C函数。这种组件类似于loki中的functor，以及boost中的bind，只是功能弱很多。与之相关的还有<br>mem_fun, mem_fun_ref, mem_fun1, mem_fun1_ref等，这些都是用于绑定成员函数的。另一方面，与其说<br>是绑定，还不如说适配，即将函数适配为functor(特指重载operator()的类)。( Mem_fun_t is an adaptor<br> for member functions )采用这些(ptr_fun, mem_fun之类的东西)组件，客端程序员可以很容易地将各种<br>运行体(Kevin似乎很喜欢发明各种名字)(C函数、成员函数)适配成functor，从而与STL泛型算法结合。<br>例如, SGI文档中给出的mem_fun例子：</p> <p style="font-size: 10pt">&nbsp;</p> <div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><img id="Codehighlighter1_9_38_Open_Image" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top"><img id="Codehighlighter1_9_38_Closed_Image" style="display: none" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align="top"><span style="color: #0000ff">struct</span><span style="color: #000000"> B </span><span id="Codehighlighter1_9_38_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id="Codehighlighter1_9_38_Open_Text"><span style="color: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;</span><span style="color: #0000ff">virtual</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000"> print() </span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top">}</span></span><span style="color: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"><br><img id="Codehighlighter1_63_111_Open_Image" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top"><img id="Codehighlighter1_63_111_Closed_Image" style="display: none" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align="top"></span><span style="color: #0000ff">struct</span><span style="color: #000000"> D1 : </span><span style="color: #0000ff">public</span><span style="color: #000000"> B </span><span id="Codehighlighter1_63_111_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id="Codehighlighter1_63_111_Open_Text"><span style="color: #000000">{<br><img id="Codehighlighter1_79_109_Open_Image" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"><img id="Codehighlighter1_79_109_Closed_Image" style="display: none" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align="top">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000"> print() </span><span id="Codehighlighter1_79_109_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id="Codehighlighter1_79_109_Open_Text"><span style="color: #000000">{ cout </span><span style="color: #000000">&lt;&lt;</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">I'm a D1</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">&lt;&lt;</span><span style="color: #000000"> endl; }</span></span><span style="color: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top">}</span></span><span style="color: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"><br><img id="Codehighlighter1_136_184_Open_Image" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top"><img id="Codehighlighter1_136_184_Closed_Image" style="display: none" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align="top"></span><span style="color: #0000ff">struct</span><span style="color: #000000"> D2 : </span><span style="color: #0000ff">public</span><span style="color: #000000"> B </span><span id="Codehighlighter1_136_184_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id="Codehighlighter1_136_184_Open_Text"><span style="color: #000000">{<br><img id="Codehighlighter1_152_182_Open_Image" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"><img id="Codehighlighter1_152_182_Closed_Image" style="display: none" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align="top">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000"> print() </span><span id="Codehighlighter1_152_182_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id="Codehighlighter1_152_182_Open_Text"><span style="color: #000000">{ cout </span><span style="color: #000000">&lt;&lt;</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">I'm a D2</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">&lt;&lt;</span><span style="color: #000000"> endl; }</span></span><span style="color: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top">}</span></span><span style="color: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"></span><span style="color: #0000ff">int</span><span style="color: #000000"> main()<br><img id="Codehighlighter1_199_357_Open_Image" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top"><img id="Codehighlighter1_199_357_Closed_Image" style="display: none" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align="top"></span><span id="Codehighlighter1_199_357_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id="Codehighlighter1_199_357_Open_Text"><span style="color: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top"> vector</span><span style="color: #000000">&lt;</span><span style="color: #000000">B</span><span style="color: #000000">*&gt;</span><span style="color: #000000"> V;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top"> V.push_back(</span><span style="color: #0000ff">new</span><span style="color: #000000"> D1);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top"> V.push_back(</span><span style="color: #0000ff">new</span><span style="color: #000000"> D2);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top"> V.push_back(</span><span style="color: #0000ff">new</span><span style="color: #000000"> D2);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top"> V.push_back(</span><span style="color: #0000ff">new</span><span style="color: #000000"> D1);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top"> for_each(V.begin(), V.end(), mem_fun(</span><span style="color: #000000">&amp;</span><span style="color: #000000">B::print));<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top">}</span></span><span style="color: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"></span></div> <p style="font-size: 10pt">&nbsp;</p> <p style="font-size: 10pt">&nbsp;</p> <p style="font-size: 10pt">注：以上分析基于dev-cpp中自带的stl，源代码见stl_functional.h。</p></div></div></form><img src ="http://www.cppblog.com/woaidongmao/aggbug/60529.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/woaidongmao/" target="_blank">肥仔</a> 2008-08-31 21:42 <a href="http://www.cppblog.com/woaidongmao/archive/2008/08/31/60529.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>实现functor - 增强型的函数指针</title><link>http://www.cppblog.com/woaidongmao/archive/2008/08/31/60527.html</link><dc:creator>肥仔</dc:creator><author>肥仔</author><pubDate>Sun, 31 Aug 2008 13:41:00 GMT</pubDate><guid>http://www.cppblog.com/woaidongmao/archive/2008/08/31/60527.html</guid><wfw:comment>http://www.cppblog.com/woaidongmao/comments/60527.html</wfw:comment><comments>http://www.cppblog.com/woaidongmao/archive/2008/08/31/60527.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/woaidongmao/comments/commentRss/60527.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/woaidongmao/services/trackbacks/60527.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 作者：Kevin Lynx 需求： 开发一种组件，用以包装C函数、通常的函数对象、成员函数，使其对外保持一种一致的接口。我将最终的组件称为functor，这里的functor与loki中的functor以及boost中的function功能一致，同STL中的functor在概念层次上可以说也是一样的。那么，functor其实也可以进一步传进其他functor构成新的functor。 C++世界里还...&nbsp;&nbsp;<a href='http://www.cppblog.com/woaidongmao/archive/2008/08/31/60527.html'>阅读全文</a><img src ="http://www.cppblog.com/woaidongmao/aggbug/60527.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/woaidongmao/" target="_blank">肥仔</a> 2008-08-31 21:41 <a href="http://www.cppblog.com/woaidongmao/archive/2008/08/31/60527.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>实现自己的LUA绑定器-一个模板编程挑战</title><link>http://www.cppblog.com/woaidongmao/archive/2008/08/31/60526.html</link><dc:creator>肥仔</dc:creator><author>肥仔</author><pubDate>Sun, 31 Aug 2008 13:38:00 GMT</pubDate><guid>http://www.cppblog.com/woaidongmao/archive/2008/08/31/60526.html</guid><wfw:comment>http://www.cppblog.com/woaidongmao/comments/60526.html</wfw:comment><comments>http://www.cppblog.com/woaidongmao/archive/2008/08/31/60526.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/woaidongmao/comments/commentRss/60526.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/woaidongmao/services/trackbacks/60526.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 实现LUA绑定器  author : Kevin Lynx  Preface &nbsp;&nbsp;&nbsp; 当LUA脚本调用我们注册的C函数时，我们需要逐个地从LUA栈里取出调用参数，当函数返回时，又需要一个一个地往LUA栈压入返回值，并且我们注册的函数只能是int()(lua_State*)类型。这很不方便，对于上层程序员来说更不方便。&nbsp;&nbsp;&nbsp; 因此我们要做的...&nbsp;&nbsp;<a href='http://www.cppblog.com/woaidongmao/archive/2008/08/31/60526.html'>阅读全文</a><img src ="http://www.cppblog.com/woaidongmao/aggbug/60526.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/woaidongmao/" target="_blank">肥仔</a> 2008-08-31 21:38 <a href="http://www.cppblog.com/woaidongmao/archive/2008/08/31/60526.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>模板函数问题</title><link>http://www.cppblog.com/woaidongmao/archive/2008/08/31/60523.html</link><dc:creator>肥仔</dc:creator><author>肥仔</author><pubDate>Sun, 31 Aug 2008 13:34:00 GMT</pubDate><guid>http://www.cppblog.com/woaidongmao/archive/2008/08/31/60523.html</guid><wfw:comment>http://www.cppblog.com/woaidongmao/comments/60523.html</wfw:comment><comments>http://www.cppblog.com/woaidongmao/archive/2008/08/31/60523.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/woaidongmao/comments/commentRss/60523.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/woaidongmao/services/trackbacks/60523.html</trackback:ping><description><![CDATA[<form id="Form1" name="Form1" action="http://www.cppblog.com/59447.html" method="post" _initialAction="59447.html"> <div id="main"> <div class="post">在VC下定义一个<br> <div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><span style="color: #008080">1</span><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"><span style="color: #000000">template</span><span style="color: #000000">&lt;</span><span style="color: #000000">typename T</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br></span><span style="color: #008080">2</span><span style="color: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top">list</span><span style="color: #000000">&lt;</span><span style="color: #000000">T</span><span style="color: #000000">&gt;</span><span style="color: #000000">::iterator&nbsp; seqSearch( list</span><span style="color: #000000">&lt;</span><span style="color: #000000">T</span><span style="color: #000000">&gt;</span><span style="color: #000000">::iterator&nbsp;&nbsp; first,&nbsp;&nbsp;&nbsp; list</span><span style="color: #000000">&lt;</span><span style="color: #000000">T</span><span style="color: #000000">&gt;</span><span style="color: #000000">::iterator&nbsp; last,&nbsp;&nbsp; </span><span style="color: #0000ff">const</span><span style="color: #000000">&nbsp; T</span><span style="color: #000000">&amp;</span><span style="color: #000000">&nbsp; target)&nbsp;&nbsp; <br></span><span style="color: #008080">3</span><span style="color: #000000"><img id="Codehighlighter1_130_266_Open_Image" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top"><img id="Codehighlighter1_130_266_Closed_Image" style="display: none" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align="top"></span><span id="Codehighlighter1_130_266_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id="Codehighlighter1_130_266_Open_Text"><span style="color: #000000">{&nbsp;&nbsp; <br></span><span style="color: #008080">4</span><span style="color: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp; list</span><span style="color: #000000">&lt;</span><span style="color: #000000">T</span><span style="color: #000000">&gt;</span><span style="color: #000000">::iterator&nbsp;&nbsp; iter&nbsp;&nbsp; </span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;&nbsp; first;&nbsp;&nbsp; <br></span><span style="color: #008080">5</span><span style="color: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff">while</span><span style="color: #000000">&nbsp;&nbsp; (iter&nbsp;&nbsp; </span><span style="color: #000000">!=</span><span style="color: #000000">&nbsp;&nbsp; last&nbsp;&nbsp; </span><span style="color: #000000">&amp;&amp;</span><span style="color: #000000">(</span><span style="color: #000000">*</span><span style="color: #000000">iter&nbsp;&nbsp; </span><span style="color: #000000">!=</span><span style="color: #000000">&nbsp;&nbsp; target))&nbsp;&nbsp; <br></span><span style="color: #008080">6</span><span style="color: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #000000">++</span><span style="color: #000000">iter;&nbsp;&nbsp; <br></span><span style="color: #008080">7</span><span style="color: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;&nbsp; iter;&nbsp;&nbsp; <br></span><span style="color: #008080">8</span><span style="color: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top">}</span></span><span style="color: #000000">&nbsp;</span></div>但是始终无法通过编译，最后改为<br> <div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><span style="color: #008080">1</span><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"><span style="color: #000000">template</span><span style="color: #000000">&lt;</span><span style="color: #000000">typename T</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br></span><span style="color: #008080">2</span><span style="color: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top">typename list</span><span style="color: #000000">&lt;</span><span style="color: #000000">T</span><span style="color: #000000">&gt;</span><span style="color: #000000">::iterator&nbsp; seqSearch(typename list</span><span style="color: #000000">&lt;</span><span style="color: #000000">T</span><span style="color: #000000">&gt;</span><span style="color: #000000">::iterator&nbsp;&nbsp; first,&nbsp;&nbsp; typename list</span><span style="color: #000000">&lt;</span><span style="color: #000000">T</span><span style="color: #000000">&gt;</span><span style="color: #000000">::iterator&nbsp; last,&nbsp;&nbsp; typename </span><span style="color: #0000ff">const</span><span style="color: #000000">&nbsp; T</span><span style="color: #000000">&amp;</span><span style="color: #000000">&nbsp; target)&nbsp;&nbsp; <br></span><span style="color: #008080">3</span><span style="color: #000000"><img id="Codehighlighter1_164_300_Open_Image" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top"><img id="Codehighlighter1_164_300_Closed_Image" style="display: none" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align="top"></span><span id="Codehighlighter1_164_300_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id="Codehighlighter1_164_300_Open_Text"><span style="color: #000000">{&nbsp;&nbsp; <br></span><span style="color: #008080">4</span><span style="color: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp; list</span><span style="color: #000000">&lt;</span><span style="color: #000000">T</span><span style="color: #000000">&gt;</span><span style="color: #000000">::iterator&nbsp;&nbsp; iter&nbsp;&nbsp; </span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;&nbsp; first;&nbsp;&nbsp; <br></span><span style="color: #008080">5</span><span style="color: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff">while</span><span style="color: #000000">&nbsp;&nbsp; (iter&nbsp;&nbsp; </span><span style="color: #000000">!=</span><span style="color: #000000">&nbsp;&nbsp; last&nbsp;&nbsp; </span><span style="color: #000000">&amp;&amp;</span><span style="color: #000000">(</span><span style="color: #000000">*</span><span style="color: #000000">iter&nbsp;&nbsp; </span><span style="color: #000000">!=</span><span style="color: #000000">&nbsp;&nbsp; target))&nbsp;&nbsp; <br></span><span style="color: #008080">6</span><span style="color: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #000000">++</span><span style="color: #000000">iter;&nbsp;&nbsp; <br></span><span style="color: #008080">7</span><span style="color: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;&nbsp; iter;&nbsp;&nbsp; <br></span><span style="color: #008080">8</span><span style="color: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top">}</span></span><span style="color: #000000">&nbsp;</span></div>就好了 <br>估计应该是编译器不知道list&lt;T*&gt;::iterator是代表一个类型<br>还是代表list&lt;T*&gt;类中的一个成员，叫做iterator  <p class="postfoot">posted on 2008-08-20 16:56 <a href="http://www.cppblog.com/tgh621/">大海</a> 阅读(842) <a href="http://www.cppblog.com/#Post">评论(3)</a>&nbsp; <a href="http://www.cppblog.com/tgh621/admin/EditPosts.aspx?postid=59447">编辑</a>&nbsp;<a href="http://www.cppblog.com/tgh621/AddToFavorite.aspx?id=59447">收藏</a> <a href="http://www.cppblog.com/tgh621/services/trackbacks/59447.aspx">引用</a> 所属分类: <a href="http://www.cppblog.com/tgh621/category/6769.html">stl</a> </p></div><img height="1" src="http://www.cppblog.com/tgh621/aggbug/59447.html?webview=1" width="1">  <div id="AjaxHolder_UpdatePanel1"><a name="pagedcomment"></a><a name="评论"> <div id="comments"> <h3>评论</h3> <h4><a title="permalink: re: 模板函数问题" href="http://www.cppblog.com/tgh621/archive/2008/08/20/59447.html#59448">#</a>&nbsp;<a name="59448"></a>re: 模板函数问题 <span>2008-08-20 17:08 </span><a id="AjaxHolder_Comments_CommentList_ctl00_NameLink" href="http://blog.csdn.net/lovekatherine" target="_blank">啸天猪</a> </h4> <p>标准规定，这种情况如果不使用typename关键字，总会被当作non-type name进行解释。<br><br>&nbsp; <a href="http://www.cppblog.com/tgh621/archive/2008/08/20/59447.html#post">回复</a>&nbsp; <a title="查看该作者发表过的评论" href="http://www.cppblog.com/comment?author=%e5%95%b8%e5%a4%a9%e7%8c%aa" target="_blank">更多评论</a> <a id="AjaxHolder_Comments_CommentList_ctl00_DeleteLink" href="http://www.cppblog.com/"></a>&nbsp; <a id="AjaxHolder_Comments_CommentList_ctl00_EditLink"></a> </p> <h4><a title="permalink: re: 模板函数问题" href="http://www.cppblog.com/tgh621/archive/2008/08/20/59447.html#59482">#</a>&nbsp;<a name="59482"></a>re: 模板函数问题 <span>2008-08-20 23:33 </span><a id="AjaxHolder_Comments_CommentList_ctl01_NameLink" href="http://www.cppblog.com/cexer/" target="_blank">cexer</a> </h4> <p>是的，这种细节就不要自己猜了，找本书看看，效率高些。&nbsp; <a href="http://www.cppblog.com/tgh621/archive/2008/08/20/59447.html#post">回复</a>&nbsp; <a title="查看该作者发表过的评论" href="http://www.cppblog.com/comment?author=cexer" target="_blank">更多评论</a> <a id="AjaxHolder_Comments_CommentList_ctl01_DeleteLink" href="http://www.cppblog.com/"></a>&nbsp; <a id="AjaxHolder_Comments_CommentList_ctl01_EditLink"></a> </p> <h4><a title="permalink: re: 模板函数问题" href="http://www.cppblog.com/tgh621/archive/2008/08/20/59447.html#59485">#</a>&nbsp;<a name="59485"></a>re: 模板函数问题<a name="Post"></a> <span>2008-08-20 23:53 </span><a id="AjaxHolder_Comments_CommentList_ctl02_NameLink" href="http://www.cppblog.com/x-matrix/" target="_blank">x-matrix</a> </h4> <p>模板内使用模板参数需指定typename，以标明它是个类型。 <br>另，这个实现是个练习吧。&nbsp; <a href="http://www.cppblog.com/tgh621/archive/2008/08/20/59447.html#post">回复</a>&nbsp; <a title="查看该作者发表过的评论" href="http://www.cppblog.com/comment?author=x-matrix" target="_blank">更多评论</a> <a id="AjaxHolder_Comments_CommentList_ctl02_DeleteLink" href="http://www.cppblog.com/"></a>&nbsp; <a id="AjaxHolder_Comments_CommentList_ctl02_EditLink"></a> </p></div></div></div></form><img src ="http://www.cppblog.com/woaidongmao/aggbug/60523.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/woaidongmao/" target="_blank">肥仔</a> 2008-08-31 21:34 <a href="http://www.cppblog.com/woaidongmao/archive/2008/08/31/60523.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Trait和Template Mataprogram的奥秘</title><link>http://www.cppblog.com/woaidongmao/archive/2008/08/31/60522.html</link><dc:creator>肥仔</dc:creator><author>肥仔</author><pubDate>Sun, 31 Aug 2008 13:23:00 GMT</pubDate><guid>http://www.cppblog.com/woaidongmao/archive/2008/08/31/60522.html</guid><wfw:comment>http://www.cppblog.com/woaidongmao/comments/60522.html</wfw:comment><comments>http://www.cppblog.com/woaidongmao/archive/2008/08/31/60522.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/woaidongmao/comments/commentRss/60522.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/woaidongmao/services/trackbacks/60522.html</trackback:ping><description><![CDATA[<p></p> <div id="main"> <div class="post"> <div class="postbody">C++是一门复杂的语言，之所以复杂，就是因为被很多的大牛们发掘出了它的很多极其怪异的用法，或者也可以说是很高明的技巧，这些技巧，我们普通人难以掌握，也很少有非使用不可的时候，但是对于那些大牛们来说，却是必不可少的利器。不信的话，翻翻Boost的源码，这样复杂的技巧比比皆是。<br><br>这些技巧，有的我以前只是听说，比如Mataprogram；有的我曾经在使用库的时候碰到过，但是怎么也想不通为什么需要这么个东西，比如Trait。直到最近几天，读《C++ Template》的时候，才突然豁然开朗。这里写出来和大家分享。<br><br>先来说说Trait，这是一个在C++ Template编程中经常用到的一个设计机制，在使用某些库的时候我也经常碰到。比如说STL库中的basic_string，其定义如下：<br> <div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><span style="color: #000000">template </span><span style="color: #000000">&lt;</span><span style="color: #000000"><br>&nbsp;&nbsp; </span><span style="color: #0000ff">class</span><span style="color: #000000"> CharType,<br>&nbsp;&nbsp; </span><span style="color: #0000ff">class</span><span style="color: #000000"> Traits</span><span style="color: #000000">=</span><span style="color: #000000">char_traits</span><span style="color: #000000">&lt;</span><span style="color: #000000">CharType</span><span style="color: #000000">&gt;</span><span style="color: #000000">, <br>&nbsp;&nbsp; </span><span style="color: #0000ff">class</span><span style="color: #000000"> Allocator</span><span style="color: #000000">=</span><span style="color: #000000">allocator</span><span style="color: #000000">&lt;</span><span style="color: #000000">CharType</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;<br></span><span style="color: #000000">&gt;</span><span style="color: #000000"><br></span><span style="color: #0000ff">class</span><span style="color: #000000"> basic_string</span></div><b><br></b><br>其中就有一个模板参数为Traits，而它的默认值为char_traits&lt;CharType&gt;，这里的char_traits&lt;&gt;就是一个trait类，它可以提供关于CharType的特征信息。我们常用的string类的定义如下：<br> <div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"><span style="color: #000000">typedef basic_string</span><span style="color: #000000">&lt;</span><span style="color: #0000ff">char</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">string</span><span style="color: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"></span></div><br>如果我们把它的默认模板参数带入，就可以看到string的形式是这样的：<br> <div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"><span style="color: #000000">basic_string</span><span style="color: #000000">&lt;</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">char</span><span style="color: #000000">, char_traits</span><span style="color: #000000">&lt;</span><span style="color: #0000ff">char</span><span style="color: #000000">&gt;</span><span style="color: #000000">, allocator</span><span style="color: #000000">&lt;</span><span style="color: #0000ff">char</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">&gt;</span></div><br><br>到这里，我就迷糊了，我在想，为什么char_trait&lt;&gt;就能够取得char的类型信息？为什么basic_string&lt;&gt;就不行？难道说加上trait这几个字，模板类就有了三头六臂不成？<br><br>另外还有一个例子就是<a href="http://www.vckbase.com/document/viewdoc/?id=1119">ATL 3.0中的窗口类</a>，这是我很早以前翻译的一篇文章，其中也使用到了Trait，在定义窗口样式的时候，其代码如下：<br> <div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><span style="color: #0000ff">class</span><span style="color: #000000"> CMyWindow: </span><span style="color: #0000ff">public</span><span style="color: #000000"> CWindowImpl</span><span style="color: #000000">&lt;</span><span style="color: #000000"><br>&nbsp;&nbsp; CMyWindow,<br>&nbsp;&nbsp; CWindow,<br>&nbsp;&nbsp; CWinTraits</span><span style="color: #000000">&lt;</span><span style="color: #000000">WS_OVERLAPPEDWINDOW</span><span style="color: #000000">|</span><span style="color: #000000">WS_VISIBLE,</span><span style="color: #000000">0</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;<br></span><span style="color: #000000">&gt;</span><span style="color: #000000"><br>{<img src="http://www.cppblog.com/Images/dot.gif">};</span></div><br>当时我就想了，为什么不直接把“<span style="color: #000000">WS_OVERLAPPEDWINDOW</span><span style="color: #000000">|</span><span style="color: #000000">WS_VISIBLE,</span><span style="color: #000000">0”当成模板参数传递给CWindowImpl&lt;&gt;算了，还非要CWinTraits&lt;&gt;来掺和一把？<br><br>直到现在，我终于知道，原来一直错的就是我。我不该把char_traits&lt;&gt;看成是一个模板类，不该认为传给它一个char它就可以读出char的特征信息，传给它一个int它就能读出int的特征信息。它当然不可能具备这么高级的功能，更不可能加上traits几个字就一下子挣脱了C++语言的束缚。<br><br>那么不把它看成一个模板类，应该怎么看呢？应该把char_traits&lt;char&gt;看成一个整体，说专业点，那叫<strong>模板特化</strong>，说通俗点，就是原来这里面的特征信息都是编写它的人自己定义的，如果你要让basic_string能够处理int，double之类的信息，你还得自己写一个char_traits&lt;int&gt;和一个char_traits&lt;double&gt;。CWinTraits&lt;...&gt;也同样是这个道理。<br><br>为了说得更清楚点，我这里举个小例子。什么例子呢？就写个计算平均值的模板函数吧，如下：<br> <div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><span style="color: #000000">template </span><span style="color: #000000">&lt;</span><span style="color: #000000">typename T</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br>T average(T </span><span style="color: #0000ff">const</span><span style="color: #000000">*</span><span style="color: #000000"> begin, T </span><span style="color: #0000ff">const</span><span style="color: #000000">*</span><span style="color: #000000"> end)<br>{<br>&nbsp;&nbsp;&nbsp; T total </span><span style="color: #000000">=</span><span style="color: #000000"> T();<br>&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff">int</span><span style="color: #000000"> count </span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">;<br>&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff">while</span><span style="color: #000000"> (begin </span><span style="color: #000000">!=</span><span style="color: #000000"> end){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; total </span><span style="color: #000000">+=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">*</span><span style="color: #000000"> begin;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #000000">++</span><span style="color: #000000">begin;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #000000">++</span><span style="color: #000000">count;<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff">return</span><span style="color: #000000"> total</span><span style="color: #000000">/</span><span style="color: #000000">count;<br>}</span></div></span><br>下面是使用这个函数的代码，如果我们计算的类型是int，结果是正确的，如下：<br> <div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><span style="color: #0000ff">int</span><span style="color: #000000"> main(){<br>&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff">int</span><span style="color: #000000"> numbers[] </span><span style="color: #000000">=</span><span style="color: #000000"> {</span><span style="color: #000000">1</span><span style="color: #000000">,</span><span style="color: #000000">2</span><span style="color: #000000">,</span><span style="color: #000000">3</span><span style="color: #000000">,</span><span style="color: #000000">4</span><span style="color: #000000">,</span><span style="color: #000000">5</span><span style="color: #000000">};<br>&nbsp;&nbsp;&nbsp; std::cout </span><span style="color: #000000">&lt;&lt;</span><span style="color: #000000"> average(</span><span style="color: #000000">&amp;</span><span style="color: #000000">numbers[</span><span style="color: #000000">0</span><span style="color: #000000">],</span><span style="color: #000000">&amp;</span><span style="color: #000000">numbers[</span><span style="color: #000000">5</span><span style="color: #000000">]) </span><span style="color: #000000">&lt;&lt;</span><span style="color: #000000"> std::endl;<br>}</span></div><br>该程序运行的结果是3，非常正确，将数据类型换成float，double也没有问题。但是，如果是char类型，就不一定了。代码如下：<br> <div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><span style="color: #0000ff">int</span><span style="color: #000000"> main(){<br>&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff">char</span><span style="color: #000000"> characters[] </span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">traits</span><span style="color: #000000">"</span><span style="color: #000000">;<br>&nbsp;&nbsp;&nbsp; std::cout </span><span style="color: #000000">&lt;&lt;</span><span style="color: #000000"> static_cast</span><span style="color: #000000">&lt;</span><span style="color: #0000ff">int</span><span style="color: #000000">&gt;</span><span style="color: #000000">(average(</span><span style="color: #000000">&amp;</span><span style="color: #000000">characters[</span><span style="color: #000000">0</span><span style="color: #000000">],</span><span style="color: #000000">&amp;</span><span style="color: #000000">characters[</span><span style="color: #000000">6</span><span style="color: #000000">])) </span><span style="color: #000000">&lt;&lt;</span><span style="color: #000000"> std::endl;<br>}</span></div> <p><br>运行结果为 -17，不信大家可以自己运行试一下。为什么是个负数呢？<br><br>原因是因为char类型能表示的范围只有-127到+128，几个字母一加，就溢出了。为了得到正确的结果，我们希望能有一种机制，来指定运算的时候用什么作为返回类型，这时候，traits就可以闪亮登场了。前面已经说过，要把trait&lt;...&gt;看成一个整体，所以应该为每一个数据类型都定义一个trait。在这个例子中，我们主要是为了对每一个运算的类型指定合适的返回类型，任务比较简单，所以，代码可以这样写：</p> <div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><span style="color: #000000">template </span><span style="color: #000000">&lt;</span><span style="color: #000000">typename T</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br></span><span style="color: #0000ff">class</span><span style="color: #000000"> TypeTraits;<br><br>template </span><span style="color: #000000">&lt;&gt;</span><span style="color: #000000"><br></span><span style="color: #0000ff">class</span><span style="color: #000000"> TypeTraits</span><span style="color: #000000">&lt;</span><span style="color: #0000ff">char</span><span style="color: #000000">&gt;</span><span style="color: #000000">{<br></span><span style="color: #0000ff">public</span><span style="color: #000000">:<br>&nbsp;&nbsp;&nbsp; typedef </span><span style="color: #0000ff">int</span><span style="color: #000000"> ReturnType;<br>}<br><br>template </span><span style="color: #000000">&lt;&gt;</span><span style="color: #000000"><br></span><span style="color: #0000ff">class</span><span style="color: #000000"> TypeTraits</span><span style="color: #000000">&lt;</span><span style="color: #0000ff">short</span><span style="color: #000000">&gt;</span><span style="color: #000000">{<br></span><span style="color: #0000ff">public</span><span style="color: #000000">:<br>&nbsp;&nbsp;&nbsp; typedef </span><span style="color: #0000ff">int</span><span style="color: #000000"> ReturnType;<br>}<br><br>template </span><span style="color: #000000">&lt;&gt;</span><span style="color: #000000"><br></span><span style="color: #0000ff">class</span><span style="color: #000000"> TypeTraits</span><span style="color: #000000">&lt;</span><span style="color: #0000ff">int</span><span style="color: #000000">&gt;</span><span style="color: #000000">{<br></span><span style="color: #0000ff">public</span><span style="color: #000000">:<br>&nbsp;&nbsp;&nbsp; typedef </span><span style="color: #0000ff">int</span><span style="color: #000000"> ReturnType;<br>}<br><br>template </span><span style="color: #000000">&lt;&gt;</span><span style="color: #000000"><br></span><span style="color: #0000ff">class</span><span style="color: #000000"> TypeTraits</span><span style="color: #000000">&lt;</span><span style="color: #0000ff">float</span><span style="color: #000000">&gt;</span><span style="color: #000000">{<br></span><span style="color: #0000ff">public</span><span style="color: #000000">:<br>&nbsp;&nbsp;&nbsp; typedef </span><span style="color: #0000ff">double</span><span style="color: #000000"> ReturnType;<br>}</span></div><br>函数可以改成这样：<br> <div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><span style="color: #000000">template </span><span style="color: #000000">&lt;</span><span style="color: #000000">typename T,typename Traits</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br>typename Traits::ReturnType average(T </span><span style="color: #0000ff">const</span><span style="color: #000000">*</span><span style="color: #000000"> begin, T </span><span style="color: #0000ff">const</span><span style="color: #000000">*</span><span style="color: #000000"> end)<br>{<br>&nbsp;&nbsp;&nbsp; typedef typename Traits::ReturnType ReturnType;<br>&nbsp;&nbsp;&nbsp; ReturnType total </span><span style="color: #000000">=</span><span style="color: #000000"> ReturnType();<br>&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff">int</span><span style="color: #000000"> count </span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">;<br>&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff">while</span><span style="color: #000000"> (begin </span><span style="color: #000000">!=</span><span style="color: #000000"> end){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; total </span><span style="color: #000000">+=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">*</span><span style="color: #000000"> begin;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #000000">++</span><span style="color: #000000">begin;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #000000">++</span><span style="color: #000000">count;<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff">return</span><span style="color: #000000"> total</span><span style="color: #000000">/</span><span style="color: #000000">count;<br>}</span></div><br>使用该函数的代码是这样：<br> <div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><span style="color: #0000ff">int</span><span style="color: #000000"> main(){<br>&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff">int</span><span style="color: #000000"> numbers[] </span><span style="color: #000000">=</span><span style="color: #000000"> {</span><span style="color: #000000">1</span><span style="color: #000000">,</span><span style="color: #000000">2</span><span style="color: #000000">,</span><span style="color: #000000">3</span><span style="color: #000000">,</span><span style="color: #000000">4</span><span style="color: #000000">,</span><span style="color: #000000">5</span><span style="color: #000000">};<br>&nbsp;&nbsp;&nbsp; std::cout </span><span style="color: #000000">&lt;&lt;</span><span style="color: #000000"> average</span><span style="color: #000000">&lt;</span><span style="color: #0000ff">int</span><span style="color: #000000">,TypeTraits</span><span style="color: #000000">&lt;</span><span style="color: #0000ff">int</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">&gt;</span><span style="color: #000000">(</span><span style="color: #000000">&amp;</span><span style="color: #000000">numbers[</span><span style="color: #000000">0</span><span style="color: #000000">],</span><span style="color: #000000">&amp;</span><span style="color: #000000">numbers[</span><span style="color: #000000">5</span><span style="color: #000000">]) </span><span style="color: #000000">&lt;&lt;</span><span style="color: #000000"> std::endl;<br>&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff">char</span><span style="color: #000000"> characters[] </span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">traits</span><span style="color: #000000">"</span><span style="color: #000000">;<br>&nbsp;&nbsp;&nbsp; std::cout </span><span style="color: #000000">&lt;&lt;</span><span style="color: #000000"> average</span><span style="color: #000000">&lt;</span><span style="color: #0000ff">char</span><span style="color: #000000">,TypeTraits</span><span style="color: #000000">&lt;</span><span style="color: #0000ff">char</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">&gt;</span><span style="color: #000000">(</span><span style="color: #000000">&amp;</span><span style="color: #000000">characters[</span><span style="color: #000000">0</span><span style="color: #000000">],</span><span style="color: #000000">&amp;</span><span style="color: #000000">characters[</span><span style="color: #000000">6</span><span style="color: #000000">]) </span><span style="color: #000000">&lt;&lt;</span><span style="color: #000000"> std::endl;<br>}</span></div><br>这时候，一切都正常了。只可惜模板函数不支持默认模板参数，要不然，这里的代码可以更简洁。<br><br>再来说说Template Mataprogram，中文叫模板元编程。这个东西，我很早就听说过，如雷灌耳。听说它主要有这样几个特点：<br>1、它编的程序不是运行的时候执行的，而是在编译的时候由编译器执行的；<br>2、它能够牵着编译器的鼻子走，靠的完全是符合标准的模板语法，不需要使用编译器的任何API；<br>3、它居然是图灵完备的，也就是说它什么事都能干。<br><br>牛吧？C++提供了一个模板机制，这些大牛们居然可以用模板把编译器耍得团团转，居然能在程序还没运行的时候就什么都能干。反正我是崇拜得五体投地。直到最近看书，才找到了它的奥秘所在，当然了，只限于基本原理。<br><br>那么，这个基本原理是怎样的呢？其实就是靠的模板的实例化，和使用枚举值或静态常量。具体来说是这样：当编译器遇到enum的定义的时候，就会对该enum进行求值，这个求值是在编译期进行的，而如果该enum对应的表达式是一个模板类的成员，则会实例化该模板类，而实例化模板类的时候，又是递归进行的，这样，就可以在递归的过程中作我们想做的任何事（理论上可以做任何事，但是以我的水平，也就只能算算加减乘除）。看起来是不是不好理解？没关系，下面看一个例子，计算N的阶乘：  <div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><span style="color: #000000">template </span><span style="color: #000000">&lt;</span><span style="color: #0000ff">int</span><span style="color: #000000"> N</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br></span><span style="color: #0000ff">class</span><span style="color: #000000"> Factorial<br>{<br></span><span style="color: #0000ff">public</span><span style="color: #000000">:<br>&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff">enum</span><span style="color: #000000"> { result </span><span style="color: #000000">=</span><span style="color: #000000"> N </span><span style="color: #000000">*</span><span style="color: #000000"> Factorial</span><span style="color: #000000">&lt;</span><span style="color: #000000">N</span><span style="color: #000000">-</span><span style="color: #000000">1</span><span style="color: #000000">&gt;</span><span style="color: #000000">::result };<br>};</span></div><br>这下该明白了吧，为了得到Factorial&lt;N&gt;::result的值，就会实例化Factorial&lt;N&gt;，然后又会实例化Factorial&lt;N-1&gt;，依次类推，一直递归下去。那么什么时候结束呢？所以还需要一个特化版本：<br> <div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><span style="color: #000000">template</span><span style="color: #000000">&lt;&gt;</span><span style="color: #000000"><br></span><span style="color: #0000ff">class</span><span style="color: #000000"> Factorial</span><span style="color: #000000">&lt;</span><span style="color: #000000">1</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br>{<br></span><span style="color: #0000ff">public</span><span style="color: #000000">:<br>&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff">enum</span><span style="color: #000000"> { result </span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000"> };<br>}</span></div><br>下面写几行代码测试一下，如下：<br> <div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><span style="color: #0000ff">int</span><span style="color: #000000"> main()<br>{<br>&nbsp;&nbsp;&nbsp; std::cout </span><span style="color: #000000">&lt;&lt;</span><span style="color: #000000"> Factorial</span><span style="color: #000000">&lt;</span><span style="color: #000000">10</span><span style="color: #000000">&gt;</span><span style="color: #000000">::result </span><span style="color: #000000">&lt;&lt;</span><span style="color: #000000"> std::endl;<br>&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">;<br>}</span></div><br>OK，事情就这么简单。大家都知道，递归可以代替循环，就只是对内存的消耗大一些，所以递归的层次不能太多。解决了循环的问题，那么分支结构如何解决呢？<br><br>不用担心，看看下面这样的模板定义：<br> <div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><span style="color: #000000">template </span><span style="color: #000000">&lt;</span><span style="color: #0000ff">bool</span><span style="color: #000000"> C, typename Ta, typename Tb</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br></span><span style="color: #0000ff">class</span><span style="color: #000000"> IfThenElse;<br><br>template </span><span style="color: #000000">&lt;</span><span style="color: #000000">typename Ta, typename Tb</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br></span><span style="color: #0000ff">class</span><span style="color: #000000"> IfThenElse</span><span style="color: #000000">&lt;</span><span style="color: #0000ff">true</span><span style="color: #000000">, Ta, Tb</span><span style="color: #000000">&gt;</span><span style="color: #000000">{<br></span><span style="color: #0000ff">public</span><span style="color: #000000">:<br>&nbsp;&nbsp;&nbsp; typedef Ta ResultT;<br>};<br><br>template </span><span style="color: #000000">&lt;</span><span style="color: #000000">typename Ta, typename Tb</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br></span><span style="color: #0000ff">class</span><span style="color: #000000"> IfThenElse</span><span style="color: #000000">&lt;</span><span style="color: #0000ff">false</span><span style="color: #000000">, Ta, Tb</span><span style="color: #000000">&gt;</span><span style="color: #000000">{<br></span><span style="color: #0000ff">public</span><span style="color: #000000">:<br>&nbsp;&nbsp;&nbsp; typedef Tb ResultT;<br>};</span></div><br>一个模板类加上两个局部特化版本就解决了问题，如果第一个模板参数是true，则选择Ta作为结果，否则就选择Tb作为结果。<br><br>虽然C++为我们提供了模板元编程的能力，虽然我现在知道了它的基本实现机制，但是我依然想不到究竟什么时候需要用到模板元编程。看来我还需要读更多的书更多的文章。同时，我觉得我们还是应该保持简单的事情简单化，继续写我的简单代码吧。</div></div></div><img src ="http://www.cppblog.com/woaidongmao/aggbug/60522.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/woaidongmao/" target="_blank">肥仔</a> 2008-08-31 21:23 <a href="http://www.cppblog.com/woaidongmao/archive/2008/08/31/60522.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>业务逻辑的强类型化</title><link>http://www.cppblog.com/woaidongmao/archive/2008/07/27/57303.html</link><dc:creator>肥仔</dc:creator><author>肥仔</author><pubDate>Sun, 27 Jul 2008 09:10:00 GMT</pubDate><guid>http://www.cppblog.com/woaidongmao/archive/2008/07/27/57303.html</guid><wfw:comment>http://www.cppblog.com/woaidongmao/comments/57303.html</wfw:comment><comments>http://www.cppblog.com/woaidongmao/archive/2008/07/27/57303.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/woaidongmao/comments/commentRss/57303.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/woaidongmao/services/trackbacks/57303.html</trackback:ping><description><![CDATA[<p style="FONT-SIZE: 12pt"><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 业务逻辑中，很多逻辑上不同类型的东西，到了编程语言中，时常会退化成一种类型。一个最简单的例子就是货币。通常在我们编程时，采用一种类型，如double（有些系统中有专门的Currency类型，为了简便起见，这里使用double），来表示货币。<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 但是，随之而来的就是币种的问题。不同的币种间存在换算，也就是汇率的问题。比如我们有RMB和USD两种货币，分别表示人民币和美元。尽管都是货币（在代码中有相同的类型），我们却不能对他们直接赋值：<br><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>double rmb_;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>double usd_=100;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>rmb_=usd_;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //绝对不行，100美元可相当于768元人民币，尽管人民币在升值<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>必须进行汇率换算：<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>rmb_=usd_*e_rate;<br><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp; e_rate就是汇率。这个谁都清楚。在逻辑上，100美元和768元人民币是等价的（假设今天的汇率是7.68），是可以兑换的。但在软件中，我们不能简单的赋值了事，必须做换算。现在我们希望用代码直接表现逻辑上的意义，也就是用赋值操作：=，实现货币间的换算，该怎么做呢？啊对，没错，操作符重载。<br><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp; 我们可以重载operator=操作符，使其具备汇率换算的功能。（或许有人会提出异议，改变一个操作符已有的语义，是否违背大师们的教诲。但我个人认为，语义应当遵从业务逻辑，既然按照逻辑含义进行重载，不应该引发什么纠纷。否则还需要重载干吗？）但问题是，重载依赖于不同的类型，double operator=(double)的操作符定义是默认的，已经存在，无法以相同形式重载。再说，即便是可以，复制对象和被赋值对象的类型相同，如何区分两种类型的转换呢？<br><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp; 很明显，我们需要新的类型。typedef肯定是没指望的，因为它仅仅为一个类型起别名，并没有产生新的类型。所以，我们只能求助于类。我们可以以如下方式定义各种不同的货币类：<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>class RMB<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>public:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp; double&nbsp;&nbsp;&nbsp; _val;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>};<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>class USD<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>public:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp; double&nbsp;&nbsp;&nbsp; _val;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>};<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&#8230;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>这样，便可以针对不同货币重载operator=：<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>class RMB<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>public:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp; RMB operator=(const RMB&amp; v) {<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; _val=v._val;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp; }<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp; RMB operator=(const USD&amp; v) {<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; _val=v._val*e_rate;&nbsp;&nbsp;&nbsp; //货币换算<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp; }<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>public:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp; double&nbsp;&nbsp;&nbsp; _val;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>};<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>class USD<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>public:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp; USD operator=(const USD&amp; v) {<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; _val=v._val;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp; }<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp; USD operator=(const RMB &amp; v) {<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; _val=v._val/e_rate;&nbsp;&nbsp;&nbsp; //货币换算<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp; }<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>public:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp; double&nbsp;&nbsp;&nbsp; _val;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>};<br><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>这样，我们便可以对两种货币赋值了：<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>RMB&nbsp;&nbsp;&nbsp; rmb_;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>USD&nbsp;&nbsp;&nbsp; usd_;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>rmb_=usd_;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //带货币换算的赋值操作<br><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 根据这个方法，我们一直往下推，可以构造出各种各样的货币，并且定义它们之间的转换：<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>class UKP&nbsp;&nbsp;&nbsp; //英镑<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>{&#8230;}<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>class JPD&nbsp;&nbsp;&nbsp; //日元<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>{&#8230;}<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&#8230;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 不过有个问题，如果有10中货币，我们必须定义100个operator=的重载，而且都是些重复代码。这样太蠢了。得采用更好的方法才能实现我们的理想。注意观察，每个货币类的代码都符合同一种模式，有很强的规律性。看出来了吧，这种情况非常适合使用C++的超级武器——模板。没错，说做就做：<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>template</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">int </span><span style="COLOR: #ff0000">CurrType</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>class Currency<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>public:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp; double&nbsp;&nbsp;&nbsp; _val;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>};<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 注意看，这里非常规地使用了模板的一个特性：非类型模板参数，就是那个int CurrType。模板参数通常都是一个类型，比如int什么的。但也可以是一个非类型的模板参数，就象这里的CurrType。传统上，非类型模板参数用于传递一个静态的值，用来构造模板类。但在这里，这个模板参数并没有被模板使用，也永远不会被使用。这个模板参数的作用就是&#8220;制造类型&#8221;：<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>typedef&nbsp;&nbsp;&nbsp; Currency</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">0</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp; RMB;&nbsp;&nbsp;&nbsp; //人民币<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>typedef&nbsp;&nbsp;&nbsp; Currency</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">1</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp; USD;&nbsp;&nbsp;&nbsp; //美元<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>typedef&nbsp;&nbsp;&nbsp; Currency</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">2</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp; UKP;&nbsp;&nbsp;&nbsp; //英镑<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>typedef&nbsp;&nbsp;&nbsp; Currency</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">3</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp; JPD;&nbsp;&nbsp;&nbsp; //日元<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&#8230;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>typedef本身不会产生新的类型，但是这里Currency</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">n</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000">已经是完全不同的类型了。当一个模板被实例化成一个类的时候，只要模板参数的实参有所不同，便是一个不同的类型。我们利用了模板的这个特性，凭空制造出任意多个结构完全相同，但却是完全独立的类型。<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>好，下一步，便是重载operator=操作符。当然不能再做为每一对货币类型重载operator=的蠢事了。用一个成员函数模板就可以解决问题：<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>double e_rate[10][10];&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //汇率表<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>template</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">int </span><span style="COLOR: #ff0000">CurrType</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>class Currency<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>public:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp; template</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">int </span><span style="COLOR: #ff0000">ct2</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp; Currency</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">CurrType</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000">&amp; operator=(count Currency</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">ct2</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000">&amp; v) {<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; _val=v._val * e_rate[ct2][CurrType];&nbsp;&nbsp;&nbsp; //找出汇率表中相应的汇率，<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 计算并赋值<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp; }<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>public:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp; double&nbsp;&nbsp;&nbsp; _val;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>};<br><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp; 操作符operator=的代码中，赋值对象v的值乘上一个汇率，这个汇率存放在汇率表中，通过模板参数CurrType和ct2检索（当然汇率表得足够大）。这样，我们便可以随意地赋值，而无须关心货币转换的问题了：<br><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>///初始化汇率表<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>e_rate[0][0]=1;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>e_rate[1][0]=7.68;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&#8230;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>//使用货币<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>USD&nbsp;&nbsp;&nbsp; usd_;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>UKP&nbsp;&nbsp;&nbsp; ukp_;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>JPD&nbsp;&nbsp;&nbsp; jpd_;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>jpd_=usd_=ukp=rmb_;&nbsp;&nbsp;&nbsp; //成功！一切顺心。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 需要说明的是，汇率表并没有在声明时就初始化，是考虑到汇率经常变动，不应当作为常量写死在代码中。更进一步可以使用一个类封装成可变大小的汇率表，甚至可以用某个文件或数据库对其初始化。<br><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>问题当然还有，货币是要参与运算的，否则没有什么用处。所以，我们还得使这些货币具备基本的计算能力。货币的计算，根据业务逻辑大致应具备以下能力：<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>1.&nbsp;&nbsp;&nbsp; +、-：两种货币的加法和减法，允许不同种货币参与计算，必须考虑转换操作，返回做操作数类型；<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>2.&nbsp;&nbsp;&nbsp; *、/：货币乘上或除以一个标量值，这里设定为double。但两种货币不能相乘或相除。<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>3.&nbsp;&nbsp;&nbsp; ==、!=：比较两种货币，允许不同种货币参与比较，但必须考虑转换操作。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 还有其他的操作，暂不做考虑，毕竟这里的目的不是开发一个完整的货币系统。为了编码上的方便，这里同时还定义了四则运算的赋值版本：+=、-=、*=、/=。为了节省篇幅，这里只展示+、*和==的代码，其他代码类推：<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>template</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">int </span><span style="COLOR: #ff0000">ty, int tp</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>inline bool operator==(currency</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">ty</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000">&amp; c1, const currency</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">tp</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000">&amp; c2) {<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp; return&nbsp;&nbsp;&nbsp; c1._val==c2._val*curr_rate[tp][ty];<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>}<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>template</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">int </span><span style="COLOR: #ff0000">ty, int tp</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>inline currency</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">ty</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000">&amp; operator+=(currency</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">ty</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000">&amp; c1, const currency</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">tp</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000">&amp; c2) {<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp; c1._val+=c2._val*curr_rate[tp][ty];<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp; return&nbsp;&nbsp;&nbsp; c1;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>}<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>template</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">int </span><span style="COLOR: #ff0000">ty, int tp</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>inline currency</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">ty</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"> operator+(currency</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">ty</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000">&amp; c1, const currency</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">tp</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000">&amp; c2) {<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp; currency</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">ty</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"> t(c1);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp; t+=c2;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp; return&nbsp;&nbsp;&nbsp; t;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 请注意==和+操作符中的的货币转换运算，每次都是将第二操作数货币转换成第一操作数货币后再进行运算操作。第一参数和第二参数的类型不同，因此允许不同货币进行计算。这可以进一步简化代码，完全以逻辑的方式编程。<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>template</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">int </span><span style="COLOR: #ff0000">ty</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>inline currency</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">ty</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000">&amp; operator*=(currency</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">ty</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000">&amp; c1, const double q) {<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp; c1._val*=q;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp; return&nbsp;&nbsp;&nbsp; c1;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>}<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>template</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">int </span><span style="COLOR: #ff0000">ty</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>inline currency</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">ty</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"> operator*(currency</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">ty</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000">&amp; c1, const double q) {<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp; currency</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">T</span><span style="COLOR: #ff0000">, ty</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp; t(c1);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp; t*=q;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp; return&nbsp;&nbsp;&nbsp; t;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>}<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>template</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">int </span><span style="COLOR: #ff0000">ty</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>inline currency</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">ty</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000">&amp; operator*=(const double q，currency</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">ty</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000">&amp; c1) {<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp; return&nbsp;&nbsp;&nbsp; operator*=(c1, q);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>}<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>template</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">int </span><span style="COLOR: #ff0000">ty</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>inline currency</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">ty</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"> operator*(const double q，currency</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">ty</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000">&amp; c1) {<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp; return&nbsp;&nbsp;&nbsp; operator*(c1, q);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>}<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&#8230;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *操作符的参数只有一个是货币类型，另一个是double类型，表示数量。只有货币乘上数量才有意义，不是吗？*操作符包括两个版本，一个货币在前，数量在后；另一个数量在前，货币在后。为的是适应rmb_*1.4和1.4*rmb_两种不同的写法，算法是完全一样的。<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>现在，货币可以运算了：<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>usd_=usd_*3;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //同种货币运算<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>ukp_=rmb_*2.5;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ///计算後直接赋值给另一种货币<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>jpd_=ukp_=rmb_+usd_;&nbsp;&nbsp;&nbsp; &nbsp;///同上，但有四种货币参与运算<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>现在，货币运算非常方便了，不需要考虑货币种类，货币的转换是自动的，无需额外代码。在简化代码的同时，也提供了操作上的约束，比如：<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>ukp_=rmb_*usd_;&nbsp;&nbsp;&nbsp; ///编译错误。货币乘上另一种货币无意义！！！<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 这句代码会引发编译错误，因为我们没有为两种货币相乘提供*的重载。很明显，一种货币与另一种货币相乘是根本没有意义的。这里通过静态的重载类型检查，对施加在货币上的运算做出约束。促使违背逻辑的代码在第一时间被拦截，避免出现运行时错误。要知道，两种货币相乘，赋给另一个货币的错误是非常隐蔽的，只有盘库或结账的时候才会发现。<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 很好，这里我们利用了C++模板的一些特殊机制，以及操作符模板、操作符重载等技术，开发一个货币系统。这个系统可以用最简洁的语句实现各种货币的计算和转换功能。同时，还利用重载机制的强类型特性，提供了符合业务逻辑的操作约束。<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 货币运算只是一个简单的案例，但相关的技术可以进一步推广到更复杂的领域中。而且业务越复杂，所得到的收益越多。因此，充分理解并运用C++所带来的泛型编程功能，可以大大简化软件的开发、减少代码的错误，降低开发的成本。<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 这种技术适合用在一些逻辑上存在差异，但在物理上具备相同特征的实体上。一方面使这些实体在代码中强类型化，以获得重载和类型检测能力。由于代码中逻辑实体的对应类型强类型化，是我们可以通过重载和静态类型检测等技术手段，实现仅使用语言提供的要素，在代码中直接构造业务模型的能力。但手工对每一个逻辑实体进行强类型化，是费力的和琐碎的，并且存在着大量的重复劳动。此时，我们可以利用模板的抽象能力，反过来利用逻辑实体在物理上的共同特性，一次性构建抽象的模板，并利用模板实例化的一些特性，很方便地构造新的类型（仅仅一个typedef）。<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp; 这种技术进一步扩展后，可以有更高级的应用。<span style="COLOR: red">一个经典的范例就是实现编译期的量纲分析。在Template Meta-programming一书中，对此有详细的讲解</span>。<br><br>================================================================================================<img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img style="WIDTH: 11px; HEIGHT: 16px" height=16 src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" width=11 align=top>作为一个好事者，我希望能够给我周边的人讲解这种技术。他们对C++很不熟悉，但熟悉C#。于是，我打算把这种技术移植到C#中，以便於讲解。说做就做。<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>我建了一个C#项目，把代码拷贝过去，然后着手修改，这样可以省些事。我立刻便遇到了问题。C#有泛型，相当于模板，但不支持非类型泛型参数，即int CurrType，只允许用一个类型作为泛型参数。这样我们就不能使用C++中耍的手法了（typedef currency</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">n</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000">）。退而求其次，直接用类实现货币类型：<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>class RMB<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>public double _val;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>}<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>class USD<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>public double _val;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>}<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&#8230;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>这样太繁琐了，很多重复。我们可以用一个基类封装_val，货币类从基类上继承获得：<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>class CurrBase<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>public double _val;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>}<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>class RMB : CurrBase<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>}<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>class USD : CurrBase<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>}<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&#8230;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>货币类都是空的，它们的存在只是为了创建一个新的类型。<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>现在处理货币转换问题。C#不能重载operator=，所以只能使用一个helper函数泛型asign代替：<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>class utility<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp; public static void asign</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">T1</span><span style="COLOR: #ff0000">, T2</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000">(T1 c1, T2 c2)<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; where T1 : CurrBase<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; where T2 : CurrBase<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp; {<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; c1._val = c2._val * utility.e_rate[c2.CurID(),c1.CurID()];<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp; }<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>}<br><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>这个asign函数是个泛型，泛型参数分别代表了两个操作数，函数中执行了货币转换。为了能够在汇率表中检索到相应的汇率，我们必须为基类和货币类定义抽象函数：<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp; public abstract class CurrBase<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp; {<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public double _val=0;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public abstract int CurID();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp; }<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp; public class RMB : CurrBase<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp; {<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public override int CurID()<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 0;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>}<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&#8230;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>基类中声明了CurID()抽象方法，并在货币类中定义。这样，便可以用统一的方式进行货币转换了：<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>asign(rmb_, usd_);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>还行，尽管不那么漂亮，但也还算实用。不过，当我多看了几眼代码后，便发现这里根本没有必要使用泛型。完全可以利用OOP的多态实现同样的功能：<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp; public static void asign(CurrBase c1, CurrBase c2)<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp; {<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; c1._val = c2._val * utility.e_rate[c2.CurID(),c1.CurID()];<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp; }<br><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>不过也没关系，使用方式还没有变，代码反而更简单了。使用泛型毕竟不是我们的根本目的，对吧？<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>现在轮到运算符了。不过我不知该把泛型运算符定义在哪里。按C#文档里的要求，运算符必须是类的static成员。但我的泛型运算符是针对许多个货币类的，定义在任何一个中，对其他类似乎不太公平。于是，我决定尝试将其定义在基类里：<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp; public abstract class CurrBase<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp; &#8230;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public static CurrBase operator+</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">T1</span><span style="COLOR: #ff0000">, T2</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000">(T1 c1, T2 c2)<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; where T1 : CurrBase<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; where T2 : CurrBase<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8230;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>}<br><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>编译器立刻还我以颜色：操作符根本不能是泛型！好吧，不能就不能吧，继续退而求其次，用OOP：<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp; public abstract class CurrBase<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp; &#8230;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public static CurrBase operator+(CurrBase c1, CurrBase c2)<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8230;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>}<br><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>不过，这次让步让得有点离谱。当我写下这样的代码时，编译器居然不认账：<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>rmb_=rmb_+usd_;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>错误信息是：错误 CS0266: 无法将类型&#8220;st_in_cs.CurrBase&#8221;隐式转换为&#8220;st_in_cs.RMB&#8221;。存在一个显式转换(是否缺少强制转换?)。<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>我非得采用强制类型转换，才能过关：<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>rmb_=(RMB)(rmb_+usd_);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>太夸张了，这样肯定不行。于是，我被迫在每个货币类中定义operator+：<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>class RMB : CurrBase<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&#8230;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp; public RMB operator+(RMB c1, USD c2)<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp; {<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8230;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp; }<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp; public RMB operator+(RMB c1, UKP c2)<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp; {<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8230;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp; }<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&#8230;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>}<br><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>这可不得了，我必须为每对货币类定义一个+操作符，+操作符的总数将会是货币类数量的平方！其他的操作符每个都是货币类数的平方。我可受不了！<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>好在，可爱的OOP为我们提供了一根稻草，使得每个货币类的每个操作符只需定义一个：<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>class RMB : CurrBase<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&#8230;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp; public RMB operator+(RMB c1, CurrBase c2)<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp; {<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8230;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp; }<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&#8230;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>}<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>这样，任何货币类都可以作为第二操作数参与运算，而操作符只需定义一个。这样的工作量，对于一个逆来顺受的程序员而言，还是可以接受的。很好，代码不出错了：<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>rmb_=rmb_+usd_;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>但当我写下如下代码时，编译器又开始抱怨了：<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>ukp_ = rmb_ + usd_;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>还是要求显示转换，除非我们为UKP定义隐式类型转换操作符：<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>class UKP<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&#8230;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp; public static implicit operator UKP(RMB v)<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp; {<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8230;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp; }<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&#8230;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>}<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>光有RMB的不行啊，还得有USD的、JPD&#8230;。不过这样的话，我们必须为每一个货币类定义所有其它货币类的类型转换操作符。又是一个组合爆炸。到这里，我已经黔驴技穷了。谁让C#不支持=操作符重载和操作符模板化呢。没办法，只能忍着点了。<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>不过，如果我们能够降低点要求，事情还是有转机的。如果我们不通过操作符，而是采用static成员方法，进行货币的运算的话，就可以省去很多代码了：<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp; public class utility<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp; {<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public static T1 asign</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">T1</span><span style="COLOR: #ff0000">, T2</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000">(T1 c1, T2 c2)<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; where T1 : CurrBase, new()<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; where T2 : CurrBase<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; c1._val = c2._val * utility.curr_rate[c2.CurID(),c1.CurID()];<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return&nbsp;&nbsp;&nbsp; c1;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public static T1 add</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">T1</span><span style="COLOR: #ff0000">, T2</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000">(T1 c1, T2 c2)<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; where T1 : CurrBase, new()<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; where T2 : CurrBase<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; T1 t=new T1();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; t._val=c1._val + c2._val * <br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; utility.curr_rate[c2.CurID(),c1.CurID()];<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return t;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8230;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>}<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>这里，我还是使用了泛型，因为这些函数需要返回一个值，只有使用泛型，才能返回一个明确的类型，以避免强制转换的要求。于是，赋值和计算的代码就成了：<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>asign(jpd_, asign(ukp_, add(rmb_, usd_)));//也就是jpd_=ukp_=rmb_+usd_<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>的确是难看了点，但是为了能够少写点代码，这也只能将就了。<br><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>好了，我尽了最大的努力，试图在C#中实现强类型、可计算的货币系统。尽管最终我可以在C#中开发出一组与C++具有相同效果的货币类（除了赋值操作以外），但需要我编写大量的代码，实现各种计算操作，以及货币类之间的类型转换操作（组合爆炸）。相比C++中总共200来行代码，的确复杂、臃肿得多。<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>我并不希望把这篇文章写成&#8220;C++ vs C#&#8221;，（尽管我很高兴看到C++比C#强）。我希望通过对这样一个代码优化任务，显示不同技术运用产生的结果。同时，也可以通过这两种实现尝试的对比，了解泛型编程的作用，以及泛型编程对语言提出的要求。<br><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>毋庸置疑，C++采用了纯粹的泛型编程，因此可以对问题进行高度抽象。并利用问题所提供的每一点有助于抽象的信息，以最简的形式对问题建模。而作为以OOP为核心的语言C#，对泛型的支持很弱。更重要的是，C#的泛型对泛型参数的运用严重依赖於泛型参数的约束（where）。如果没有where，C#将泛型参数作为Object类型处理，此时泛型参数没有意义（我无法访问该类型的成员）。如果有了where，C#要求泛型参数必须同where中指定的类型有继承关系（如asign中的T1必须是CurrBase的继承类）。而泛型函数中对泛型参数的使用也局限在约束类型（即CurrBase）上。于是，我们可以直接用以基类（CurrBase）为参数的asign函数代替泛型版本的asign。由于C#对泛型参数的继承性要求，使得泛型被困住了手脚，无法发挥应用的作用。正由于这些问题，C++才采用了现在模板的形式，而没有采用同C#一样的泛型模式。<br><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>或许有人会说，既然OOP能解决问题（asign最初不需要泛型也行，但最终还需要泛型来控制返回值的类型），为什么还要GP呢？<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>对于这个问题，前面也给出了答案。由于C#的泛型不支持非类型泛型参数，因此迫使我们使用传统OOP的手段：利用基类实现货币类的实现，定义货币类来创建新类型，使货币强类型化，利用虚函数提供货币独有信息。仅这一层面，OOP方式已经大大不如GP方式了，GP仅定义了一个模板，所有的货币类型都是通过typedef一句语句产生，无需更多的代码。而OOP方式要求必须为每一个货币编写一个类，代码量明显多于GP方式。<br><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>此后，C++通过重载一组操作符模板，实现货币的运算。而货币模板以及生成货币类型的typedef都无须任何改变。而在C#中，由于不支持泛型操作符，被迫定义大量的特定于类型的操作符。所有运算操作符，在每个货币类中都必须重载一次。而转型操作符，则必须在每个货币类中重载n-1次。<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>换句话说，有n种货币，有m个操作符（包括转型操作符），那么就需要定义n+1个类（包括基类），n&#215;m+n&#215;(n-1)个操作符。假设n=10，m=10，那么总共需要11个类定义，190个操作符重载！如果每个类定义需要20行代码，而每个操作符重载需要5行代码，那么总共需要1170行代码。如果货币数量增加，总的代码数将以几何级数的方式增长。<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>上面的计算表明，尽管OOP可以解决问题，实现我们的目标，但所带来的开发量和维护量却是难以承受的。而且，OOP的方式扩展非常困难，随着系统规模的扩大，扩展将越来越困难。所有这些都表明一点，尽管OOP是软件工程的明星，但在实际情况下，很多地方存在着OOP无法解决或难以解决的问题。这也就是为什么业界的先锋人物不断拓展和强化泛型编程的原因。<br></span></p>
<img src ="http://www.cppblog.com/woaidongmao/aggbug/57303.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/woaidongmao/" target="_blank">肥仔</a> 2008-07-27 17:10 <a href="http://www.cppblog.com/woaidongmao/archive/2008/07/27/57303.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>