1<html> 2 3<head> 4<meta http-equiv="Content-Type" 5content="text/html; charset=iso-8859-1"> 6<meta name="Template" 7content="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" 13vlink="#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 19defined 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 23from a function, and consists of a collection of typedefs defined 24as in the table below. The purpose of call_traits is to ensure 25that problems like "<a href="#refs">references to references</a>" 26never occur, and that parameters are passed in the most efficient 27manner possible (see <a href="#examples">examples</a>). In each 28case if your existing practice is to use the type defined on the 29left, then replace it with the call_traits defined type on the 30right. </p> 31 32<p>Note that for compilers that do not support either partial 33specialization or member templates, no benefit will occur from 34using call_traits: the call_traits defined types will always be 35the same as the existing practice in this case. In addition if 36only member templates and not partial template specialisation is 37support by the compiler (for example Visual C++ 6) then 38call_traits can not be used with array types (although it can be 39used 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 138be copy-constructed from which other types, those entries marked 139with 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 236possible:</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 335various types, the table assumes that the compiler supports 336partial specialization: if it doesn't then all types behave in 337the same way as the entry for "myclass", and 338call_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 496by value (see the <a href="test/call_traits_test.cpp">call_traits_test.cpp</a> 497file), the aim is to illustrate how each of the available 498call_traits typedefs may be used:</p> 499 500<pre>template <class T> 501struct 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 528problem):</h4> 529 530<p>Consider the definition of std::binder1st:</p> 531 532<pre>template <class Operation> 533class binder1st : 534 public unary_function<typename Operation::second_argument_type, typename Operation::result_type> 535{ 536protected: 537 Operation op; 538 typename Operation::first_argument_type value; 539public: 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 545the functor takes its second argument as a reference, that 546implies that <code>Operation::second_argument_type</code> is a 547reference type, <code>operator()</code> will now end up taking a 548reference to a reference as an argument, and that is not 549currently legal. The solution here is to modify <code>operator()</code> 550to 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> 555is a reference type, the argument is passed as a reference, and 556the 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>, 561then template argument deduction deduces the passed parameter as 562"const reference to array of T", this also applies to 563string literals (which are really array literals). Consequently 564instead of returning a pair of pointers, it tries to return a 565pair of arrays, and since an array type is not copy-constructible 566the code fails to compile. One solution is to explicitly cast the 567arguments to make_pair to pointers, but call_traits provides a 568better (i.e. automatic) solution (and one that works safely even 569in generic code where the cast might do the wrong thing):</p> 570 571<pre>template <class T1, class T2> 572std::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 583degraded to pointers if the deduced types are arrays, similar 584situations occur in the standard binders and adapters: in 585principle in any function that "wraps" a temporary 586whose type is deduced. Note that the function arguments to 587make_pair are not expressed in terms of call_traits: doing so 588would 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 593of a small built-in type as a function parameter, this mainly has 594an effect when the parameter is used within a loop body. In the 595following example (see <a 596href="../type_traits/examples/fill_example.cpp">fill_example.cpp</a>), 597a version of std::fill is optimized in two ways: if the type 598passed is a single byte built-in type then std::memset is used to 599effect the fill, otherwise a conventional C++ implemention is 600used, but with the passed parameter "optimized" using 601call_traits:</p> 602 603<pre>namespace detail{ 604 605template <bool opt> 606struct 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 619template <> 620struct 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 631template <class I, class T> 632inline 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 642small built-in types is that with the value passed as "T 643const" instead of "const T&" the compiler is 644able to tell both that the value is constant and that it is free 645of aliases. With this information the compiler is able to cache 646the passed value in a register, unroll the loop, or use 647explicitly parallel instructions: if any of these are supported. 648Exactly how much mileage you will get from this depends upon your 649compiler - we could really use some accurate benchmarking 650software as part of boost for cases like this.</p> 651 652<p>Note that the function arguments to fill are not expressed in 653terms of call_traits: doing so would prevent template argument 654deduction from functioning. Instead fill acts as a "thin 655wrapper" that is there to perform template argument 656deduction, the compiler will optimise away the call to fill all 657together, replacing it with the call to filler<>::do_fill, 658which does use call_traits.</p> 659 660<h3>Rationale</h3> 661 662<p>The following notes are intended to briefly describe the 663rational behind choices made in call_traits.</p> 664 665<p>All user-defined types follow "existing practice" 666and need no comment.</p> 667 668<p>Small built-in types (what the standard calls fundamental 669types [3.9.1]) differ from existing practice only in the <i>param_type</i> 670typedef. In this case passing "T const" is compatible 671with existing practice, but may improve performance in some cases 672(see <a href="#ex4">Example 4</a>), in any case this should never 673be 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 6782</a> - references to references are not allowed, so the 679call_traits members must be defined such that these problems do 680not occur. There is a proposal to modify the language such that 681"a reference to a reference is a reference" (issue #106, 682submitted by Bjarne Stroustrup), call_traits<T>::value_type 683and call_traits<T>::param_type both provide the same effect 684as that proposal, without the need for a language change (in 685other words it's a workaround).</p> 686 687<p>For array types, a function that takes an array as an argument 688will degrade the array type to a pointer type: this means that 689the type of the actual parameter is different from its declared 690type, something that can cause endless problems in template code 691that relies on the declared type of a parameter. For example:</p> 692 693<pre>template <class T> 694struct A 695{ 696 void foo(T t); 697};</pre> 698 699<p><font face="Times New Roman">In this case if we instantiate 700A<int[2]> then the declared type of the parameter passed to 701member function foo is int[2], but it's actual type is const int*, 702if we try to use the type T within the function body, then there 703is a strong likelyhood that our code will not compile:</font></p> 704 705<pre>template <class T> 706void 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 712explicit, and the type of the parameter is the same as it's 713declared type:</p> 714 715<pre>template <class T> 716struct A 717{ 718 void foo(typename call_traits<T>::value_type t); 719}; 720 721template <class T> 722void 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 728returned, not a copy of the whole array, and again call_traits 729makes the degradation explicit. The value_type member is useful 730whenever an array must be explicitly degraded to a pointer - <a 731href="#ex3">Example 3</a> provides the test case (Footnote: the 732array specialisation for call_traits is the least well understood 733of all the call_traits specialisations, if the given semantics 734cause specific problems for you, or don't solve a particular 735array-related problem, then I would be interested to hear about 736it. Most people though will probably never need to use this 737specialisation).</p> 738 739<hr> 740 741<p>Revised 01 September 2000</p> 742 743 <p> 744 Copyright 2000 Steve Cleary, Beman Dawes, Howard 745 Hinnant and John Maddock. <br/> 746 Use, modification and distribution are subject to the 747 Boost Software License, Version 1.0. 748 (See accompanying file LICENSE_1_0.txt 749 or copy at <a href="http://www.boost.org/LICENSE_1_0.txt"> 750 http://www.boost.org/LICENSE_1_0.txt 751 </a>). 752 </p> 753</body> 754</html> 755 756