1 | <html> |
---|
2 | |
---|
3 | <head> |
---|
4 | <meta http-equiv="Content-Type" |
---|
5 | content="text/html; charset=iso-8859-1"> |
---|
6 | <meta name="Template" |
---|
7 | content="C:\PROGRAM FILES\MICROSOFT OFFICE\OFFICE\html.dot"> |
---|
8 | <meta name="GENERATOR" content="Microsoft FrontPage Express 2.0"> |
---|
9 | <title>Call Traits</title> |
---|
10 | </head> |
---|
11 | |
---|
12 | <body bgcolor="#FFFFFF" text="#000000" link="#0000FF" |
---|
13 | vlink="#800080"> |
---|
14 | |
---|
15 | <h1><img src="../../boost.png" width="276" height="86">Header |
---|
16 | <<a href="../../boost/detail/call_traits.hpp">boost/call_traits.hpp</a>></h1> |
---|
17 | |
---|
18 | <p>All of the contents of <boost/call_traits.hpp> are |
---|
19 | defined inside namespace boost.</p> |
---|
20 | |
---|
21 | <p>The template class call_traits<T> encapsulates the |
---|
22 | "best" method to pass a parameter of some type T to or |
---|
23 | from a function, and consists of a collection of typedefs defined |
---|
24 | as in the table below. The purpose of call_traits is to ensure |
---|
25 | that problems like "<a href="#refs">references to references</a>" |
---|
26 | never occur, and that parameters are passed in the most efficient |
---|
27 | manner possible (see <a href="#examples">examples</a>). In each |
---|
28 | case if your existing practice is to use the type defined on the |
---|
29 | left, then replace it with the call_traits defined type on the |
---|
30 | right. </p> |
---|
31 | |
---|
32 | <p>Note that for compilers that do not support either partial |
---|
33 | specialization or member templates, no benefit will occur from |
---|
34 | using call_traits: the call_traits defined types will always be |
---|
35 | the same as the existing practice in this case. In addition if |
---|
36 | only member templates and not partial template specialisation is |
---|
37 | support by the compiler (for example Visual C++ 6) then |
---|
38 | call_traits can not be used with array types (although it can be |
---|
39 | used to solve the reference to reference problem).</p> |
---|
40 | |
---|
41 | <table border="0" cellpadding="7" cellspacing="1" width="797"> |
---|
42 | <tr> |
---|
43 | <td valign="top" width="17%" bgcolor="#008080"><p |
---|
44 | align="center">Existing practice</p> |
---|
45 | </td> |
---|
46 | <td valign="top" width="35%" bgcolor="#008080"><p |
---|
47 | align="center">call_traits equivalent</p> |
---|
48 | </td> |
---|
49 | <td valign="top" width="32%" bgcolor="#008080"><p |
---|
50 | align="center">Description</p> |
---|
51 | </td> |
---|
52 | <td valign="top" width="16%" bgcolor="#008080"><p |
---|
53 | align="center">Notes</p> |
---|
54 | </td> |
---|
55 | </tr> |
---|
56 | <tr> |
---|
57 | <td valign="top" width="17%"><p align="center">T<br> |
---|
58 | (return by value)</p> |
---|
59 | </td> |
---|
60 | <td valign="top" width="35%"><p align="center"><code>call_traits<T>::value_type</code></p> |
---|
61 | </td> |
---|
62 | <td valign="top" width="32%">Defines a type that |
---|
63 | represents the "value" of type T. Use this for |
---|
64 | functions that return by value, or possibly for stored |
---|
65 | values of type T.</td> |
---|
66 | <td valign="top" width="16%"><p align="center">2</p> |
---|
67 | </td> |
---|
68 | </tr> |
---|
69 | <tr> |
---|
70 | <td valign="top" width="17%"><p align="center">T&<br> |
---|
71 | (return value)</p> |
---|
72 | </td> |
---|
73 | <td valign="top" width="35%"><p align="center"><code>call_traits<T>::reference</code></p> |
---|
74 | </td> |
---|
75 | <td valign="top" width="32%">Defines a type that |
---|
76 | represents a reference to type T. Use for functions that |
---|
77 | would normally return a T&.</td> |
---|
78 | <td valign="top" width="16%"><p align="center">1</p> |
---|
79 | </td> |
---|
80 | </tr> |
---|
81 | <tr> |
---|
82 | <td valign="top" width="17%"><p align="center">const |
---|
83 | T&<br> |
---|
84 | (return value)</p> |
---|
85 | </td> |
---|
86 | <td valign="top" width="35%"><p align="center"><code>call_traits<T>::const_reference</code></p> |
---|
87 | </td> |
---|
88 | <td valign="top" width="32%">Defines a type that |
---|
89 | represents a constant reference to type T. Use for |
---|
90 | functions that would normally return a const T&.</td> |
---|
91 | <td valign="top" width="16%"><p align="center">1</p> |
---|
92 | </td> |
---|
93 | </tr> |
---|
94 | <tr> |
---|
95 | <td valign="top" width="17%"><p align="center">const |
---|
96 | T&<br> |
---|
97 | (function parameter)</p> |
---|
98 | </td> |
---|
99 | <td valign="top" width="35%"><p align="center"><code>call_traits<T>::param_type</code></p> |
---|
100 | </td> |
---|
101 | <td valign="top" width="32%">Defines a type that |
---|
102 | represents the "best" way to pass a parameter |
---|
103 | of type T to a function.</td> |
---|
104 | <td valign="top" width="16%"><p align="center">1,3</p> |
---|
105 | </td> |
---|
106 | </tr> |
---|
107 | </table> |
---|
108 | |
---|
109 | <p>Notes:</p> |
---|
110 | |
---|
111 | <ol> |
---|
112 | <li>If T is already reference type, then call_traits is |
---|
113 | defined such that <a href="#refs">references to |
---|
114 | references</a> do not occur (requires partial |
---|
115 | specialization).</li> |
---|
116 | <li>If T is an array type, then call_traits defines <code>value_type</code> |
---|
117 | as a "constant pointer to type" rather than an |
---|
118 | "array of type" (requires partial |
---|
119 | specialization). Note that if you are using value_type as |
---|
120 | a stored value then this will result in storing a "constant |
---|
121 | pointer to an array" rather than the array itself. |
---|
122 | This may or may not be a good thing depending upon what |
---|
123 | you actually need (in other words take care!).</li> |
---|
124 | <li>If T is a small built in type or a pointer, then <code>param_type</code> |
---|
125 | is defined as <code>T const</code>, instead of <code>T |
---|
126 | const&</code>. This can improve the ability of the |
---|
127 | compiler to optimize loops in the body of the function if |
---|
128 | they depend upon the passed parameter, the semantics of |
---|
129 | the passed parameter is otherwise unchanged (requires |
---|
130 | partial specialization).</li> |
---|
131 | </ol> |
---|
132 | |
---|
133 | <p> </p> |
---|
134 | |
---|
135 | <h3>Copy constructibility</h3> |
---|
136 | |
---|
137 | <p>The following table defines which call_traits types can always |
---|
138 | be copy-constructed from which other types, those entries marked |
---|
139 | with a '?' are true only if and only if T is copy constructible:</p> |
---|
140 | |
---|
141 | <table border="0" cellpadding="7" cellspacing="1" width="766"> |
---|
142 | <tr> |
---|
143 | <td valign="top" width="17%"> </td> |
---|
144 | <td valign="top" colspan="5" width="85%" |
---|
145 | bgcolor="#008080"><p align="center">To:</p> |
---|
146 | </td> |
---|
147 | </tr> |
---|
148 | <tr> |
---|
149 | <td valign="top" width="17%" bgcolor="#008080">From:</td> |
---|
150 | <td valign="top" width="17%" bgcolor="#C0C0C0"><p |
---|
151 | align="center">T</p> |
---|
152 | </td> |
---|
153 | <td valign="top" width="17%" bgcolor="#C0C0C0"><p |
---|
154 | align="center">value_type</p> |
---|
155 | </td> |
---|
156 | <td valign="top" width="17%" bgcolor="#C0C0C0"><p |
---|
157 | align="center">reference</p> |
---|
158 | </td> |
---|
159 | <td valign="top" width="17%" bgcolor="#C0C0C0"><p |
---|
160 | align="center">const_reference</p> |
---|
161 | </td> |
---|
162 | <td valign="top" width="17%" bgcolor="#C0C0C0"><p |
---|
163 | align="center">param_type</p> |
---|
164 | </td> |
---|
165 | </tr> |
---|
166 | <tr> |
---|
167 | <td valign="top" width="17%" bgcolor="#C0C0C0">T</td> |
---|
168 | <td valign="top" width="17%"><p align="center">?</p> |
---|
169 | </td> |
---|
170 | <td valign="top" width="17%"><p align="center">?</p> |
---|
171 | </td> |
---|
172 | <td valign="top" width="17%"><p align="center">Y</p> |
---|
173 | </td> |
---|
174 | <td valign="top" width="17%"><p align="center">Y</p> |
---|
175 | </td> |
---|
176 | <td valign="top" width="17%"><p align="center">Y</p> |
---|
177 | </td> |
---|
178 | </tr> |
---|
179 | <tr> |
---|
180 | <td valign="top" width="17%" bgcolor="#C0C0C0">value_type</td> |
---|
181 | <td valign="top" width="17%"><p align="center">?</p> |
---|
182 | </td> |
---|
183 | <td valign="top" width="17%"><p align="center">?</p> |
---|
184 | </td> |
---|
185 | <td valign="top" width="17%"><p align="center">N</p> |
---|
186 | </td> |
---|
187 | <td valign="top" width="17%"><p align="center">N</p> |
---|
188 | </td> |
---|
189 | <td valign="top" width="17%"><p align="center">Y</p> |
---|
190 | </td> |
---|
191 | </tr> |
---|
192 | <tr> |
---|
193 | <td valign="top" width="17%" bgcolor="#C0C0C0">reference</td> |
---|
194 | <td valign="top" width="17%"><p align="center">?</p> |
---|
195 | </td> |
---|
196 | <td valign="top" width="17%"><p align="center">?</p> |
---|
197 | </td> |
---|
198 | <td valign="top" width="17%"><p align="center">Y</p> |
---|
199 | </td> |
---|
200 | <td valign="top" width="17%"><p align="center">Y</p> |
---|
201 | </td> |
---|
202 | <td valign="top" width="17%"><p align="center">Y</p> |
---|
203 | </td> |
---|
204 | </tr> |
---|
205 | <tr> |
---|
206 | <td valign="top" width="17%" bgcolor="#C0C0C0">const_reference</td> |
---|
207 | <td valign="top" width="17%"><p align="center">?</p> |
---|
208 | </td> |
---|
209 | <td valign="top" width="17%"><p align="center">N</p> |
---|
210 | </td> |
---|
211 | <td valign="top" width="17%"><p align="center">N</p> |
---|
212 | </td> |
---|
213 | <td valign="top" width="17%"><p align="center">Y</p> |
---|
214 | </td> |
---|
215 | <td valign="top" width="17%"><p align="center">Y</p> |
---|
216 | </td> |
---|
217 | </tr> |
---|
218 | <tr> |
---|
219 | <td valign="top" width="17%" bgcolor="#C0C0C0">param_type</td> |
---|
220 | <td valign="top" width="17%"><p align="center">?</p> |
---|
221 | </td> |
---|
222 | <td valign="top" width="17%"><p align="center">?</p> |
---|
223 | </td> |
---|
224 | <td valign="top" width="17%"><p align="center">N</p> |
---|
225 | </td> |
---|
226 | <td valign="top" width="17%"><p align="center">N</p> |
---|
227 | </td> |
---|
228 | <td valign="top" width="17%"><p align="center">Y</p> |
---|
229 | </td> |
---|
230 | </tr> |
---|
231 | </table> |
---|
232 | |
---|
233 | <p> </p> |
---|
234 | |
---|
235 | <p>If T is an assignable type the following assignments are |
---|
236 | possible:</p> |
---|
237 | |
---|
238 | <table border="0" cellpadding="7" cellspacing="1" width="766"> |
---|
239 | <tr> |
---|
240 | <td valign="top" width="17%"> </td> |
---|
241 | <td valign="top" colspan="5" width="85%" |
---|
242 | bgcolor="#008080"><p align="center">To:</p> |
---|
243 | </td> |
---|
244 | </tr> |
---|
245 | <tr> |
---|
246 | <td valign="top" width="17%" bgcolor="#008080">From:</td> |
---|
247 | <td valign="top" width="17%" bgcolor="#C0C0C0"><p |
---|
248 | align="center">T</p> |
---|
249 | </td> |
---|
250 | <td valign="top" width="17%" bgcolor="#C0C0C0"><p |
---|
251 | align="center">value_type</p> |
---|
252 | </td> |
---|
253 | <td valign="top" width="17%" bgcolor="#C0C0C0"><p |
---|
254 | align="center">reference</p> |
---|
255 | </td> |
---|
256 | <td valign="top" width="17%" bgcolor="#C0C0C0"><p |
---|
257 | align="center">const_reference</p> |
---|
258 | </td> |
---|
259 | <td valign="top" width="17%" bgcolor="#C0C0C0"><p |
---|
260 | align="center">param_type</p> |
---|
261 | </td> |
---|
262 | </tr> |
---|
263 | <tr> |
---|
264 | <td valign="top" width="17%" bgcolor="#C0C0C0">T</td> |
---|
265 | <td valign="top" width="17%"><p align="center">Y</p> |
---|
266 | </td> |
---|
267 | <td valign="top" width="17%"><p align="center">Y</p> |
---|
268 | </td> |
---|
269 | <td valign="top" width="17%"><p align="center">-</p> |
---|
270 | </td> |
---|
271 | <td valign="top" width="17%"><p align="center">-</p> |
---|
272 | </td> |
---|
273 | <td valign="top" width="17%"><p align="center">-</p> |
---|
274 | </td> |
---|
275 | </tr> |
---|
276 | <tr> |
---|
277 | <td valign="top" width="17%" bgcolor="#C0C0C0">value_type</td> |
---|
278 | <td valign="top" width="17%"><p align="center">Y</p> |
---|
279 | </td> |
---|
280 | <td valign="top" width="17%"><p align="center">Y</p> |
---|
281 | </td> |
---|
282 | <td valign="top" width="17%"><p align="center">-</p> |
---|
283 | </td> |
---|
284 | <td valign="top" width="17%"><p align="center">-</p> |
---|
285 | </td> |
---|
286 | <td valign="top" width="17%"><p align="center">-</p> |
---|
287 | </td> |
---|
288 | </tr> |
---|
289 | <tr> |
---|
290 | <td valign="top" width="17%" bgcolor="#C0C0C0">reference</td> |
---|
291 | <td valign="top" width="17%"><p align="center">Y</p> |
---|
292 | </td> |
---|
293 | <td valign="top" width="17%"><p align="center">Y</p> |
---|
294 | </td> |
---|
295 | <td valign="top" width="17%"><p align="center">-</p> |
---|
296 | </td> |
---|
297 | <td valign="top" width="17%"><p align="center">-</p> |
---|
298 | </td> |
---|
299 | <td valign="top" width="17%"><p align="center">-</p> |
---|
300 | </td> |
---|
301 | </tr> |
---|
302 | <tr> |
---|
303 | <td valign="top" width="17%" bgcolor="#C0C0C0">const_reference</td> |
---|
304 | <td valign="top" width="17%"><p align="center">Y</p> |
---|
305 | </td> |
---|
306 | <td valign="top" width="17%"><p align="center">Y</p> |
---|
307 | </td> |
---|
308 | <td valign="top" width="17%"><p align="center">-</p> |
---|
309 | </td> |
---|
310 | <td valign="top" width="17%"><p align="center">-</p> |
---|
311 | </td> |
---|
312 | <td valign="top" width="17%"><p align="center">-</p> |
---|
313 | </td> |
---|
314 | </tr> |
---|
315 | <tr> |
---|
316 | <td valign="top" width="17%" bgcolor="#C0C0C0">param_type</td> |
---|
317 | <td valign="top" width="17%"><p align="center">Y</p> |
---|
318 | </td> |
---|
319 | <td valign="top" width="17%"><p align="center">Y</p> |
---|
320 | </td> |
---|
321 | <td valign="top" width="17%"><p align="center">-</p> |
---|
322 | </td> |
---|
323 | <td valign="top" width="17%"><p align="center">-</p> |
---|
324 | </td> |
---|
325 | <td valign="top" width="17%"><p align="center">-</p> |
---|
326 | </td> |
---|
327 | </tr> |
---|
328 | </table> |
---|
329 | |
---|
330 | <p> </p> |
---|
331 | |
---|
332 | <h3><a name="examples"></a>Examples</h3> |
---|
333 | |
---|
334 | <p>The following table shows the effect that call_traits has on |
---|
335 | various types, the table assumes that the compiler supports |
---|
336 | partial specialization: if it doesn't then all types behave in |
---|
337 | the same way as the entry for "myclass", and |
---|
338 | call_traits can not be used with reference or array types.</p> |
---|
339 | |
---|
340 | <table border="0" cellpadding="7" cellspacing="1" width="766"> |
---|
341 | <tr> |
---|
342 | <td valign="top" width="17%"> </td> |
---|
343 | <td valign="top" colspan="5" width="85%" |
---|
344 | bgcolor="#008080"><p align="center">Call_traits type:</p> |
---|
345 | </td> |
---|
346 | </tr> |
---|
347 | <tr> |
---|
348 | <td valign="top" width="17%" bgcolor="#008080"><p |
---|
349 | align="center">Original type T</p> |
---|
350 | </td> |
---|
351 | <td valign="top" width="17%" bgcolor="#C0C0C0"><p |
---|
352 | align="center">value_type</p> |
---|
353 | </td> |
---|
354 | <td valign="top" width="17%" bgcolor="#C0C0C0"><p |
---|
355 | align="center">reference</p> |
---|
356 | </td> |
---|
357 | <td valign="top" width="17%" bgcolor="#C0C0C0"><p |
---|
358 | align="center">const_reference</p> |
---|
359 | </td> |
---|
360 | <td valign="top" width="17%" bgcolor="#C0C0C0"><p |
---|
361 | align="center">param_type</p> |
---|
362 | </td> |
---|
363 | <td valign="top" width="17%" bgcolor="#C0C0C0"><p |
---|
364 | align="center">Applies to:</p> |
---|
365 | </td> |
---|
366 | </tr> |
---|
367 | <tr> |
---|
368 | <td valign="top" width="17%" bgcolor="#C0C0C0"><p |
---|
369 | align="center">myclass</p> |
---|
370 | </td> |
---|
371 | <td valign="top" width="17%"><p align="center">myclass</p> |
---|
372 | </td> |
---|
373 | <td valign="top" width="17%"><p align="center">myclass&</p> |
---|
374 | </td> |
---|
375 | <td valign="top" width="17%"><p align="center">const |
---|
376 | myclass&</p> |
---|
377 | </td> |
---|
378 | <td valign="top" width="17%"><p align="center">myclass |
---|
379 | const&</p> |
---|
380 | </td> |
---|
381 | <td valign="top" width="17%"><p align="center">All user |
---|
382 | defined types.</p> |
---|
383 | </td> |
---|
384 | </tr> |
---|
385 | <tr> |
---|
386 | <td valign="top" width="17%" bgcolor="#C0C0C0"><p |
---|
387 | align="center">int</p> |
---|
388 | </td> |
---|
389 | <td valign="top" width="17%"><p align="center">int</p> |
---|
390 | </td> |
---|
391 | <td valign="top" width="17%"><p align="center">int&</p> |
---|
392 | </td> |
---|
393 | <td valign="top" width="17%"><p align="center">const |
---|
394 | int&</p> |
---|
395 | </td> |
---|
396 | <td valign="top" width="17%"><p align="center">int const</p> |
---|
397 | </td> |
---|
398 | <td valign="top" width="17%"><p align="center">All small |
---|
399 | built-in types.</p> |
---|
400 | </td> |
---|
401 | </tr> |
---|
402 | <tr> |
---|
403 | <td valign="top" width="17%" bgcolor="#C0C0C0"><p |
---|
404 | align="center">int*</p> |
---|
405 | </td> |
---|
406 | <td valign="top" width="17%"><p align="center">int*</p> |
---|
407 | </td> |
---|
408 | <td valign="top" width="17%"><p align="center">int*&</p> |
---|
409 | </td> |
---|
410 | <td valign="top" width="17%"><p align="center">int*const&</p> |
---|
411 | </td> |
---|
412 | <td valign="top" width="17%"><p align="center">int* const</p> |
---|
413 | </td> |
---|
414 | <td valign="top" width="17%"><p align="center">All |
---|
415 | pointer types.</p> |
---|
416 | </td> |
---|
417 | </tr> |
---|
418 | <tr> |
---|
419 | <td valign="top" width="17%" bgcolor="#C0C0C0"><p |
---|
420 | align="center">int&</p> |
---|
421 | </td> |
---|
422 | <td valign="top" width="17%"><p align="center">int&</p> |
---|
423 | </td> |
---|
424 | <td valign="top" width="17%"><p align="center">int&</p> |
---|
425 | </td> |
---|
426 | <td valign="top" width="17%"><p align="center">const |
---|
427 | int&</p> |
---|
428 | </td> |
---|
429 | <td valign="top" width="17%"><p align="center">int&</p> |
---|
430 | </td> |
---|
431 | <td valign="top" width="17%"><p align="center">All |
---|
432 | reference types.</p> |
---|
433 | </td> |
---|
434 | </tr> |
---|
435 | <tr> |
---|
436 | <td valign="top" width="17%" bgcolor="#C0C0C0"><p |
---|
437 | align="center">const int&</p> |
---|
438 | </td> |
---|
439 | <td valign="top" width="17%"><p align="center">const |
---|
440 | int&</p> |
---|
441 | </td> |
---|
442 | <td valign="top" width="17%"><p align="center">const |
---|
443 | int&</p> |
---|
444 | </td> |
---|
445 | <td valign="top" width="17%"><p align="center">const |
---|
446 | int&</p> |
---|
447 | </td> |
---|
448 | <td valign="top" width="17%"><p align="center">const |
---|
449 | int&</p> |
---|
450 | </td> |
---|
451 | <td valign="top" width="17%"><p align="center">All |
---|
452 | constant-references.</p> |
---|
453 | </td> |
---|
454 | </tr> |
---|
455 | <tr> |
---|
456 | <td valign="top" width="17%" bgcolor="#C0C0C0"><p |
---|
457 | align="center">int[3]</p> |
---|
458 | </td> |
---|
459 | <td valign="top" width="17%"><p align="center">const int*</p> |
---|
460 | </td> |
---|
461 | <td valign="top" width="17%"><p align="center">int(&)[3]</p> |
---|
462 | </td> |
---|
463 | <td valign="top" width="17%"><p align="center">const int(&)[3]</p> |
---|
464 | </td> |
---|
465 | <td valign="top" width="17%"><p align="center">const int* |
---|
466 | const</p> |
---|
467 | </td> |
---|
468 | <td valign="top" width="17%"><p align="center">All array |
---|
469 | types.</p> |
---|
470 | </td> |
---|
471 | </tr> |
---|
472 | <tr> |
---|
473 | <td valign="top" width="17%" bgcolor="#C0C0C0"><p |
---|
474 | align="center">const int[3]</p> |
---|
475 | </td> |
---|
476 | <td valign="top" width="17%"><p align="center">const int*</p> |
---|
477 | </td> |
---|
478 | <td valign="top" width="17%"><p align="center">const int(&)[3]</p> |
---|
479 | </td> |
---|
480 | <td valign="top" width="17%"><p align="center">const int(&)[3]</p> |
---|
481 | </td> |
---|
482 | <td valign="top" width="17%"><p align="center">const int* |
---|
483 | const</p> |
---|
484 | </td> |
---|
485 | <td valign="top" width="17%"><p align="center">All |
---|
486 | constant-array types.</p> |
---|
487 | </td> |
---|
488 | </tr> |
---|
489 | </table> |
---|
490 | |
---|
491 | <p> </p> |
---|
492 | |
---|
493 | <h4>Example 1:</h4> |
---|
494 | |
---|
495 | <p>The following class is a trivial class that stores some type T |
---|
496 | by value (see the <a href="call_traits_test.cpp">call_traits_test.cpp</a> |
---|
497 | file), the aim is to illustrate how each of the available |
---|
498 | call_traits typedefs may be used:</p> |
---|
499 | |
---|
500 | <pre>template <class T> |
---|
501 | struct contained |
---|
502 | { |
---|
503 | // define our typedefs first, arrays are stored by value |
---|
504 | // so value_type is not the same as result_type: |
---|
505 | typedef typename boost::call_traits<T>::param_type param_type; |
---|
506 | typedef typename boost::call_traits<T>::reference reference; |
---|
507 | typedef typename boost::call_traits<T>::const_reference const_reference; |
---|
508 | typedef T value_type; |
---|
509 | typedef typename boost::call_traits<T>::value_type result_type; |
---|
510 | |
---|
511 | // stored value: |
---|
512 | value_type v_; |
---|
513 | |
---|
514 | // constructors: |
---|
515 | contained() {} |
---|
516 | contained(param_type p) : v_(p){} |
---|
517 | // return byval: |
---|
518 | result_type value() { return v_; } |
---|
519 | // return by_ref: |
---|
520 | reference get() { return v_; } |
---|
521 | const_reference const_get()const { return v_; } |
---|
522 | // pass value: |
---|
523 | void call(param_type p){} |
---|
524 | |
---|
525 | };</pre> |
---|
526 | |
---|
527 | <h4><a name="refs"></a>Example 2 (the reference to reference |
---|
528 | problem):</h4> |
---|
529 | |
---|
530 | <p>Consider the definition of std::binder1st:</p> |
---|
531 | |
---|
532 | <pre>template <class Operation> |
---|
533 | class binder1st : |
---|
534 | public unary_function<typename Operation::second_argument_type, typename Operation::result_type> |
---|
535 | { |
---|
536 | protected: |
---|
537 | Operation op; |
---|
538 | typename Operation::first_argument_type value; |
---|
539 | public: |
---|
540 | binder1st(const Operation& x, const typename Operation::first_argument_type& y); |
---|
541 | typename Operation::result_type operator()(const typename Operation::second_argument_type& x) const; |
---|
542 | }; </pre> |
---|
543 | |
---|
544 | <p>Now consider what happens in the relatively common case that |
---|
545 | the functor takes its second argument as a reference, that |
---|
546 | implies that <code>Operation::second_argument_type</code> is a |
---|
547 | reference type, <code>operator()</code> will now end up taking a |
---|
548 | reference to a reference as an argument, and that is not |
---|
549 | currently legal. The solution here is to modify <code>operator()</code> |
---|
550 | to use call_traits:</p> |
---|
551 | |
---|
552 | <pre>typename Operation::result_type operator()(typename call_traits<typename Operation::second_argument_type>::param_type x) const;</pre> |
---|
553 | |
---|
554 | <p>Now in the case that <code>Operation::second_argument_type</code> |
---|
555 | is a reference type, the argument is passed as a reference, and |
---|
556 | the no "reference to reference" occurs.</p> |
---|
557 | |
---|
558 | <h4><a name="ex3"></a>Example 3 (the make_pair problem):</h4> |
---|
559 | |
---|
560 | <p>If we pass the name of an array as one (or both) arguments to <code>std::make_pair</code>, |
---|
561 | then template argument deduction deduces the passed parameter as |
---|
562 | "const reference to array of T", this also applies to |
---|
563 | string literals (which are really array literals). Consequently |
---|
564 | instead of returning a pair of pointers, it tries to return a |
---|
565 | pair of arrays, and since an array type is not copy-constructible |
---|
566 | the code fails to compile. One solution is to explicitly cast the |
---|
567 | arguments to make_pair to pointers, but call_traits provides a |
---|
568 | better (i.e. automatic) solution (and one that works safely even |
---|
569 | in generic code where the cast might do the wrong thing):</p> |
---|
570 | |
---|
571 | <pre>template <class T1, class T2> |
---|
572 | std::pair< |
---|
573 | typename boost::call_traits<T1>::value_type, |
---|
574 | typename boost::call_traits<T2>::value_type> |
---|
575 | make_pair(const T1& t1, const T2& t2) |
---|
576 | { |
---|
577 | return std::pair< |
---|
578 | typename boost::call_traits<T1>::value_type, |
---|
579 | typename boost::call_traits<T2>::value_type>(t1, t2); |
---|
580 | }</pre> |
---|
581 | |
---|
582 | <p>Here, the deduced argument types will be automatically |
---|
583 | degraded to pointers if the deduced types are arrays, similar |
---|
584 | situations occur in the standard binders and adapters: in |
---|
585 | principle in any function that "wraps" a temporary |
---|
586 | whose type is deduced. Note that the function arguments to |
---|
587 | make_pair are not expressed in terms of call_traits: doing so |
---|
588 | would prevent template argument deduction from functioning.</p> |
---|
589 | |
---|
590 | <h4><a name="ex4"></a>Example 4 (optimising fill):</h4> |
---|
591 | |
---|
592 | <p>The call_traits template will "optimize" the passing |
---|
593 | of a small built-in type as a function parameter, this mainly has |
---|
594 | an effect when the parameter is used within a loop body. In the |
---|
595 | following example (see <a |
---|
596 | href="../type_traits/examples/fill_example.cpp">fill_example.cpp</a>), |
---|
597 | a version of std::fill is optimized in two ways: if the type |
---|
598 | passed is a single byte built-in type then std::memset is used to |
---|
599 | effect the fill, otherwise a conventional C++ implemention is |
---|
600 | used, but with the passed parameter "optimized" using |
---|
601 | call_traits:</p> |
---|
602 | |
---|
603 | <pre>namespace detail{ |
---|
604 | |
---|
605 | template <bool opt> |
---|
606 | struct filler |
---|
607 | { |
---|
608 | template <typename I, typename T> |
---|
609 | static void do_fill(I first, I last, typename boost::call_traits<T>::param_type val); |
---|
610 | { |
---|
611 | while(first != last) |
---|
612 | { |
---|
613 | *first = val; |
---|
614 | ++first; |
---|
615 | } |
---|
616 | } |
---|
617 | }; |
---|
618 | |
---|
619 | template <> |
---|
620 | struct filler<true> |
---|
621 | { |
---|
622 | template <typename I, typename T> |
---|
623 | static void do_fill(I first, I last, T val) |
---|
624 | { |
---|
625 | memset(first, val, last-first); |
---|
626 | } |
---|
627 | }; |
---|
628 | |
---|
629 | } |
---|
630 | |
---|
631 | template <class I, class T> |
---|
632 | inline void fill(I first, I last, const T& val) |
---|
633 | { |
---|
634 | enum{ can_opt = boost::is_pointer<I>::value |
---|
635 | && boost::is_arithmetic<T>::value |
---|
636 | && (sizeof(T) == 1) }; |
---|
637 | typedef detail::filler<can_opt> filler_t; |
---|
638 | filler_t::template do_fill<I,T>(first, last, val); |
---|
639 | }</pre> |
---|
640 | |
---|
641 | <p>Footnote: the reason that this is "optimal" for |
---|
642 | small built-in types is that with the value passed as "T |
---|
643 | const" instead of "const T&" the compiler is |
---|
644 | able to tell both that the value is constant and that it is free |
---|
645 | of aliases. With this information the compiler is able to cache |
---|
646 | the passed value in a register, unroll the loop, or use |
---|
647 | explicitly parallel instructions: if any of these are supported. |
---|
648 | Exactly how much mileage you will get from this depends upon your |
---|
649 | compiler - we could really use some accurate benchmarking |
---|
650 | software as part of boost for cases like this.</p> |
---|
651 | |
---|
652 | <p>Note that the function arguments to fill are not expressed in |
---|
653 | terms of call_traits: doing so would prevent template argument |
---|
654 | deduction from functioning. Instead fill acts as a "thin |
---|
655 | wrapper" that is there to perform template argument |
---|
656 | deduction, the compiler will optimise away the call to fill all |
---|
657 | together, replacing it with the call to filler<>::do_fill, |
---|
658 | which does use call_traits.</p> |
---|
659 | |
---|
660 | <h3>Rationale</h3> |
---|
661 | |
---|
662 | <p>The following notes are intended to briefly describe the |
---|
663 | rational behind choices made in call_traits.</p> |
---|
664 | |
---|
665 | <p>All user-defined types follow "existing practice" |
---|
666 | and need no comment.</p> |
---|
667 | |
---|
668 | <p>Small built-in types (what the standard calls fundamental |
---|
669 | types [3.9.1]) differ from existing practice only in the <i>param_type</i> |
---|
670 | typedef. In this case passing "T const" is compatible |
---|
671 | with existing practice, but may improve performance in some cases |
---|
672 | (see <a href="#ex4">Example 4</a>), in any case this should never |
---|
673 | be any worse than existing practice.</p> |
---|
674 | |
---|
675 | <p>Pointers follow the same rational as small built-in types.</p> |
---|
676 | |
---|
677 | <p>For reference types the rational follows <a href="#refs">Example |
---|
678 | 2</a> - references to references are not allowed, so the |
---|
679 | call_traits members must be defined such that these problems do |
---|
680 | not occur. There is a proposal to modify the language such that |
---|
681 | "a reference to a reference is a reference" (issue #106, |
---|
682 | submitted by Bjarne Stroustrup), call_traits<T>::value_type |
---|
683 | and call_traits<T>::param_type both provide the same effect |
---|
684 | as that proposal, without the need for a language change (in |
---|
685 | other words it's a workaround).</p> |
---|
686 | |
---|
687 | <p>For array types, a function that takes an array as an argument |
---|
688 | will degrade the array type to a pointer type: this means that |
---|
689 | the type of the actual parameter is different from its declared |
---|
690 | type, something that can cause endless problems in template code |
---|
691 | that relies on the declared type of a parameter. For example:</p> |
---|
692 | |
---|
693 | <pre>template <class T> |
---|
694 | struct A |
---|
695 | { |
---|
696 | void foo(T t); |
---|
697 | };</pre> |
---|
698 | |
---|
699 | <p><font face="Times New Roman">In this case if we instantiate |
---|
700 | A<int[2]> then the declared type of the parameter passed to |
---|
701 | member function foo is int[2], but it's actual type is const int*, |
---|
702 | if we try to use the type T within the function body, then there |
---|
703 | is a strong likelyhood that our code will not compile:</font></p> |
---|
704 | |
---|
705 | <pre>template <class T> |
---|
706 | void A<T>::foo(T t) |
---|
707 | { |
---|
708 | T dup(t); // doesn't compile for case that T is an array. |
---|
709 | }</pre> |
---|
710 | |
---|
711 | <p>By using call_traits the degradation from array to pointer is |
---|
712 | explicit, and the type of the parameter is the same as it's |
---|
713 | declared type:</p> |
---|
714 | |
---|
715 | <pre>template <class T> |
---|
716 | struct A |
---|
717 | { |
---|
718 | void foo(typename call_traits<T>::value_type t); |
---|
719 | }; |
---|
720 | |
---|
721 | template <class T> |
---|
722 | void A<T>::foo(typename call_traits<T>::value_type t) |
---|
723 | { |
---|
724 | typename call_traits<T>::value_type dup(t); // OK even if T is an array type. |
---|
725 | }</pre> |
---|
726 | |
---|
727 | <p>For value_type (return by value), again only a pointer may be |
---|
728 | returned, not a copy of the whole array, and again call_traits |
---|
729 | makes the degradation explicit. The value_type member is useful |
---|
730 | whenever an array must be explicitly degraded to a pointer - <a |
---|
731 | href="#ex3">Example 3</a> provides the test case (Footnote: the |
---|
732 | array specialisation for call_traits is the least well understood |
---|
733 | of all the call_traits specialisations, if the given semantics |
---|
734 | cause specific problems for you, or don't solve a particular |
---|
735 | array-related problem, then I would be interested to hear about |
---|
736 | it. Most people though will probably never need to use this |
---|
737 | specialisation).</p> |
---|
738 | |
---|
739 | <hr> |
---|
740 | |
---|
741 | <p>Revised 01 September 2000</p> |
---|
742 | |
---|
743 | <p>© Copyright boost.org 2000. Permission to copy, use, modify, |
---|
744 | sell and distribute this document is granted provided this |
---|
745 | copyright notice appears in all copies. This document is provided |
---|
746 | "as is" without express or implied warranty, and with |
---|
747 | no claim as to its suitability for any purpose.</p> |
---|
748 | |
---|
749 | <p>Based on contributions by Steve Cleary, Beman Dawes, Howard |
---|
750 | Hinnant and John Maddock.</p> |
---|
751 | |
---|
752 | <p>Maintained by <a href="mailto:john@johnmaddock.co.uk">John |
---|
753 | Maddock</a>, the latest version of this file can be found at <a |
---|
754 | href="http://www.boost.org/">www.boost.org</a>, and the boost |
---|
755 | discussion list at <a |
---|
756 | href="http://www.yahoogroups.com/list/boost">www.yahoogroups.com/list/boost</a>.</p> |
---|
757 | |
---|
758 | <p>.</p> |
---|
759 | |
---|
760 | <p> </p> |
---|
761 | |
---|
762 | <p> </p> |
---|
763 | </body> |
---|
764 | </html> |
---|