[12] | 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> |
---|