]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | <html> |
2 | <head> | |
3 | <meta http-equiv="Content-Type" content="text/html; charset=US-ASCII"> | |
4 | <title>Background and Tutorial</title> | |
5 | <link rel="stylesheet" href="../../../../../doc/src/boostbook.css" type="text/css"> | |
6 | <meta name="generator" content="DocBook XSL Stylesheets V1.77.1"> | |
7 | <link rel="home" href="../index.html" title="Chapter 1. Boost.TypeTraits"> | |
8 | <link rel="up" href="../index.html" title="Chapter 1. Boost.TypeTraits"> | |
9 | <link rel="prev" href="intro.html" title="Introduction"> | |
10 | <link rel="next" href="category.html" title="Type Traits by Category"> | |
11 | </head> | |
12 | <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"> | |
13 | <table cellpadding="2" width="100%"><tr> | |
14 | <td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../boost.png"></td> | |
15 | <td align="center"><a href="../../../../../index.html">Home</a></td> | |
16 | <td align="center"><a href="../../../../../libs/libraries.htm">Libraries</a></td> | |
17 | <td align="center"><a href="http://www.boost.org/users/people.html">People</a></td> | |
18 | <td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td> | |
19 | <td align="center"><a href="../../../../../more/index.htm">More</a></td> | |
20 | </tr></table> | |
21 | <hr> | |
22 | <div class="spirit-nav"> | |
23 | <a accesskey="p" href="intro.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="category.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a> | |
24 | </div> | |
25 | <div class="section"> | |
26 | <div class="titlepage"><div><div><h2 class="title" style="clear: both"> | |
27 | <a name="boost_typetraits.background"></a><a class="link" href="background.html" title="Background and Tutorial">Background and Tutorial</a> | |
28 | </h2></div></div></div> | |
29 | <p> | |
30 | The following is an updated version of the article "C++ Type traits" | |
31 | by John Maddock and Steve Cleary that appeared in the October 2000 issue of | |
32 | <a href="http://www.ddj.com" target="_top">Dr Dobb's Journal</a>. | |
33 | </p> | |
34 | <p> | |
35 | Generic programming (writing code which works with any data type meeting a | |
36 | set of requirements) has become the method of choice for providing reusable | |
37 | code. However, there are times in generic programming when "generic" | |
38 | just isn't good enough - sometimes the differences between types are too large | |
39 | for an efficient generic implementation. This is when the traits technique | |
40 | becomes important - by encapsulating those properties that need to be considered | |
41 | on a type by type basis inside a traits class, we can minimize the amount of | |
42 | code that has to differ from one type to another, and maximize the amount of | |
43 | generic code. | |
44 | </p> | |
45 | <p> | |
46 | Consider an example: when working with character strings, one common operation | |
47 | is to determine the length of a null terminated string. Clearly it's possible | |
48 | to write generic code that can do this, but it turns out that there are much | |
49 | more efficient methods available: for example, the C library functions <code class="computeroutput"><span class="identifier">strlen</span></code> and <code class="computeroutput"><span class="identifier">wcslen</span></code> | |
50 | are usually written in assembler, and with suitable hardware support can be | |
51 | considerably faster than a generic version written in C++. The authors of the | |
52 | C++ standard library realized this, and abstracted the properties of <code class="computeroutput"><span class="keyword">char</span></code> and <code class="computeroutput"><span class="keyword">wchar_t</span></code> | |
53 | into the class <code class="computeroutput"><span class="identifier">char_traits</span></code>. | |
54 | Generic code that works with character strings can simply use <code class="computeroutput"><span class="identifier">char_traits</span><span class="special"><>::</span><span class="identifier">length</span></code> to determine the length of a null | |
55 | terminated string, safe in the knowledge that specializations of <code class="computeroutput"><span class="identifier">char_traits</span></code> will use the most appropriate | |
56 | method available to them. | |
57 | </p> | |
58 | <h5> | |
59 | <a name="boost_typetraits.background.h0"></a> | |
60 | <span class="phrase"><a name="boost_typetraits.background.type_traits"></a></span><a class="link" href="background.html#boost_typetraits.background.type_traits">Type | |
61 | Traits</a> | |
62 | </h5> | |
63 | <p> | |
64 | Class <code class="computeroutput"><span class="identifier">char_traits</span></code> is a classic | |
65 | example of a collection of type specific properties wrapped up in a single | |
66 | class - what Nathan Myers termed a <span class="emphasis"><em>baggage class</em></span><a class="link" href="background.html#background.references">[1]</a>. In the Boost type-traits library, | |
67 | we<a class="link" href="background.html#background.references">[2]</a> have written a set of very | |
68 | specific traits classes, each of which encapsulate a single trait from the | |
69 | C++ type system; for example, is a type a pointer or a reference type? Or does | |
70 | a type have a trivial constructor, or a const-qualifier? The type-traits classes | |
71 | share a unified design: each class inherits from the type <a class="link" href="reference/integral_constant.html" title="integral_constant">true_type</a> | |
72 | if the type has the specified property and inherits from <a class="link" href="reference/integral_constant.html" title="integral_constant">false_type</a> | |
73 | otherwise. As we will show, these classes can be used in generic programming | |
74 | to determine the properties of a given type and introduce optimizations that | |
75 | are appropriate for that case. | |
76 | </p> | |
77 | <p> | |
78 | The type-traits library also contains a set of classes that perform a specific | |
79 | transformation on a type; for example, they can remove a top-level const or | |
80 | volatile qualifier from a type. Each class that performs a transformation defines | |
81 | a single typedef-member <code class="computeroutput"><span class="identifier">type</span></code> | |
82 | that is the result of the transformation. All of the type-traits classes are | |
83 | defined inside namespace <code class="computeroutput"><span class="identifier">boost</span></code>; | |
84 | for brevity, namespace-qualification is omitted in most of the code samples | |
85 | given. | |
86 | </p> | |
87 | <h5> | |
88 | <a name="boost_typetraits.background.h1"></a> | |
89 | <span class="phrase"><a name="boost_typetraits.background.implementation"></a></span><a class="link" href="background.html#boost_typetraits.background.implementation">Implementation</a> | |
90 | </h5> | |
91 | <p> | |
92 | There are far too many separate classes contained in the type-traits library | |
93 | to give a full implementation here - see the source code in the Boost library | |
94 | for the full details - however, most of the implementation is fairly repetitive | |
95 | anyway, so here we will just give you a flavor for how some of the classes | |
96 | are implemented. Beginning with possibly the simplest class in the library, | |
97 | <code class="computeroutput"><span class="identifier">is_void</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span></code> inherits | |
98 | from <code class="computeroutput"><a class="link" href="reference/integral_constant.html" title="integral_constant">true_type</a></code> | |
99 | only if <code class="computeroutput"><span class="identifier">T</span></code> is <code class="computeroutput"><span class="keyword">void</span></code>. | |
100 | </p> | |
101 | <pre class="programlisting"><span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">></span> | |
102 | <span class="keyword">struct</span> <a class="link" href="reference/is_void.html" title="is_void">is_void</a> <span class="special">:</span> <span class="keyword">public</span> <a class="link" href="reference/integral_constant.html" title="integral_constant">false_type</a><span class="special">{};</span> | |
103 | ||
104 | <span class="keyword">template</span> <span class="special"><></span> | |
105 | <span class="keyword">struct</span> <a class="link" href="reference/is_void.html" title="is_void">is_void</a><span class="special"><</span><span class="keyword">void</span><span class="special">></span> <span class="special">:</span> <span class="keyword">public</span> <a class="link" href="reference/integral_constant.html" title="integral_constant">true_type</a><span class="special">{};</span> | |
106 | </pre> | |
107 | <p> | |
108 | Here we define a primary version of the template class <code class="computeroutput"><a class="link" href="reference/is_void.html" title="is_void">is_void</a></code>, | |
109 | and provide a full-specialization when <code class="computeroutput"><span class="identifier">T</span></code> | |
110 | is <code class="computeroutput"><span class="keyword">void</span></code>. While full specialization | |
111 | of a template class is an important technique, sometimes we need a solution | |
112 | that is halfway between a fully generic solution, and a full specialization. | |
113 | This is exactly the situation for which the standards committee defined partial | |
114 | template-class specialization. As an example, consider the class <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">is_pointer</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span></code>: | |
115 | here we needed a primary version that handles all the cases where T is not | |
116 | a pointer, and a partial specialization to handle all the cases where T is | |
117 | a pointer: | |
118 | </p> | |
119 | <pre class="programlisting"><span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">></span> | |
120 | <span class="keyword">struct</span> <a class="link" href="reference/is_pointer.html" title="is_pointer">is_pointer</a> <span class="special">:</span> <span class="keyword">public</span> <a class="link" href="reference/integral_constant.html" title="integral_constant">false_type</a><span class="special">{};</span> | |
121 | ||
122 | <span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">></span> | |
123 | <span class="keyword">struct</span> <a class="link" href="reference/is_pointer.html" title="is_pointer">is_pointer</a><span class="special"><</span><span class="identifier">T</span><span class="special">*></span> <span class="special">:</span> <span class="keyword">public</span> <a class="link" href="reference/integral_constant.html" title="integral_constant">true_type</a><span class="special">{};</span> | |
124 | </pre> | |
125 | <p> | |
126 | The syntax for partial specialization is somewhat arcane and could easily occupy | |
127 | an article in its own right; like full specialization, in order to write a | |
128 | partial specialization for a class, you must first declare the primary template. | |
129 | The partial specialization contains an extra <...> after the class name | |
130 | that contains the partial specialization parameters; these define the types | |
131 | that will bind to that partial specialization rather than the default template. | |
132 | The rules for what can appear in a partial specialization are somewhat convoluted, | |
133 | but as a rule of thumb if you can legally write two function overloads of the | |
134 | form: | |
135 | </p> | |
136 | <pre class="programlisting"><span class="keyword">void</span> <span class="identifier">foo</span><span class="special">(</span><span class="identifier">T</span><span class="special">);</span> | |
137 | <span class="keyword">void</span> <span class="identifier">foo</span><span class="special">(</span><span class="identifier">U</span><span class="special">);</span> | |
138 | </pre> | |
139 | <p> | |
140 | Then you can also write a partial specialization of the form: | |
141 | </p> | |
142 | <pre class="programlisting"><span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">></span> | |
143 | <span class="keyword">class</span> <span class="identifier">c</span><span class="special">{</span> <span class="comment">/*details*/</span> <span class="special">};</span> | |
144 | ||
145 | <span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">></span> | |
146 | <span class="keyword">class</span> <span class="identifier">c</span><span class="special"><</span><span class="identifier">U</span><span class="special">>{</span> <span class="comment">/*details*/</span> <span class="special">};</span> | |
147 | </pre> | |
148 | <p> | |
149 | This rule is by no means foolproof, but it is reasonably simple to remember | |
150 | and close enough to the actual rule to be useful for everyday use. | |
151 | </p> | |
152 | <p> | |
153 | As a more complex example of partial specialization consider the class <code class="computeroutput"><span class="identifier">remove_extent</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span></code>. This | |
154 | class defines a single typedef-member <code class="computeroutput"><span class="identifier">type</span></code> | |
155 | that is the same type as T but with any top-level array bounds removed; this | |
156 | is an example of a traits class that performs a transformation on a type: | |
157 | </p> | |
158 | <pre class="programlisting"><span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">></span> | |
159 | <span class="keyword">struct</span> <a class="link" href="reference/remove_extent.html" title="remove_extent">remove_extent</a> | |
160 | <span class="special">{</span> <span class="keyword">typedef</span> <span class="identifier">T</span> <span class="identifier">type</span><span class="special">;</span> <span class="special">};</span> | |
161 | ||
162 | <span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">N</span><span class="special">></span> | |
163 | <span class="keyword">struct</span> <a class="link" href="reference/remove_extent.html" title="remove_extent">remove_extent</a><span class="special"><</span><span class="identifier">T</span><span class="special">[</span><span class="identifier">N</span><span class="special">]></span> | |
164 | <span class="special">{</span> <span class="keyword">typedef</span> <span class="identifier">T</span> <span class="identifier">type</span><span class="special">;</span> <span class="special">};</span> | |
165 | </pre> | |
166 | <p> | |
167 | The aim of <code class="computeroutput"><a class="link" href="reference/remove_extent.html" title="remove_extent">remove_extent</a></code> | |
168 | is this: imagine a generic algorithm that is passed an array type as a template | |
169 | parameter, <code class="computeroutput"><a class="link" href="reference/remove_extent.html" title="remove_extent">remove_extent</a></code> | |
170 | provides a means of determining the underlying type of the array. For example | |
171 | <code class="computeroutput"><span class="identifier">remove_extent</span><span class="special"><</span><span class="keyword">int</span><span class="special">[</span><span class="number">4</span><span class="special">][</span><span class="number">5</span><span class="special">]>::</span><span class="identifier">type</span></code> would evaluate to the type <code class="computeroutput"><span class="keyword">int</span><span class="special">[</span><span class="number">5</span><span class="special">]</span></code>. This example also shows that the number of | |
172 | template parameters in a partial specialization does not have to match the | |
173 | number in the default template. However, the number of parameters that appear | |
174 | after the class name do have to match the number and type of the parameters | |
175 | in the default template. | |
176 | </p> | |
177 | <h5> | |
178 | <a name="boost_typetraits.background.h2"></a> | |
179 | <span class="phrase"><a name="boost_typetraits.background.optimized_copy"></a></span><a class="link" href="background.html#boost_typetraits.background.optimized_copy">Optimized | |
180 | copy</a> | |
181 | </h5> | |
182 | <p> | |
183 | As an example of how the type traits classes can be used, consider the standard | |
184 | library algorithm copy: | |
185 | </p> | |
186 | <pre class="programlisting"><span class="keyword">template</span><span class="special"><</span><span class="keyword">typename</span> <span class="identifier">Iter1</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Iter2</span><span class="special">></span> | |
187 | <span class="identifier">Iter2</span> <span class="identifier">copy</span><span class="special">(</span><span class="identifier">Iter1</span> <span class="identifier">first</span><span class="special">,</span> <span class="identifier">Iter1</span> <span class="identifier">last</span><span class="special">,</span> <span class="identifier">Iter2</span> <span class="identifier">out</span><span class="special">);</span> | |
188 | </pre> | |
189 | <p> | |
190 | Obviously, there's no problem writing a generic version of copy that works | |
191 | for all iterator types <code class="computeroutput"><span class="identifier">Iter1</span></code> | |
192 | and <code class="computeroutput"><span class="identifier">Iter2</span></code>; however, there are | |
193 | some circumstances when the copy operation can best be performed by a call | |
194 | to <code class="computeroutput"><span class="identifier">memcpy</span></code>. In order to implement | |
195 | copy in terms of <code class="computeroutput"><span class="identifier">memcpy</span></code> all | |
196 | of the following conditions need to be met: | |
197 | </p> | |
198 | <div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "> | |
199 | <li class="listitem"> | |
200 | Both of the iterator types <code class="computeroutput"><span class="identifier">Iter1</span></code> | |
201 | and <code class="computeroutput"><span class="identifier">Iter2</span></code> must be pointers. | |
202 | </li> | |
203 | <li class="listitem"> | |
204 | Both <code class="computeroutput"><span class="identifier">Iter1</span></code> and <code class="computeroutput"><span class="identifier">Iter2</span></code> must point to the same type - excluding | |
205 | const and volatile-qualifiers. | |
206 | </li> | |
207 | <li class="listitem"> | |
208 | The type pointed to by <code class="computeroutput"><span class="identifier">Iter1</span></code> | |
209 | must have a trivial assignment operator. | |
210 | </li> | |
211 | </ul></div> | |
212 | <p> | |
213 | By trivial assignment operator we mean that the type is either a scalar type<a class="link" href="background.html#background.references">[3]</a> or: | |
214 | </p> | |
215 | <div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "> | |
216 | <li class="listitem"> | |
217 | The type has no user defined assignment operator. | |
218 | </li> | |
219 | <li class="listitem"> | |
220 | The type does not have any data members that are references. | |
221 | </li> | |
222 | <li class="listitem"> | |
223 | All base classes, and all data member objects must have trivial assignment | |
224 | operators. | |
225 | </li> | |
226 | </ul></div> | |
227 | <p> | |
228 | If all these conditions are met then a type can be copied using <code class="computeroutput"><span class="identifier">memcpy</span></code> rather than using a compiler generated | |
229 | assignment operator. The type-traits library provides a class <code class="computeroutput"><a class="link" href="reference/has_trivial_assign.html" title="has_trivial_assign">has_trivial_assign</a></code>, | |
230 | such that <code class="computeroutput"><span class="identifier">has_trivial_assign</span><span class="special"><</span><span class="identifier">T</span><span class="special">>::</span><span class="identifier">value</span></code> is true only if T has a trivial assignment | |
231 | operator. This class "just works" for scalar types, but has to be | |
232 | explicitly specialised for class/struct types that also happen to have a trivial | |
233 | assignment operator. In other words if <a class="link" href="reference/has_trivial_assign.html" title="has_trivial_assign">has_trivial_assign</a> | |
234 | gives the wrong answer, it will give the "safe" wrong answer - that | |
235 | trivial assignment is not allowable. | |
236 | </p> | |
237 | <p> | |
238 | The code for an optimized version of copy that uses <code class="computeroutput"><span class="identifier">memcpy</span></code> | |
239 | where appropriate is given in <a class="link" href="examples/copy.html" title="An Optimized Version of std::copy">the | |
240 | examples</a>. The code begins by defining a template function <code class="computeroutput"><span class="identifier">do_copy</span></code> that performs a "slow but safe" | |
241 | copy. The last parameter passed to this function may be either a <code class="computeroutput"><a class="link" href="reference/integral_constant.html" title="integral_constant">true_type</a></code> | |
242 | or a <code class="computeroutput"><a class="link" href="reference/integral_constant.html" title="integral_constant">false_type</a></code>. | |
243 | Following that there is an overload of do_copy that uses <code class="computeroutput"><span class="identifier">memcpy</span></code>: | |
244 | this time the iterators are required to actually be pointers to the same type, | |
245 | and the final parameter must be a <code class="computeroutput"><a class="link" href="reference/integral_constant.html" title="integral_constant">true_type</a></code>. | |
246 | Finally, the version of <code class="computeroutput"><span class="identifier">copy</span></code> | |
247 | calls <code class="computeroutput"><span class="identifier">do_copy</span></code>, passing <code class="computeroutput"><a class="link" href="reference/has_trivial_assign.html" title="has_trivial_assign">has_trivial_assign</a><span class="special"><</span><span class="identifier">value_type</span><span class="special">>()</span></code> as the final parameter: this will dispatch | |
248 | to the optimized version where appropriate, otherwise it will call the "slow | |
249 | but safe version". | |
250 | </p> | |
251 | <h5> | |
252 | <a name="boost_typetraits.background.h3"></a> | |
253 | <span class="phrase"><a name="boost_typetraits.background.was_it_worth_it_"></a></span><a class="link" href="background.html#boost_typetraits.background.was_it_worth_it_">Was | |
254 | it worth it?</a> | |
255 | </h5> | |
256 | <p> | |
257 | It has often been repeated in these columns that "premature optimization | |
258 | is the root of all evil" <a class="link" href="background.html#background.references">[4]</a>. | |
259 | So the question must be asked: was our optimization premature? To put this | |
260 | in perspective the timings for our version of copy compared a conventional | |
261 | generic copy<a class="link" href="background.html#background.references">[5]</a> are shown in table | |
262 | 1. | |
263 | </p> | |
264 | <p> | |
265 | Clearly the optimization makes a difference in this case; but, to be fair, | |
266 | the timings are loaded to exclude cache miss effects - without this accurate | |
267 | comparison between algorithms becomes difficult. However, perhaps we can add | |
268 | a couple of caveats to the premature optimization rule: | |
269 | </p> | |
270 | <div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "> | |
271 | <li class="listitem"> | |
272 | If you use the right algorithm for the job in the first place then optimization | |
273 | will not be required; in some cases, memcpy is the right algorithm. | |
274 | </li> | |
275 | <li class="listitem"> | |
276 | If a component is going to be reused in many places by many people then | |
277 | optimizations may well be worthwhile where they would not be so for a single | |
278 | case - in other words, the likelihood that the optimization will be absolutely | |
279 | necessary somewhere, sometime is that much higher. Just as importantly | |
280 | the perceived value of the stock implementation will be higher: there is | |
281 | no point standardizing an algorithm if users reject it on the grounds that | |
282 | there are better, more heavily optimized versions available. | |
283 | </li> | |
284 | </ul></div> | |
285 | <div class="table"> | |
286 | <a name="boost_typetraits.background.time_taken_to_copy_1000_elements_using__copy_const_t___t_____times_in_micro_seconds_"></a><p class="title"><b>Table 1.1. Time taken to copy 1000 elements using `copy<const T*, T*>` (times | |
287 | in micro-seconds)</b></p> | |
288 | <div class="table-contents"><table class="table" summary="Time taken to copy 1000 elements using `copy<const T*, T*>` (times | |
289 | in micro-seconds)"> | |
290 | <colgroup> | |
291 | <col> | |
292 | <col> | |
293 | <col> | |
294 | </colgroup> | |
295 | <thead><tr> | |
296 | <th> | |
297 | <p> | |
298 | Version | |
299 | </p> | |
300 | </th> | |
301 | <th> | |
302 | <p> | |
303 | T | |
304 | </p> | |
305 | </th> | |
306 | <th> | |
307 | <p> | |
308 | Time | |
309 | </p> | |
310 | </th> | |
311 | </tr></thead> | |
312 | <tbody> | |
313 | <tr> | |
314 | <td> | |
315 | <p> | |
316 | "Optimized" copy | |
317 | </p> | |
318 | </td> | |
319 | <td> | |
320 | <p> | |
321 | char | |
322 | </p> | |
323 | </td> | |
324 | <td> | |
325 | <p> | |
326 | 0.99 | |
327 | </p> | |
328 | </td> | |
329 | </tr> | |
330 | <tr> | |
331 | <td> | |
332 | <p> | |
333 | Conventional copy | |
334 | </p> | |
335 | </td> | |
336 | <td> | |
337 | <p> | |
338 | char | |
339 | </p> | |
340 | </td> | |
341 | <td> | |
342 | <p> | |
343 | 8.07 | |
344 | </p> | |
345 | </td> | |
346 | </tr> | |
347 | <tr> | |
348 | <td> | |
349 | <p> | |
350 | "Optimized" copy | |
351 | </p> | |
352 | </td> | |
353 | <td> | |
354 | <p> | |
355 | int | |
356 | </p> | |
357 | </td> | |
358 | <td> | |
359 | <p> | |
360 | 2.52 | |
361 | </p> | |
362 | </td> | |
363 | </tr> | |
364 | <tr> | |
365 | <td> | |
366 | <p> | |
367 | Conventional copy | |
368 | </p> | |
369 | </td> | |
370 | <td> | |
371 | <p> | |
372 | int | |
373 | </p> | |
374 | </td> | |
375 | <td> | |
376 | <p> | |
377 | 8.02 | |
378 | </p> | |
379 | </td> | |
380 | </tr> | |
381 | </tbody> | |
382 | </table></div> | |
383 | </div> | |
384 | <br class="table-break"><h5> | |
385 | <a name="boost_typetraits.background.h4"></a> | |
386 | <span class="phrase"><a name="boost_typetraits.background.pair_of_references"></a></span><a class="link" href="background.html#boost_typetraits.background.pair_of_references">Pair | |
387 | of References</a> | |
388 | </h5> | |
389 | <p> | |
390 | The optimized copy example shows how type traits may be used to perform optimization | |
391 | decisions at compile-time. Another important usage of type traits is to allow | |
392 | code to compile that otherwise would not do so unless excessive partial specialization | |
393 | is used. This is possible by delegating partial specialization to the type | |
394 | traits classes. Our example for this form of usage is a pair that can hold | |
395 | references <a class="link" href="background.html#background.references">[6]</a>. | |
396 | </p> | |
397 | <p> | |
398 | First, let us examine the definition of <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">pair</span></code>, omitting | |
399 | the comparison operators, default constructor, and template copy constructor | |
400 | for simplicity: | |
401 | </p> | |
402 | <pre class="programlisting"><span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">T1</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">T2</span><span class="special">></span> | |
403 | <span class="keyword">struct</span> <span class="identifier">pair</span> | |
404 | <span class="special">{</span> | |
405 | <span class="keyword">typedef</span> <span class="identifier">T1</span> <span class="identifier">first_type</span><span class="special">;</span> | |
406 | <span class="keyword">typedef</span> <span class="identifier">T2</span> <span class="identifier">second_type</span><span class="special">;</span> | |
407 | ||
408 | <span class="identifier">T1</span> <span class="identifier">first</span><span class="special">;</span> | |
409 | <span class="identifier">T2</span> <span class="identifier">second</span><span class="special">;</span> | |
410 | ||
411 | <span class="identifier">pair</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">T1</span> <span class="special">&</span> <span class="identifier">nfirst</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">T2</span> <span class="special">&</span> <span class="identifier">nsecond</span><span class="special">)</span> | |
412 | <span class="special">:</span><span class="identifier">first</span><span class="special">(</span><span class="identifier">nfirst</span><span class="special">),</span> <span class="identifier">second</span><span class="special">(</span><span class="identifier">nsecond</span><span class="special">)</span> <span class="special">{</span> <span class="special">}</span> | |
413 | <span class="special">};</span> | |
414 | </pre> | |
415 | <p> | |
416 | Now, this "pair" cannot hold references as it currently stands, because | |
417 | the constructor would require taking a reference to a reference, which is currently | |
418 | illegal <a class="link" href="background.html#background.references">[7]</a>. Let us consider what | |
419 | the constructor's parameters would have to be in order to allow "pair" | |
420 | to hold non-reference types, references, and constant references: | |
421 | </p> | |
422 | <div class="table"> | |
423 | <a name="boost_typetraits.background.required_constructor_argument_types"></a><p class="title"><b>Table 1.2. Required Constructor Argument Types</b></p> | |
424 | <div class="table-contents"><table class="table" summary="Required Constructor Argument Types"> | |
425 | <colgroup> | |
426 | <col> | |
427 | <col> | |
428 | </colgroup> | |
429 | <thead><tr> | |
430 | <th> | |
431 | <p> | |
432 | Type of <code class="computeroutput"><span class="identifier">T1</span></code> | |
433 | </p> | |
434 | </th> | |
435 | <th> | |
436 | <p> | |
437 | Type of parameter to initializing constructor | |
438 | </p> | |
439 | </th> | |
440 | </tr></thead> | |
441 | <tbody> | |
442 | <tr> | |
443 | <td> | |
444 | <p> | |
445 | T | |
446 | </p> | |
447 | </td> | |
448 | <td> | |
449 | <p> | |
450 | const T & | |
451 | </p> | |
452 | </td> | |
453 | </tr> | |
454 | <tr> | |
455 | <td> | |
456 | <p> | |
457 | T & | |
458 | </p> | |
459 | </td> | |
460 | <td> | |
461 | <p> | |
462 | T & | |
463 | </p> | |
464 | </td> | |
465 | </tr> | |
466 | <tr> | |
467 | <td> | |
468 | <p> | |
469 | const T & | |
470 | </p> | |
471 | </td> | |
472 | <td> | |
473 | <p> | |
474 | const T & | |
475 | </p> | |
476 | </td> | |
477 | </tr> | |
478 | </tbody> | |
479 | </table></div> | |
480 | </div> | |
481 | <br class="table-break"><p> | |
482 | A little familiarity with the type traits classes allows us to construct a | |
483 | single mapping that allows us to determine the type of parameter from the type | |
484 | of the contained class. The type traits classes provide a transformation <a class="link" href="reference/add_reference.html" title="add_reference">add_reference</a>, which | |
485 | adds a reference to its type, unless it is already a reference. | |
486 | </p> | |
487 | <div class="table"> | |
488 | <a name="boost_typetraits.background.using_add_reference_to_synthesize_the_correct_constructor_type"></a><p class="title"><b>Table 1.3. Using add_reference to synthesize the correct constructor type</b></p> | |
489 | <div class="table-contents"><table class="table" summary="Using add_reference to synthesize the correct constructor type"> | |
490 | <colgroup> | |
491 | <col> | |
492 | <col> | |
493 | <col> | |
494 | </colgroup> | |
495 | <thead><tr> | |
496 | <th> | |
497 | <p> | |
498 | Type of <code class="computeroutput"><span class="identifier">T1</span></code> | |
499 | </p> | |
500 | </th> | |
501 | <th> | |
502 | <p> | |
503 | Type of <code class="computeroutput"><span class="keyword">const</span> <span class="identifier">T1</span></code> | |
504 | </p> | |
505 | </th> | |
506 | <th> | |
507 | <p> | |
508 | Type of <code class="computeroutput"><span class="identifier">add_reference</span><span class="special"><</span><span class="keyword">const</span> | |
509 | <span class="identifier">T1</span><span class="special">>::</span><span class="identifier">type</span></code> | |
510 | </p> | |
511 | </th> | |
512 | </tr></thead> | |
513 | <tbody> | |
514 | <tr> | |
515 | <td> | |
516 | <p> | |
517 | T | |
518 | </p> | |
519 | </td> | |
520 | <td> | |
521 | <p> | |
522 | const T | |
523 | </p> | |
524 | </td> | |
525 | <td> | |
526 | <p> | |
527 | const T & | |
528 | </p> | |
529 | </td> | |
530 | </tr> | |
531 | <tr> | |
532 | <td> | |
533 | <p> | |
534 | T & | |
535 | </p> | |
536 | </td> | |
537 | <td> | |
538 | <p> | |
539 | T & [8] | |
540 | </p> | |
541 | </td> | |
542 | <td> | |
543 | <p> | |
544 | T & | |
545 | </p> | |
546 | </td> | |
547 | </tr> | |
548 | <tr> | |
549 | <td> | |
550 | <p> | |
551 | const T & | |
552 | </p> | |
553 | </td> | |
554 | <td> | |
555 | <p> | |
556 | const T & | |
557 | </p> | |
558 | </td> | |
559 | <td> | |
560 | <p> | |
561 | const T & | |
562 | </p> | |
563 | </td> | |
564 | </tr> | |
565 | </tbody> | |
566 | </table></div> | |
567 | </div> | |
568 | <br class="table-break"><p> | |
569 | This allows us to build a primary template definition for <code class="computeroutput"><span class="identifier">pair</span></code> | |
570 | that can contain non-reference types, reference types, and constant reference | |
571 | types: | |
572 | </p> | |
573 | <pre class="programlisting"><span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">T1</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">T2</span><span class="special">></span> | |
574 | <span class="keyword">struct</span> <span class="identifier">pair</span> | |
575 | <span class="special">{</span> | |
576 | <span class="keyword">typedef</span> <span class="identifier">T1</span> <span class="identifier">first_type</span><span class="special">;</span> | |
577 | <span class="keyword">typedef</span> <span class="identifier">T2</span> <span class="identifier">second_type</span><span class="special">;</span> | |
578 | ||
579 | <span class="identifier">T1</span> <span class="identifier">first</span><span class="special">;</span> | |
580 | <span class="identifier">T2</span> <span class="identifier">second</span><span class="special">;</span> | |
581 | ||
582 | <span class="identifier">pair</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><a class="link" href="reference/add_reference.html" title="add_reference">add_reference</a><span class="special"><</span><span class="keyword">const</span> <span class="identifier">T1</span><span class="special">>::</span><span class="identifier">type</span> <span class="identifier">nfirst</span><span class="special">,</span> | |
583 | <span class="identifier">boost</span><span class="special">::</span><a class="link" href="reference/add_reference.html" title="add_reference">add_reference</a><span class="special"><</span><span class="keyword">const</span> <span class="identifier">T2</span><span class="special">>::</span><span class="identifier">type</span> <span class="identifier">nsecond</span><span class="special">)</span> | |
584 | <span class="special">:</span><span class="identifier">first</span><span class="special">(</span><span class="identifier">nfirst</span><span class="special">),</span> <span class="identifier">second</span><span class="special">(</span><span class="identifier">nsecond</span><span class="special">)</span> <span class="special">{</span> <span class="special">}</span> | |
585 | <span class="special">};</span> | |
586 | </pre> | |
587 | <p> | |
588 | Add back in the standard comparison operators, default constructor, and template | |
589 | copy constructor (which are all the same), and you have a <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">pair</span></code> that | |
590 | can hold reference types! | |
591 | </p> | |
592 | <p> | |
593 | This same extension could have been done using partial template specialization | |
594 | of <code class="computeroutput"><span class="identifier">pair</span></code>, but to specialize | |
595 | <code class="computeroutput"><span class="identifier">pair</span></code> in this way would require | |
596 | three partial specializations, plus the primary template. Type traits allows | |
597 | us to define a single primary template that adjusts itself auto-magically to | |
598 | any of these partial specializations, instead of a brute-force partial specialization | |
599 | approach. Using type traits in this fashion allows programmers to delegate | |
600 | partial specialization to the type traits classes, resulting in code that is | |
601 | easier to maintain and easier to understand. | |
602 | </p> | |
603 | <h5> | |
604 | <a name="boost_typetraits.background.h5"></a> | |
605 | <span class="phrase"><a name="boost_typetraits.background.conclusion"></a></span><a class="link" href="background.html#boost_typetraits.background.conclusion">Conclusion</a> | |
606 | </h5> | |
607 | <p> | |
608 | We hope that in this article we have been able to give you some idea of what | |
609 | type-traits are all about. A more complete listing of the available classes | |
610 | are in the boost documentation, along with further examples using type traits. | |
611 | Templates have enabled C++ uses to take the advantage of the code reuse that | |
612 | generic programming brings; hopefully this article has shown that generic programming | |
613 | does not have to sink to the lowest common denominator, and that templates | |
614 | can be optimal as well as generic. | |
615 | </p> | |
616 | <h5> | |
617 | <a name="boost_typetraits.background.h6"></a> | |
618 | <span class="phrase"><a name="boost_typetraits.background.acknowledgements"></a></span><a class="link" href="background.html#boost_typetraits.background.acknowledgements">Acknowledgements</a> | |
619 | </h5> | |
620 | <p> | |
621 | The authors would like to thank Beman Dawes and Howard Hinnant for their helpful | |
622 | comments when preparing this article. | |
623 | </p> | |
624 | <h5> | |
625 | <a name="boost_typetraits.background.h7"></a> | |
626 | <span class="phrase"><a name="boost_typetraits.background._anchor_id__background_references___references"></a></span><a class="link" href="background.html#boost_typetraits.background._anchor_id__background_references___references">References</a> | |
627 | </h5> | |
628 | <div class="orderedlist"><ol class="orderedlist" type="1"> | |
629 | <li class="listitem"> | |
630 | Nathan C. Myers, C++ Report, June 1995. | |
631 | </li> | |
632 | <li class="listitem"> | |
633 | The type traits library is based upon contributions by Steve Cleary, Beman | |
634 | Dawes, Howard Hinnant and John Maddock: it can be found at www.boost.org. | |
635 | </li> | |
636 | <li class="listitem"> | |
637 | A scalar type is an arithmetic type (i.e. a built-in integer or floating | |
638 | point type), an enumeration type, a pointer, a pointer to member, or a | |
639 | const- or volatile-qualified version of one of these types. | |
640 | </li> | |
641 | <li class="listitem"> | |
642 | This quote is from Donald Knuth, ACM Computing Surveys, December 1974, | |
643 | pg 268. | |
644 | </li> | |
645 | <li class="listitem"> | |
646 | The test code is available as part of the boost utility library (see algo_opt_examples.cpp), | |
647 | the code was compiled with gcc 2.95 with all optimisations turned on, tests | |
648 | were conducted on a 400MHz Pentium II machine running Microsoft Windows | |
649 | 98. | |
650 | </li> | |
651 | <li class="listitem"> | |
652 | John Maddock and Howard Hinnant have submitted a "compressed_pair" | |
653 | library to Boost, which uses a technique similar to the one described here | |
654 | to hold references. Their pair also uses type traits to determine if any | |
655 | of the types are empty, and will derive instead of contain to conserve | |
656 | space -- hence the name "compressed". | |
657 | </li> | |
658 | <li class="listitem"> | |
659 | This is actually an issue with the C++ Core Language Working Group (issue | |
660 | #106), submitted by Bjarne Stroustrup. The tentative resolution is to allow | |
661 | a "reference to a reference to T" to mean the same thing as a | |
662 | "reference to T", but only in template instantiation, in a method | |
663 | similar to multiple cv-qualifiers. | |
664 | </li> | |
665 | <li class="listitem"> | |
666 | For those of you who are wondering why this shouldn't be const-qualified, | |
667 | remember that references are always implicitly constant (for example, you | |
668 | can't re-assign a reference). Remember also that "const T &" | |
669 | is something completely different. For this reason, cv-qualifiers on template | |
670 | type arguments that are references are ignored. | |
671 | </li> | |
672 | </ol></div> | |
673 | </div> | |
674 | <table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr> | |
675 | <td align="left"></td> | |
676 | <td align="right"><div class="copyright-footer">Copyright © 2000, 2011 Adobe Systems Inc, David Abrahams, | |
677 | Frederic Bron, Steve Cleary, Beman Dawes, Aleksey Gurtovoy, Howard Hinnant, | |
678 | Jesse Jones, Mat Marcus, Itay Maman, John Maddock, Alexander Nasonov, Thorsten | |
679 | Ottosen, Roman Perepelitsa, Robert Ramey, Jeremy Siek, Robert Stewart and Steven | |
680 | Watanabe<p> | |
681 | Distributed under the Boost Software License, Version 1.0. (See accompanying | |
682 | file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>) | |
683 | </p> | |
684 | </div></td> | |
685 | </tr></table> | |
686 | <hr> | |
687 | <div class="spirit-nav"> | |
688 | <a accesskey="p" href="intro.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="category.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a> | |
689 | </div> | |
690 | </body> | |
691 | </html> |