﻿<?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++博客-beautykingdom-随笔分类-Template</title><link>http://www.cppblog.com/beautykingdom/category/7617.html</link><description /><language>zh-cn</language><lastBuildDate>Wed, 05 May 2010 09:21:31 GMT</lastBuildDate><pubDate>Wed, 05 May 2010 09:21:31 GMT</pubDate><ttl>60</ttl><item><title>Template specialization</title><link>http://www.cppblog.com/beautykingdom/archive/2010/05/03/114290.html</link><dc:creator>chatler</dc:creator><author>chatler</author><pubDate>Mon, 03 May 2010 14:11:00 GMT</pubDate><guid>http://www.cppblog.com/beautykingdom/archive/2010/05/03/114290.html</guid><wfw:comment>http://www.cppblog.com/beautykingdom/comments/114290.html</wfw:comment><comments>http://www.cppblog.com/beautykingdom/archive/2010/05/03/114290.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/beautykingdom/comments/commentRss/114290.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/beautykingdom/services/trackbacks/114290.html</trackback:ping><description><![CDATA[If we want to define a different implementation for a template when a
specific type is passed as template parameter, we can declare a
specialization of that template.<br>
<br>
For example, let's suppose that we have a very simple class called
<tt>mycontainer</tt>
that can store one element of any type and that it has just one member
function called
<tt>increase</tt>, which increases its value. But we
find that when it stores an element of type
<tt>char</tt> it would be
more convenient to have a completely different implementation with a
function member
<tt>uppercase</tt>, so we decide to declare a class
template specialization for that type:<br>
<br>
<div class="auto">
<table class="split">
    <tbody>
        <tr>
            <td class="rownum">
            <tt>1<br>2<br>3<br>4<br>5<br>6<br>7<br>8<br>9<br>10<br>11<br>12<br>13<br>14<br>15<br>16<br>17<br>18<br>19<br>20<br>21<br>22<br>23<br>24<br>25<br>26<br>27<br>28<br>29<br>30<br>31<br>32<br>33<br>34<br></tt></td>
            <td class="source">
            <pre><code><cite>// template specialization</cite><br><dfn>#include &lt;iostream&gt;</dfn><br><var>using</var> <var>namespace</var> std;<br><br><cite>// class template:</cite><br><var>template</var> &lt;<var>class</var> T&gt;<br><var>class</var> mycontainer {<br>    T element;<br>  <var>public</var>:<br>    mycontainer (T arg) {element=arg;}<br>    T increase () {<var>return</var> ++element;}<br>};<br><br><cite>// class template specialization:</cite><br><var>template</var> &lt;&gt;<br><var>class</var> mycontainer &lt;<var>char</var>&gt; {<br>    <var>char</var> element;<br>  <var>public</var>:<br>    mycontainer (<var>char</var> arg) {element=arg;}<br>    <var>char</var> uppercase ()<br>    {<br>      <var>if</var> ((element&gt;=<kbd>'a'</kbd>)&amp;&amp;(element&lt;=<kbd>'z'</kbd>))<br>      element+=<kbd>'A'</kbd>-<kbd>'a'</kbd>;<br>      <var>return</var> element;<br>    }<br>};<br><br><var>int</var> main () {<br>  mycontainer&lt;<var>int</var>&gt; myint (7);<br>  mycontainer&lt;<var>char</var>&gt; mychar (<kbd>'j'</kbd>);<br>  cout &lt;&lt; myint.increase() &lt;&lt; endl;<br>  cout &lt;&lt; mychar.uppercase() &lt;&lt; endl;<br>  <var>return</var> 0;<br>}</code></pre>
            </td>
            <td class="output">
            <pre><samp>8<br>J</samp></pre>
            </td>
        </tr>
    </tbody>
</table>
</div>
<br>
<br>
This is the syntax used in the class template specialization:<br>
<br>
<div class="auto">
<table class="snippet">
    <tbody>
        <tr>
            <td class="rownum">
            <tt>&nbsp;</tt></td>
            <td class="source">
            <pre><code><var>template</var> &lt;&gt; <var>class</var> mycontainer &lt;<var>char</var>&gt; { ... };</code></pre>
            </td>
        </tr>
    </tbody>
</table>
</div>
<br>
<br>
First of all, notice that we precede the class template name with an
empty
<tt>template&lt;&gt;</tt> parameter list. This is to explicitly
declare it as a template specialization.<br>
<br>
But more important than this prefix, is the
<tt>&lt;char&gt;</tt>
specialization parameter after the class template name. This
specialization parameter itself identifies the type for which we are
going to declare a template class specialization (
<tt>char</tt>). Notice
the differences between the generic class template and the
specialization:<br>
<br>
<div class="auto">
<table class="snippet">
    <tbody>
        <tr>
            <td class="rownum">
            <tt>1<br>2<br></tt></td>
            <td class="source">
            <pre><code><var>template</var> &lt;<var>class</var> T&gt; <var>class</var> mycontainer { ... };<br><var>template</var> &lt;&gt; <var>class</var> mycontainer &lt;<var>char</var>&gt; { ... };</code></pre>
            </td>
        </tr>
    </tbody>
</table>
</div>
<br>
<br>
The first line is the generic template, and the second one is the
specialization.<br>
<br>
When we declare specializations for a template class, we must also
define all its members, even those exactly equal to the generic template
class, because there is no "inheritance" of members from the generic
template to the specialization.
<br><br>from:<br><a  href="http://www.cplusplus.com/doc/tutorial/templates/">http://www.cplusplus.com/doc/tutorial/templates/</a>
<br><br><img src ="http://www.cppblog.com/beautykingdom/aggbug/114290.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/beautykingdom/" target="_blank">chatler</a> 2010-05-03 22:11 <a href="http://www.cppblog.com/beautykingdom/archive/2010/05/03/114290.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>A Description of the C++ typename keyword</title><link>http://www.cppblog.com/beautykingdom/archive/2010/04/19/112970.html</link><dc:creator>chatler</dc:creator><author>chatler</author><pubDate>Mon, 19 Apr 2010 03:58:00 GMT</pubDate><guid>http://www.cppblog.com/beautykingdom/archive/2010/04/19/112970.html</guid><wfw:comment>http://www.cppblog.com/beautykingdom/comments/112970.html</wfw:comment><comments>http://www.cppblog.com/beautykingdom/archive/2010/04/19/112970.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/beautykingdom/comments/commentRss/112970.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/beautykingdom/services/trackbacks/112970.html</trackback:ping><description><![CDATA[<div id="content">
<p>[Originally written sometime in December, 2006. Fixed a couple markup
errors, changed some wording, and added a little bit 12/23/2007. I
still don't quite consider it complete; I haven't explained all the
rules yet. I have a ranty version of what I want to add <a  href="http://pages.cs.wisc.edu/%7Edriscoll/typename.txt">here</a>; start
reading where it says "[RESUMING]" if you read this document first.]</p>
<p>The purpose of this document is to describe the reasoning behind
the inclusion of the <tt>typename</tt> keyword in standard C++, and
explain where, when, and how it can and can't be used.</p>
<h2>A secondary use</h2>
<p>There is a use of <tt>typename</tt> that is entirely distinct from
the
main focus of this discussion. I will present it first because it is
easy. It seems to me that someone said "hey, since we're adding
<tt>typename</tt> anyway, why not make it do this" and people said
"that's a good idea."</p>
<p>Most older C++ books, when discussing templates, use the following
type of example:</p>
<pre>template &lt;class T&gt; ...</pre>
<p>I know when I was starting to learn templates, at first I was a
little thrown by the fact that <tt>T</tt> was prefaced by
<tt>class</tt>, and yet it was possible to instantiate that template
with primitive types such as <tt>int</tt>. The confusion was very
short-lived, but the use of <tt>class</tt> in that context never
seemed to fit entirely right. Fortunately for my sensibilities, it is
also possible to use <tt>typename</tt>:</p>
<pre>template &lt;typename T&gt; ...</pre>
<p>This means exactly the same thing as the previous instance. The
<tt>typename</tt> and <tt>class</tt> keywords can be used
interchangeably to state that a template parameter is a type
variable (as opposed to a non-type template parameter).</p>
<p>I personally like to use <tt>typename</tt> in this context because
I think it's ever so slightly clearer. And maybe not so much "clearer"
as just conceptually nicer. (I think that good names for things are
very important.) Some C++ programmers share my view, and use
<tt>typename</tt> for templates. (However, later we will see how it's
possible that this decision can hurt readibility.) Some programmers
make a distinction between templates that are fully generic (such as
the STL containers) and more special purpose ones that can only take
certain classes, and use <tt>typename</tt> for the former category and
<tt>class</tt> for the latter. Others use <tt>class</tt>
exclusively. This is just a style choice.</p>
<p>However, while I use <tt>typename</tt> in real code, I will stick
to <tt>class</tt> in this document to reduce confusion with the other
use of <tt>typename</tt>.</p>
<h2>The <em>real</em> reason for <tt>typename</tt></h2>
<p>This discussion I think follows fairly closely appendix B from the
book <em>C++ Template Metaprogramming: Concepts, Tools, and Techniques
from Boost and Beyond</em> by David Abrahams and Aleksey Gurtovoy,
though I don't have it in front of me now. If there are any
deficiencies in my discussion of the issues, that book contains the
clearest description of them that I've seen.</p>
<h3>Some definitions</h3>
<p>There are two key concepts needed to understand the description of
<tt>typename</tt>, and they are <em>qualified</em> and <em>dependent</em>
names.</p>
<h4>Qualified and unqualified names</h4>
<p>A qualified name is one that specifies a scope. For instance, in
the following C++ program, the references to <tt>cout</tt> and
<tt>endl</tt> are qualified names:</p>
<pre>#include &lt;iostream&gt;<br><br>int main()  {<br>   std::cout %lt;%lt; "Hello world!" %lt;%lt; std:: endl;<br>}</pre>
<p>In both cases, the use of <tt>cout</tt> and <tt>endl</tt> began
with <tt>std::</tt>.</p>
<p>Had I decided to bring <tt>cout</tt> and <tt>endl</tt> into scope
with a <tt>using</tt> declaration or directive*, they would have been
unqualified names, because they would lack the <tt>std::</tt>.</p>
<p>(* Remember, a using declaration is like <tt>using std::cout;</tt>,
and actually introduces the name <tt>cout</tt> into the scope that the
<tt>using</tt> appears in. A using directive is of the form <tt>using
namespace std;</tt> and makes names visible but doesn't introduce
anything. [12/23/07 -- I'm not sure this is true. Just a warning.])</p>
<p> Note, however, that if I had brought them into scope with
<tt>using</tt> but still used <tt>std::cout</tt>, it remains a
qualified name. The qualified-ness of a name has nothing to do with
what scope it's used in, what names are visible at that point of the
program etc.; it is solely a statement about the name that was used to
reference the entity in question. (Also note that there's nothing
special about <tt>std</tt>, or indeed about namespaces at
all. <tt>vector&lt;int&gt;::iterator</tt> is a nested name as well.)
</p>
<h4>Dependent and non-dependent names</h4>
<p>A dependent name is a name that depends on a template
parameter. Suppose we have the following declaration (not legal
C++):</p>
<pre>template &lt;class T&gt;<br>class MyClass {<br>   int i;<br>   vector&lt;int&gt; vi;<br>   vector&lt;int&gt;::iterator vitr;<br>   <br>   T t;<br>   vector&lt;T&gt; vt;<br>   vector&lt;T&gt;::iterator viter;<br>};</pre>
<p>The types of the first three declarations are known at the time of
the template declaration. However, the types of the second set of
three declarations are <em>not</em> known until the point of
instantiation, because they depend on the template parameter
<tt>T</tt>.</p>
<p>The names <tt>T</tt>, <tt>vector&lt;T&gt;</tt>, and
<tt>vector&lt;T&gt;::iterator</tt> are called dependent names, and the
types
they name are dependent types. The names used in the first three
declarations are called non-dependent names, at the types are
non-dependent types.</p>
<p>The final complication in what's considered dependent is that
typedefs transfer the quality of being dependent. For instance:</p>
<pre>typedef T another_name_for_T;</pre>
<p><tt>another_name_for_T</tt> is still considered a dependent name
despite the type variable <tt>T</tt> from the template declaration not
appearing.</p>
<p><em>Note:</em> I am not very familiar with the notion of dependent
types in the type theory sense, but they are not quite the same thing
in any case. My impression is that you could probably argue a C++
template itself is a dependent type in the type-theoretical sense, but
the C++ notion of a dependent type is more like the <em>argument</em>
to a dependent type in the type-theoretical sense.</p>
<h4>Some other issues of wording</h4>
<p>Note that while there is a notion of a dependent type, there is not a
notion of a qualified type. A type can be unqualified in one instance,
and qualified the next; the qualification is a property of a
particular naming of a type, not of the type itself. (Indeed, when a
type is first defined, it is always unqualified.)</p>
<p>However, it will be useful to refer to a qualified type; what I
mean by this is a qualified name that refers to a type. I will switch
back to the more precise wording when I talk about the rules of
<tt>typename</tt>.</p>
<h3>The problem</h3>
<p>So now we can consider the following example:</p>
<pre>template &lt;class T&gt;<br>void foo() {<br>   T::iterator * iter;<br>   ...<br>}</pre>
<p>What did the programmer intend this bit of code to do? Probably,
what the programmer intended was for there to be a class that defined
a nested type called <tt>iterator</tt>:</p>
<pre>class ContainsAType {<br>   class iterator { ... }:<br>   ...<br>};</pre>
<p>and for <tt>foo</tt> to be called with an instantiation of <tt>T</tt>
being that type:</p>
<pre>foo&lt;ContainsAType&gt;();</pre>
<p>In that case, then line 3 would be a declaration of a variable
called <tt>iter</tt> that would be a pointer to an object of type
<tt>T::iterator</tt> (in the case of <tt>ContainsAType</tt>,
<tt>int*</tt>, making <tt>iter</tt> a double-indirection pointer to an
int). So far so good.</p>
<p>However, what the programmer didn't expect is for someone else to
come up and declare the following class:</p>
<pre>class ContainsAValue {<br>   static int iterator;<br>};</pre>
<p>and call <tt>foo</tt> instantiated with it:</p>
<pre>foo&lt;ContainsAValue&gt;();</pre>
<p>In this case, line 3 becomes a statement that evaluates an
expression which is the product of two things: a variable called
<tt>iter</tt> (which may be undeclared or may be a name of a global)
and the static variable <tt>T::iterator</tt>.</p>
<p>Uh oh! The same series of tokens can be parsed in two entirely
different ways, and there's no way to disambiguate them until
instantiation. C++ frowns on this situation. Rather than delaying
interpretation of the tokens until instantiation,
they change the languge:</p>
<p><strong>Before a qualified dependent type, you need
<tt>typename</tt></strong></p>
<p>To be legal, assuming the programmer intended line 3 as a
declaration,
they would have to write</p>
<pre>template &lt;class T&gt;<br>void foo() {<br>   <strong>typename</strong> T::iterator * iter;<br>   ...<br>}</pre>
<p>Without <tt>typename</tt>, there is a C++ parsing rule that says
that qualified dependent names should be parsed as non-types even if
it leads to a syntax error. Thus if there was a variable called
<tt>iter</tt> in scope, the example would be legal; it would just be
interpreted as multiplication. Then when the programmer instantiated
<tt>foo</tt> with <tt>ContainsAType</tt>, there would be an error
because you can't multiply something by a type.</p>
<p><tt>typename</tt> states that the name that follows should be
treated as a type. Otherwise, names are interpreted to refer to
non-types.</p>
<p>This rule even holds if it doesn't make sense <strong>even if it doesn't
make sense to refer to a non-type</strong>. For instance, suppose we were
to do something more typical and declare an iterator instead of a
pointer to an iterator:</p>
<pre>template &lt;class T&gt;<br>void foo() {<br>   <strong>typename</strong> T::iterator iter;<br>   ...<br>}</pre>
<p>Even in this case, <tt>typename</tt> is required, and omitting it
will cause  compile error. As another example, typedefs also
require use:</p>
<pre>template &lt;class T&gt;<br>void foo() {<br>   typedef <strong>typename</strong> T::iterator iterator_type;<br>   ...<br>}<br><br>from:<br>http://pages.cs.wisc.edu/~driscoll/typename.html<br></pre>
</div><img src ="http://www.cppblog.com/beautykingdom/aggbug/112970.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/beautykingdom/" target="_blank">chatler</a> 2010-04-19 11:58 <a href="http://www.cppblog.com/beautykingdom/archive/2010/04/19/112970.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>How to Generate C++ Class Template Definitions</title><link>http://www.cppblog.com/beautykingdom/archive/2010/04/19/112960.html</link><dc:creator>chatler</dc:creator><author>chatler</author><pubDate>Mon, 19 Apr 2010 03:05:00 GMT</pubDate><guid>http://www.cppblog.com/beautykingdom/archive/2010/04/19/112960.html</guid><wfw:comment>http://www.cppblog.com/beautykingdom/comments/112960.html</wfw:comment><comments>http://www.cppblog.com/beautykingdom/archive/2010/04/19/112960.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/beautykingdom/comments/commentRss/112960.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/beautykingdom/services/trackbacks/112960.html</trackback:ping><description><![CDATA[<h1 class="articleTitle">c++ class template header and implementation (skeleton) definitions are
often hard to read, let alone to write. Especially when defining
template classes that are derived from base template classes, I often
find myself struggling for the correct syntax.</h1>
In this article, I will present a template-based source code generator
to produce C++ class template header implementation (skeleton)
definitions in .hpp and .cpp files, based on a minimal yet functional
set of methods.
<p>
A template is a way to specify generic code, with a placeholder for the
type. Note that the type is the only "parameter" of a template, but a
very powerful one, since anything from a function to a class (or a
routine) can be specified in "general" terms without concerning yourself
about the specific type. Yet. These details are postponed until you
start to use the template. You can consider templates to be compile-time
polymorphic, yet typesafe (in contrast to C MACROs).
</p>
<p>
<strong>Function vs. Class</strong><br>
When talking about C++ templates, one should realize that there are, in
fact, two kinds of templates: function templates and class templates.
The former are quite easy to implement, because they usually only
contain the template(s) in their definition. As an example of a function
template, here is a function that produces the minimum of two
arguments, without specifying the actual type of the arguments:
</p>
<pre><code>template &lt;typename T&gt;<br>T max(const T &amp;X, const T &amp;Y)<br>{<br>  if (X &gt; Y) <br>    return X;<br>  else<br>    return Y;<br>}</code></pre>
T is the usual template character that is used to specify the typename,
which—at the time of definition—is unknown, and will be determined when
you actually use the template in your source code. Here is an example:
<pre><code>int x = max(6, 42); // compiler determines T = int<br>float y = max(3.1415927, 2.20371); // compiler determines T = float</code></pre>
Or explicitly, as follows:
<pre><code>int x = max&lt;int&gt; (6, 42); // explicit template syntax</code></pre>
The C++ compiler will be able to determine—at compile time—where the
calls to this function template are made, which argument types are used,
and hence which "expansions" of this function template have to be
generated (like a MACRO expansion) and then compiled and linked into an
executable. All this is happening behind the scenes, of course, although
template expansion can take a lot of compiler and linker resource (as
you may find out when you start to use them more often).
<p>
Class templates are similar to function templates in that the compiler
will determine at compile-time which expansions (or instantions) of the
class template are needed. The fact that they are classes and not merely
functions, makes the syntax a bit more difficult, however.
</p>
<p>
<strong>Pop Quiz</strong><br>
Even if you're an experienced C++ class template user, could you tell me
from the top of your head what the syntax would be of the
implementation skeleton for the copy constructor of a template class
TDerived, which is derived from a template class TBase? You have 10
seconds ...</p>
<p>
It turns out to be as follows:
</p>
<pre><code>template &lt;class T&gt; TDerived&lt;T&gt;::TDerived(const TDerived&lt;T&gt;&amp; copy): TBase&lt;T&gt;(copy)</code></pre>
But I don't blame you if you couldn't come up with that right away. If
you did know the answer, then you probably don't need to read the
remainder of this article, unless you're also interested in a
template-based template header/source generator. That's what I made for
myself, to help me remember.
<p>
<strong>Canonical Class</strong><br>
But before I want to continue with class templates, let's first talk
about a minimum useful class, sometimes also called a canonical class.
By this I mean a class definition which is minimal (only a few key
methods), but still complete and useful. This means that the class
should at least contain the default constructor (without an argument),
the destructor, a copy constructor, the assignment operator, the compare
operator and last—optionally—the stream operator (always useful when
debugging). When a class contains at least these methods, we can call it
a canonical class.
</p>
<p>
Since I'm planning to produce a template header and source generator,
it's important to realise what I should generate and what not. Making
sure that I produce a canonical class—especially when it comes to
templates, can make the difference between a nice but useless or an
actual useful tool.
As an example, here is the canonical class definition (header file) of a
class TBase:
</p>
<pre><code>class TBase<br>{<br>  public:<br>    // Constructors &amp; Destructors<br>    TBase(void);<br>    TBase(const TBase&amp; copy);<br>    virtual ~TBase(void);<br><br>    // Operator overloading<br>    TBase&amp; operator = (const TBase&amp; other);<br>    int operator == (const TBase&amp; other) const;<br><br>    // Output<br>    friend ostream&amp; operator &lt;&lt; (ostream&amp; os, const TBase&amp; other);<br>};</code></pre>
<br>
<div><strong>Canonical Class Template</strong><br>
We can modify the listing above to turn it into a canonical template
class definition. Just like function templates, this means we have to
use the &lt;T&gt; template syntax in a few places, and sometimes in more
than a few.
Luckily, it's not that hard, and the result can be seen in the following
listing:
<pre><code>template &lt;class T&gt; class TBase<br>{<br>  public:<br>    // Constructors &amp; Destructors<br>    TBase(void);<br>    TBase(const TBase&lt;T&gt;&amp; copy);<br>    virtual ~TBase(void);<br><br>    // Operator overloading<br>    TBase&lt;T&gt;&amp; operator = (const TBase&lt;T&gt;&amp; other);<br>    int operator == (const TBase&lt;T&gt;&amp; other) const;<br><br>    // Output<br>    friend ostream&amp; operator &lt;&lt; (ostream&amp; os, const TBase&lt;T&gt;&amp; other);<br>};<br><br></code>Just to let you know what the implementation looks like (the empty <br>skeletons, that is), take a look at the following listing:<br><code>// Constructors &amp; Destructors<br>template &lt;class T&gt; TBase&lt;T&gt;::TBase(void) {}<br>template &lt;class T&gt; TBase&lt;T&gt;::TBase(const TBase&lt;T&gt;&amp; copy) {}<br>template &lt;class T&gt; TBase&lt;T&gt;::~TBase(void) {}<br><br>// Operator overloading<br>template &lt;class T&gt; TBase&lt;T&gt;&amp; TBase&lt;T&gt;::operator = (const TBase&lt;T&gt;&amp; other) {}<br>template &lt;class T&gt; int TBase&lt;T&gt;::operator == (const TBase&lt;T&gt;&amp; other) const {}<br><br>// Output<br>template &lt;class T&gt; ostream&amp; operator &lt;&lt; (ostream&amp; os, const TBase&lt;T&gt;&amp; other) {}</code><br>This is usually the place where I could do with a little help or support<br> to get the class template syntax right.<br></pre>
<p>
<strong>Derived Templates</strong><br>
If you've been able to keep up with me so far, then let's get to the
final round: templates derived from other templates. Sometimes you just
have to derive your own custom class template TDerived from a base
template class TBase (sound familiar?).
And just for your amusement (and mine), I've included the header listing
for the derived canonical class template definition below:
</p>
<code>template &lt;class T&gt; class TDerived: public TBase&lt;T&gt;
{
public:
// Constructors &amp; Destructors
TDerived(void);
TDerived(const TDerived&lt;T&gt;&amp; copy);
virtual ~TDerived(void);
// Operator overloading
TDerived&lt;T&gt;&amp; operator = (const TDerived&lt;T&gt;&amp; other);
int operator == (const TDerived&lt;T&gt;&amp; other) const;
// Output
friend ostream&amp; operator &lt;&lt; (ostream&amp; os, const TDerived&lt;T&gt;&amp; other);
};</code>
Certainly this TDerived class template definition needs a list of empty
implementation skeletons, which are defined as follows (empty because
they're skeletons, but they still need to be implemented by the
programmer, of course).
<code>// Constructors &amp; Destructors
template &lt;class T&gt; TDerived&lt;T&gt;::TDerived(void): TBase&lt;T&gt;() {}
template &lt;class T&gt; TDerived&lt;T&gt;::TDerived(const TDerived&lt;T&gt;&amp; copy): TBase&lt;T&gt;(copy) {}
template &lt;class T&gt; TDerived&lt;T&gt;::~TDerived(void) {}
// Operator overloading
template &lt;class T&gt; TDerived&lt;T&gt;&amp; TDerived&lt;T&gt;::operator = (const TDerived&lt;T&gt;&amp; other) {}
template &lt;class T&gt; int TDerived&lt;T&gt;::operator == (const TDerived&lt;T&gt;&amp; other) const {}
// Output
template &lt;class T&gt; ostream&amp; operator &lt;&lt; (ostream&amp; os, const TDerived&lt;T&gt;&amp; other) {}</code>
OK, who could already produce the above listing without a second
thought? If you could, then you probably didn't need to read this
article, because the fun stuff is over. What remains is the description
of a little tool that I made for myself to actually produce and generate
the output listings that we've seen so far.
<div><strong>Template Template</strong><br>
If you look closely at the listings presented so far, you can see a
pattern (believe me, there is logic behind this class template syntax).
In fact, I have been able to produce two template files that can be used
to generate the template listings we've seen in this article. The
template file for the class definition (typically inside a header file)
is defined as follows:
<pre><code>//    File: &lt;#class&gt;.hpp<br>//  Author: drs. Robert E. Swart&gt;<br>//    Date: &lt;#date&gt;<br>//    Time: &lt;#time&gt;<br>// Version: 0.01<br>// Generated by: HeadGen (c) 1995-2001 by Bob Swart<br>(aka Dr.Bob - www.drbob42.com)<br>// Changes:<br>//<br><br>#ifndef &lt;#class&gt;_hpp<br>#define &lt;#class&gt;_hpp<br><br>#include &lt;iostream.h&gt;<br>&lt;#includebase&gt;<br><br>template &lt;class &lt;#templatechar&gt;&gt; class &lt;#class&gt; &lt;#publicbase&gt;<br>{<br>  public:<br>    // Constructors &amp; Destructors<br>    &lt;#class&gt;(void);<br>    &lt;#class&gt;(const &lt;#class&gt;&lt;#template&gt;&amp; copy);<br>    virtual ~&lt;#class&gt;(void);&gt;<br><br>    // Accessing functions<br><br>    // Modifier functions<br><br>    // Operator overloading<br>    &lt;#class&gt;&lt;#template&gt;&amp; operator = (const &lt;#class&gt;&lt;#template&gt;&amp; other);<br>    int operator == (const &lt;#class&gt;&lt;#template&gt;&amp; other) const;<br><br>    // Streaming output<br>    friend ostream&amp; operator &lt;&lt; (ostream&amp; os, const &lt;#class&gt;&lt;#template&gt;&amp; other);<br><br>  protected:<br>  private:<br>};<br><br>#endif<br><br></code>Note the special #-tags. WebBroker developers may recognize these as <br>tags used in the PageProducer components. That's actually the case, <br>since I'm using a TPageProducer component (from the Internet tab) to <br>expand the above template into a true class template definition <br>header—with or without a template base class. <br>The same technique can be applied to the following template listing, <br>that can be used to produce the empty template skeleton implementations:<br><code>//    File: &lt;#class&gt;.cpp<br>//  Author: drs. Robert E. Swart<br>//    Date: &lt;#date&gt;<br>//    Time: &lt;#time&gt;<br>// Version: 0.01<br>// Generated by: HeadGen (c) 1995-2001 by Bob Swart<br>(aka Dr.Bob - www.drbob42.com)<br>// Changes:<br>//<br><br>#include "&lt;#include&gt;.hpp"<br><br>// Constructors &amp; Destructors<br>template &lt;class &lt;#templatechar&gt;&gt; &lt;#class&gt;&lt;#template&gt;::&lt;#class&gt;(void) &lt;#base&gt;<br>&lt;#body&gt;<br><br>template &lt;class &lt;#templatechar&gt;&gt; &lt;#class&gt;&lt;#template&gt;::&lt;#class&gt;(const<br>&lt;#class&gt;&lt;#template&gt;&amp; copy) &lt;#basecopy&gt;<br>&lt;#body&gt;<br><br>template &lt;class &lt;#templatechar&gt;&gt; &lt;#class&gt;&lt;#template&gt;::~&lt;#class&gt;(void)<br>&lt;#body&gt;<br><br>// Operator overloading<br>template &lt;class &lt;#templatechar&gt;&gt; &lt;#class&gt;&lt;#template&gt;&amp; &lt;#class&gt;&lt;#template&gt;::operator = (const &lt;<br>#class&gt;&lt;#template&gt;&amp; other)<br>&lt;#body&gt;<br><br>template &lt;class &lt;#templatechar&gt;&gt; int &lt;#class&gt;&lt;#template&gt;::operator == (const<br>&lt;#class&gt;&lt;#template&gt;&amp; other) const<br>&lt;#body&gt;<br><br>// Streaming output<br>template &lt;class &lt;#templatechar&gt;&gt; ostream&amp; operator &lt;&lt; (ostream&amp;<br>os, const &lt;#class&gt;&lt;#template&gt;&amp; other)<br>&lt;#body&gt;</code><br>Again, the above listing can be used to produce a stand-alone class <br>template as well as a derived class template. We only need to specify <br>three options: the class name, the (optional) base class name, and the <br>template character.<br></pre>
<p>
<strong>HeadGen</strong><br>
<!-- FIGURE1 TABLE STARTS -->
</p>
&nbsp;The utility HeadGen only requires the class name (the template character
is T by default), as can be seen in <a  href="javascript:showSupportItem('figure1');">Figure 1.</a>
<p>
For the base class, specify Base in the Class Name box leave the
Ancestor type box empty, and click on Generate. For the derived class,
specify Derived in the Class Name box, Base in the Ancestor Type box and
then click on Generate again. In both cases, the T will be added as
prefix automatically (files Base.hpp and Base.cpp will contain the
definition for TBase).
</p>
<p>
A very simple Borland C++Builder example program (to test the syntax of
the generated files) can be seen below:
</p>
<code>//---------------------------------------------------------
#pragma hdrstop
#include "Base.cpp" // TBase
#include "Derived.cpp"; // TDerived
//--------------------------------------------------------
typedef TDerived&lt;int&gt; TintClass;
#pragma argsused
int main(int argc, char* argv[])
{
TintClass* Bob = new TintClass();
TintClass Swart = TintClass(*Bob);
if (*Bob == Swart) { *Bob = Swart; }
return 0;
}
//--------------------------------------------------------
</code>
Note that I needed to include the .cpp files of the templates, and not
only (or just) the .hpp files. That's because the .cpp files are
"expanded" (like MACROs) to the compiler, which must find them in order
to be able to use them.
<strong>External Templates</strong><br>
The two template files are external files HeadGen.h (for the .hpp
header) and HeadGen.c (for the .cpp source file). As an additional
benefit, you can edit these templates and make sure your own copyright
statements appear in them. Make sure to keep all #-tags intact, though,
otherwise the template PageProducer won't be able to work correctly
anymore.
<pre><br></pre>
</div>
<pre><br><code><br>from:<br><a  href="http://www.devx.com/cplus/Article/20689/0/page/1">http://www.devx.com/cplus/Article/20689/0/page/1</a><br></code></pre>
</div>
<br><img src ="http://www.cppblog.com/beautykingdom/aggbug/112960.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/beautykingdom/" target="_blank">chatler</a> 2010-04-19 11:05 <a href="http://www.cppblog.com/beautykingdom/archive/2010/04/19/112960.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>template friends</title><link>http://www.cppblog.com/beautykingdom/archive/2010/04/17/112879.html</link><dc:creator>chatler</dc:creator><author>chatler</author><pubDate>Sat, 17 Apr 2010 15:33:00 GMT</pubDate><guid>http://www.cppblog.com/beautykingdom/archive/2010/04/17/112879.html</guid><wfw:comment>http://www.cppblog.com/beautykingdom/comments/112879.html</wfw:comment><comments>http://www.cppblog.com/beautykingdom/archive/2010/04/17/112879.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/beautykingdom/comments/commentRss/112879.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/beautykingdom/services/trackbacks/112879.html</trackback:ping><description><![CDATA[Class templates can have <a href="http://msdn.microsoft.com/en-us/library/9f82kehd.aspx">friends</a>.
A class or class template, function, or function template can be a
friend to a template class. Friends can also be specializations of a
class template or function template, but not partial specializations.
<br><br>Example<br>
In the following example, a friend
function is defined as a function template within the class template.
This code produces a version of the friend function for every
instantiation of the template. This construct is useful if your friend
function depends on the same template parameters as the class does.<br><br>
<pre>// template_friend1.cpp<br>// compile with: /EHsc<br><br>#include &lt;iostream&gt;<br>using namespace std;<br><br>template &lt;class T&gt; class Array {<br>   T* array;<br>   int size;<br><br>public:<br>   Array(int sz): size(sz) {<br>      array = new T[size];<br>      memset(array, 0, size * sizeof(T));<br>   }<br><br>   Array(const Array&amp; a) {<br>      size = a.size;<br>      array = new T[size];<br>      memcpy_s(array, a.array, sizeof(T));<br>   }<br><br>   T&amp; operator[](int i) {<br>      return *(array + i);<br>   }<br><br>   int Length() { return size; }<br><br>   void print() {<br>      for (int i = 0; i &lt; size; i++)      <br>         cout &lt;&lt; *(array + i) &lt;&lt; " ";<br><br>      cout &lt;&lt; endl;<br>   }<br><br>   template&lt;class T&gt;<br>   friend Array&lt;T&gt;* combine(Array&lt;T&gt;&amp; a1, Array&lt;T&gt;&amp; a2);<br>};<br><br>template&lt;class T&gt;<br>Array&lt;T&gt;* combine(Array&lt;T&gt;&amp; a1, Array&lt;T&gt;&amp; a2) {<br>   Array&lt;T&gt;* a = new Array&lt;T&gt;(a1.size + a2.size);<br>   for (int i = 0; i &lt; a1.size; i++)<br>      (*a)[i] = *(a1.array + i);<br><br>   for (int i = 0; i &lt; a2.size; i++)<br>      (*a)[i + a1.size] = *(a2.array + i);<br><br>   return a;<br>}<br><br>int main() {<br>   Array&lt;char&gt; alpha1(26);<br>   for (int i = 0 ; i &lt; alpha1.Length() ; i++)<br>      alpha1[i] = 'A' + i;<br><br>   alpha1.print();<br><br>   Array&lt;char&gt; alpha2(26);<br>   for (int i = 0 ; i &lt; alpha2.Length() ; i++)<br>      alpha2[i] = 'a' + i;<br><br>   alpha2.print();<br>   Array&lt;char&gt;*alpha3 = combine(alpha1, alpha2);<br>   alpha3-&gt;print();<br>   delete alpha3;<br>}<br></pre>
<pre>A B C D E F G H I J K L M N O P Q R S T U V W X Y Z <br>a b c d e f g h i j k l m n o p q r s t u v w x y z <br>A B C D E F G H I J K L M N O P Q R S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z <br></pre>
<br>
<p xmlns="http://www.w3.org/1999/xhtml">The next example involves a
friend that has a template specialization. A function template
specialization is automatically a friend if the original function
template is a friend.</p>
<p xmlns="http://www.w3.org/1999/xhtml">It is
also possible to declare only the specialized version of the template as
the friend, as the comment before the friend declaration in the
following code indicates. If you do this, you must put the definition of
the friend template specialization outside of the template class. </p>
<br>
<pre>// template_friend2.cpp<br>// compile with: /EHsc<br>#include &lt;iostream&gt;<br>using namespace std;<br><br>template &lt;class T&gt;<br>class Array;<br><br>template &lt;class T&gt;<br>void f(Array&lt;T&gt;&amp; a);<br><br>template &lt;class T&gt; class Array<br>{<br>    T* array;<br>    int size;<br><br>public:<br>    Array(int sz): size(sz)<br>    {<br>        array = new T[size];<br>        memset(array, 0, size * sizeof(T));<br>    }<br>    Array(const Array&amp; a)<br>    {<br>        size = a.size;<br>        array = new T[size];<br>        memcpy_s(array, a.array, sizeof(T));<br>    }<br>    T&amp; operator[](int i)<br>    {<br>        return *(array + i);<br>    }<br>    int Length()<br>    { <br>        return size;<br>    }<br>    void print()<br>    {<br>        for (int i = 0; i &lt; size; i++)<br>        {<br>            cout &lt;&lt; *(array + i) &lt;&lt; " ";<br>        }<br>        cout &lt;&lt; endl;<br>    }<br>    // If you replace the friend declaration with the int-specific<br>    // version, only the int specialization will be a friend.<br>    // The code in the generic f will fail<br>    // with C2248: 'Array&lt;T&gt;::size' :<br>    // cannot access private member declared in class 'Array&lt;T&gt;'.<br>    //friend void f&lt;int&gt;(Array&lt;int&gt;&amp; a);<br><br>    friend void f&lt;&gt;(Array&lt;T&gt;&amp; a);<br>};<br><br>// f function template, friend of Array&lt;T&gt;<br>template &lt;class T&gt;<br>void f(Array&lt;T&gt;&amp; a)<br>{<br>    cout &lt;&lt; a.size &lt;&lt; " generic" &lt;&lt; endl;<br>}<br><br>// Specialization of f for int arrays<br>// will be a friend because the template f is a friend.<br>template&lt;&gt; void f(Array&lt;int&gt;&amp; a)<br>{<br>    cout &lt;&lt; a.size &lt;&lt; " int" &lt;&lt; endl;<br>}<br><br>int main()<br>{<br>    Array&lt;char&gt; ac(10);<br>    f(ac);<br><br>    Array&lt;int&gt; a(10);<br>    f(a);<br>}<br></pre>
<pre>10 generic<br>10 int<br></pre>
The next example shows a friend class template declared within a class
template. The class template is then used as the template argument for
the friend class. Friend class templates must be defined outside of the
class template in which they are declared. Any specializations or
partial specializations of the friend template are also friends of the
original class template.
<br><br>
<pre>// template_friend3.cpp<br>// compile with: /EHsc<br>#include &lt;iostream&gt;<br>using namespace std;<br><br>template &lt;class T&gt;<br>class X<br>{<br>private:<br>   T* data;<br>   void InitData(int seed) { data = new T(seed); }<br>public:<br>   void print() { cout &lt;&lt; *data &lt;&lt; endl; }<br>   template &lt;class U&gt; friend class Factory;<br>};<br><br>template &lt;class U&gt;<br>class Factory<br>{<br>public:<br>   U* GetNewObject(int seed)<br>   {<br>      U* pu = new U;<br>      pu-&gt;InitData(seed);<br>      return pu;<br>   }<br>};<br><br>int main()<br>{<br>   Factory&lt; X&lt;int&gt; &gt; XintFactory;<br>   X&lt;int&gt;* x1 = XintFactory.GetNewObject(65);<br>   X&lt;int&gt;* x2 = XintFactory.GetNewObject(97);<br><br>   Factory&lt; X&lt;char&gt; &gt; XcharFactory;<br>   X&lt;char&gt;* x3 = XcharFactory.GetNewObject(65);<br>   X&lt;char&gt;* x4 = XcharFactory.GetNewObject(97);<br>   x1-&gt;print();<br>   x2-&gt;print();<br>   x3-&gt;print();<br>   x4-&gt;print();<br>}<br></pre>
<pre>65<br>97<br>A<br>a<br></pre>
from：<br><a  href="http://msdn.microsoft.com/en-us/library/f1b2td24.aspx">http://msdn.microsoft.com/en-us/library/f1b2td24.aspx
</a><br><br><br> <img src ="http://www.cppblog.com/beautykingdom/aggbug/112879.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/beautykingdom/" target="_blank">chatler</a> 2010-04-17 23:33 <a href="http://www.cppblog.com/beautykingdom/archive/2010/04/17/112879.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>