summaryrefslogtreecommitdiff
path: root/docs/tutorials/templates.html
blob: 76822f7071d37239cacd8f811f8db7a084282e53 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<html>
  <!-- $Id$ -->
  <head>
    <title>About C++ Templates</title>
  </head>

  <BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F">
<center>
    <h1>About C++ Templates</h1>
</center>


    <hr>

When you get to server.cpp in Tutorial 2 you'll see these lines at the bottom:
<P>
<UL>
<PRE>
<font color=blue>#if defined</font> (<font color=purple>ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION</font>)
template class ACE_Acceptor &lt;Logging_Handler, ACE_SOCK_ACCEPTOR>;
template class ACE_Svc_Handler&lt;ACE_SOCK_STREAM, ACE_NULL_SYNCH>;
<font color=blue>#elif defined</font> (<font color=purple>ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA</font>)
<font color=blue>#pragma</font> <font color=purple>instantiate</font> ACE_Acceptor &lt;Logging_Handler, ACE_SOCK_ACCEPTOR>
<font color=blue>#pragma</font> <font color=purple>instantiate</font> ACE_Svc_Handler&lt;ACE_SOCK_STREAM, ACE_NULL_SYNCH>
<font color=blue>#endif</font> <font color=red>/* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */</font>
Thanks to Krishna Padmasola for providing these.
</PRE>
</UL>
<P>
What's that all about?
<P>
Well, if you've been doing ACE for more than about 30 seconds you will
have run into the joys and sorrows of C++ templates.  They're really
great things that prevent the need for complex #define'd macros,
ensure type safety and do other really nifty things.  One of the
problems, however, is that not all compilers can figure out what
templates you need.
<P>
Take the simple templated class:
<UL>
<PRE>

template &lt;class DATATYPE>
class MyTemplate
{
public:
    MyTemplate(void)
        {
        }

    DATATYPE data(void)
        {
            return data_;
        }

    void data( DATATYPE _data )
        {
            data_ = _data;
        }

protected:

    DATATYPE data_;
};
</PRE>
</UL>
<P>
Now suppose you write the following code fragment:
<P>
<UL>
<PRE>
int main(int,char**)
{
    MyTemplate&lt;int> itemp;
    MyTemplate&lt;char> ctemp;

    ...
}
</pre>
</ul>
<P>
Some compilers will take care of you and automatically generate the
equivalent classes:
<UL>
<pre>
class MyTemplate
{
public:
    MyTemplate(void)
        {
        }

    int data(void)
        {
            return data_;
        }

    void data( int _data )
        {
            data_ = _data;
        }

protected:

    int data_;
};

class MyTemplate
{
public:
    MyTemplate(void)
        {
        }

    char data(void)
        {
            return data_;
        }

    void data( char _data )
        {
            data_ = _data;
        }

protected:

    char data_;
};
</pre>
</ul>
<P>
On the other hand, some compilers will complain loudly about undefined 
symbols and all sorts of other things.  When Clinton Carr compiled
server.cpp of Tutorial 2 on his RedHat 5.1 (gcc) system, for instance, 
he was rewarded with these lovely errors:
<P>
<UL>
<PRE>
server.cpp:60: undefined reference to `ACE_Acceptor&lt;Client_Handler, ACE_SOCK_Acceptor>::ACE_Acceptor(ACE_Reactor *)'
server.cpp:72: undefined reference to `ACE_Acceptor&lt;Client_Handler, ACE_SOCK_Acceptor>::open(ACE_INET_Addr const &, ACE_Reactor *,int)'
server.cpp:73: undefined reference to `ACE_Acceptor&lt;Client_Handler, ACE_SOCK_Acceptor>::~ACE_Acceptor(void)'
server.cpp:112: undefined reference to `ACE_Acceptor&lt;Client_Handler, ACE_SOCK_Acceptor>::~ACE_Acceptor(void)'

</PRE>
</UL>
<P>
Figuring out the correct manual instantiations is usually an
iterative and tedious process.  On Linux, I generally use a version of gcc that 
will do automatic instantiaion.  "Normal" gcc with the Cygnus repo
patches does that as does egcs.  Lately (1/99) I've been using egcs
1.1.1 with pretty good results.  On our Digital Unix 4.0b system the
native compiler (CXX) has switches that will request it to also
automatically instantiate templates as needed.
<P>
The tradeoffs?
<P>
If you choose to do manual instantiation then your code will work just 
about anywhere ACE will.  For complex applications, it can take a
number of hours to get things right.
<P>
If you choose to let the compiler do instantiations for you then it
will perform the iterative process.  That means that every compile
will be longer than without manual instantiations.
<P>
Compromise?
<P>
Yes, you can do that.  You can manually instantiate some
templates and let the compiler get the rest.  Some compilers will
generate output that you can then use to figure out the correct
templates.  Gcc/egcs create .rpo files for each object.  These files
contain mangled names that the compiler uses to figure out what to
instantiate.  With c++filt and some patience, you can parse that stuff 
to figure out what the compiler is instantiating for you.  Note that
c++filt expects you to have a GNU-flavored C++ compiler available.
<P>
My best advice is to get a compiler that will handle the
instantiations for you.  When you have some free time on your hands,
take a look at its intermediate files (if any) and start working on
manual instantiation.
<P>
For some more hints, take a look at <A HREF="../../ACE-INSTALL.html#g++">ACE-INSTALL</A>
<P>
    <hr>

Thanks to Amos Shapira for catching a number of errors here.

  </body>
</html>