123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755 |
- <html>
- <head>
- <meta http-equiv="Content-Type"
- content="text/html; charset=iso-8859-1">
- <meta name="Template"
- content="C:\PROGRAM FILES\MICROSOFT OFFICE\OFFICE\html.dot">
- <meta name="GENERATOR" content="Microsoft FrontPage Express 2.0">
- <title>Call Traits</title>
- </head>
- <body bgcolor="#FFFFFF" text="#000000" link="#0000FF"
- vlink="#800080">
- <h1><img src="../../boost.png" width="276" height="86">Header
- <<a href="../../boost/detail/call_traits.hpp">boost/call_traits.hpp</a>></h1>
- <p>All of the contents of <boost/call_traits.hpp> are
- defined inside namespace boost.</p>
- <p>The template class call_traits<T> encapsulates the
- "best" method to pass a parameter of some type T to or
- from a function, and consists of a collection of typedefs defined
- as in the table below. The purpose of call_traits is to ensure
- that problems like "<a href="#refs">references to references</a>"
- never occur, and that parameters are passed in the most efficient
- manner possible (see <a href="#examples">examples</a>). In each
- case if your existing practice is to use the type defined on the
- left, then replace it with the call_traits defined type on the
- right. </p>
- <p>Note that for compilers that do not support either partial
- specialization or member templates, no benefit will occur from
- using call_traits: the call_traits defined types will always be
- the same as the existing practice in this case. In addition if
- only member templates and not partial template specialisation is
- support by the compiler (for example Visual C++ 6) then
- call_traits can not be used with array types (although it can be
- used to solve the reference to reference problem).</p>
- <table border="0" cellpadding="7" cellspacing="1" width="797">
- <tr>
- <td valign="top" width="17%" bgcolor="#008080"><p
- align="center">Existing practice</p>
- </td>
- <td valign="top" width="35%" bgcolor="#008080"><p
- align="center">call_traits equivalent</p>
- </td>
- <td valign="top" width="32%" bgcolor="#008080"><p
- align="center">Description</p>
- </td>
- <td valign="top" width="16%" bgcolor="#008080"><p
- align="center">Notes</p>
- </td>
- </tr>
- <tr>
- <td valign="top" width="17%"><p align="center">T<br>
- (return by value)</p>
- </td>
- <td valign="top" width="35%"><p align="center"><code>call_traits<T>::value_type</code></p>
- </td>
- <td valign="top" width="32%">Defines a type that
- represents the "value" of type T. Use this for
- functions that return by value, or possibly for stored
- values of type T.</td>
- <td valign="top" width="16%"><p align="center">2</p>
- </td>
- </tr>
- <tr>
- <td valign="top" width="17%"><p align="center">T&<br>
- (return value)</p>
- </td>
- <td valign="top" width="35%"><p align="center"><code>call_traits<T>::reference</code></p>
- </td>
- <td valign="top" width="32%">Defines a type that
- represents a reference to type T. Use for functions that
- would normally return a T&.</td>
- <td valign="top" width="16%"><p align="center">1</p>
- </td>
- </tr>
- <tr>
- <td valign="top" width="17%"><p align="center">const
- T&<br>
- (return value)</p>
- </td>
- <td valign="top" width="35%"><p align="center"><code>call_traits<T>::const_reference</code></p>
- </td>
- <td valign="top" width="32%">Defines a type that
- represents a constant reference to type T. Use for
- functions that would normally return a const T&.</td>
- <td valign="top" width="16%"><p align="center">1</p>
- </td>
- </tr>
- <tr>
- <td valign="top" width="17%"><p align="center">const
- T&<br>
- (function parameter)</p>
- </td>
- <td valign="top" width="35%"><p align="center"><code>call_traits<T>::param_type</code></p>
- </td>
- <td valign="top" width="32%">Defines a type that
- represents the "best" way to pass a parameter
- of type T to a function.</td>
- <td valign="top" width="16%"><p align="center">1,3</p>
- </td>
- </tr>
- </table>
- <p>Notes:</p>
- <ol>
- <li>If T is already reference type, then call_traits is
- defined such that <a href="#refs">references to
- references</a> do not occur (requires partial
- specialization).</li>
- <li>If T is an array type, then call_traits defines <code>value_type</code>
- as a "constant pointer to type" rather than an
- "array of type" (requires partial
- specialization). Note that if you are using value_type as
- a stored value then this will result in storing a "constant
- pointer to an array" rather than the array itself.
- This may or may not be a good thing depending upon what
- you actually need (in other words take care!).</li>
- <li>If T is a small built in type or a pointer, then <code>param_type</code>
- is defined as <code>T const</code>, instead of <code>T
- const&</code>. This can improve the ability of the
- compiler to optimize loops in the body of the function if
- they depend upon the passed parameter, the semantics of
- the passed parameter is otherwise unchanged (requires
- partial specialization).</li>
- </ol>
- <p> </p>
- <h3>Copy constructibility</h3>
- <p>The following table defines which call_traits types can always
- be copy-constructed from which other types, those entries marked
- with a '?' are true only if and only if T is copy constructible:</p>
- <table border="0" cellpadding="7" cellspacing="1" width="766">
- <tr>
- <td valign="top" width="17%"> </td>
- <td valign="top" colspan="5" width="85%"
- bgcolor="#008080"><p align="center">To:</p>
- </td>
- </tr>
- <tr>
- <td valign="top" width="17%" bgcolor="#008080">From:</td>
- <td valign="top" width="17%" bgcolor="#C0C0C0"><p
- align="center">T</p>
- </td>
- <td valign="top" width="17%" bgcolor="#C0C0C0"><p
- align="center">value_type</p>
- </td>
- <td valign="top" width="17%" bgcolor="#C0C0C0"><p
- align="center">reference</p>
- </td>
- <td valign="top" width="17%" bgcolor="#C0C0C0"><p
- align="center">const_reference</p>
- </td>
- <td valign="top" width="17%" bgcolor="#C0C0C0"><p
- align="center">param_type</p>
- </td>
- </tr>
- <tr>
- <td valign="top" width="17%" bgcolor="#C0C0C0">T</td>
- <td valign="top" width="17%"><p align="center">?</p>
- </td>
- <td valign="top" width="17%"><p align="center">?</p>
- </td>
- <td valign="top" width="17%"><p align="center">Y</p>
- </td>
- <td valign="top" width="17%"><p align="center">Y</p>
- </td>
- <td valign="top" width="17%"><p align="center">Y</p>
- </td>
- </tr>
- <tr>
- <td valign="top" width="17%" bgcolor="#C0C0C0">value_type</td>
- <td valign="top" width="17%"><p align="center">?</p>
- </td>
- <td valign="top" width="17%"><p align="center">?</p>
- </td>
- <td valign="top" width="17%"><p align="center">N</p>
- </td>
- <td valign="top" width="17%"><p align="center">N</p>
- </td>
- <td valign="top" width="17%"><p align="center">Y</p>
- </td>
- </tr>
- <tr>
- <td valign="top" width="17%" bgcolor="#C0C0C0">reference</td>
- <td valign="top" width="17%"><p align="center">?</p>
- </td>
- <td valign="top" width="17%"><p align="center">?</p>
- </td>
- <td valign="top" width="17%"><p align="center">Y</p>
- </td>
- <td valign="top" width="17%"><p align="center">Y</p>
- </td>
- <td valign="top" width="17%"><p align="center">Y</p>
- </td>
- </tr>
- <tr>
- <td valign="top" width="17%" bgcolor="#C0C0C0">const_reference</td>
- <td valign="top" width="17%"><p align="center">?</p>
- </td>
- <td valign="top" width="17%"><p align="center">N</p>
- </td>
- <td valign="top" width="17%"><p align="center">N</p>
- </td>
- <td valign="top" width="17%"><p align="center">Y</p>
- </td>
- <td valign="top" width="17%"><p align="center">Y</p>
- </td>
- </tr>
- <tr>
- <td valign="top" width="17%" bgcolor="#C0C0C0">param_type</td>
- <td valign="top" width="17%"><p align="center">?</p>
- </td>
- <td valign="top" width="17%"><p align="center">?</p>
- </td>
- <td valign="top" width="17%"><p align="center">N</p>
- </td>
- <td valign="top" width="17%"><p align="center">N</p>
- </td>
- <td valign="top" width="17%"><p align="center">Y</p>
- </td>
- </tr>
- </table>
- <p> </p>
- <p>If T is an assignable type the following assignments are
- possible:</p>
- <table border="0" cellpadding="7" cellspacing="1" width="766">
- <tr>
- <td valign="top" width="17%"> </td>
- <td valign="top" colspan="5" width="85%"
- bgcolor="#008080"><p align="center">To:</p>
- </td>
- </tr>
- <tr>
- <td valign="top" width="17%" bgcolor="#008080">From:</td>
- <td valign="top" width="17%" bgcolor="#C0C0C0"><p
- align="center">T</p>
- </td>
- <td valign="top" width="17%" bgcolor="#C0C0C0"><p
- align="center">value_type</p>
- </td>
- <td valign="top" width="17%" bgcolor="#C0C0C0"><p
- align="center">reference</p>
- </td>
- <td valign="top" width="17%" bgcolor="#C0C0C0"><p
- align="center">const_reference</p>
- </td>
- <td valign="top" width="17%" bgcolor="#C0C0C0"><p
- align="center">param_type</p>
- </td>
- </tr>
- <tr>
- <td valign="top" width="17%" bgcolor="#C0C0C0">T</td>
- <td valign="top" width="17%"><p align="center">Y</p>
- </td>
- <td valign="top" width="17%"><p align="center">Y</p>
- </td>
- <td valign="top" width="17%"><p align="center">-</p>
- </td>
- <td valign="top" width="17%"><p align="center">-</p>
- </td>
- <td valign="top" width="17%"><p align="center">-</p>
- </td>
- </tr>
- <tr>
- <td valign="top" width="17%" bgcolor="#C0C0C0">value_type</td>
- <td valign="top" width="17%"><p align="center">Y</p>
- </td>
- <td valign="top" width="17%"><p align="center">Y</p>
- </td>
- <td valign="top" width="17%"><p align="center">-</p>
- </td>
- <td valign="top" width="17%"><p align="center">-</p>
- </td>
- <td valign="top" width="17%"><p align="center">-</p>
- </td>
- </tr>
- <tr>
- <td valign="top" width="17%" bgcolor="#C0C0C0">reference</td>
- <td valign="top" width="17%"><p align="center">Y</p>
- </td>
- <td valign="top" width="17%"><p align="center">Y</p>
- </td>
- <td valign="top" width="17%"><p align="center">-</p>
- </td>
- <td valign="top" width="17%"><p align="center">-</p>
- </td>
- <td valign="top" width="17%"><p align="center">-</p>
- </td>
- </tr>
- <tr>
- <td valign="top" width="17%" bgcolor="#C0C0C0">const_reference</td>
- <td valign="top" width="17%"><p align="center">Y</p>
- </td>
- <td valign="top" width="17%"><p align="center">Y</p>
- </td>
- <td valign="top" width="17%"><p align="center">-</p>
- </td>
- <td valign="top" width="17%"><p align="center">-</p>
- </td>
- <td valign="top" width="17%"><p align="center">-</p>
- </td>
- </tr>
- <tr>
- <td valign="top" width="17%" bgcolor="#C0C0C0">param_type</td>
- <td valign="top" width="17%"><p align="center">Y</p>
- </td>
- <td valign="top" width="17%"><p align="center">Y</p>
- </td>
- <td valign="top" width="17%"><p align="center">-</p>
- </td>
- <td valign="top" width="17%"><p align="center">-</p>
- </td>
- <td valign="top" width="17%"><p align="center">-</p>
- </td>
- </tr>
- </table>
- <p> </p>
- <h3><a name="examples"></a>Examples</h3>
- <p>The following table shows the effect that call_traits has on
- various types, the table assumes that the compiler supports
- partial specialization: if it doesn't then all types behave in
- the same way as the entry for "myclass", and
- call_traits can not be used with reference or array types.</p>
- <table border="0" cellpadding="7" cellspacing="1" width="766">
- <tr>
- <td valign="top" width="17%"> </td>
- <td valign="top" colspan="5" width="85%"
- bgcolor="#008080"><p align="center">Call_traits type:</p>
- </td>
- </tr>
- <tr>
- <td valign="top" width="17%" bgcolor="#008080"><p
- align="center">Original type T</p>
- </td>
- <td valign="top" width="17%" bgcolor="#C0C0C0"><p
- align="center">value_type</p>
- </td>
- <td valign="top" width="17%" bgcolor="#C0C0C0"><p
- align="center">reference</p>
- </td>
- <td valign="top" width="17%" bgcolor="#C0C0C0"><p
- align="center">const_reference</p>
- </td>
- <td valign="top" width="17%" bgcolor="#C0C0C0"><p
- align="center">param_type</p>
- </td>
- <td valign="top" width="17%" bgcolor="#C0C0C0"><p
- align="center">Applies to:</p>
- </td>
- </tr>
- <tr>
- <td valign="top" width="17%" bgcolor="#C0C0C0"><p
- align="center">myclass</p>
- </td>
- <td valign="top" width="17%"><p align="center">myclass</p>
- </td>
- <td valign="top" width="17%"><p align="center">myclass&</p>
- </td>
- <td valign="top" width="17%"><p align="center">const
- myclass&</p>
- </td>
- <td valign="top" width="17%"><p align="center">myclass
- const&</p>
- </td>
- <td valign="top" width="17%"><p align="center">All user
- defined types.</p>
- </td>
- </tr>
- <tr>
- <td valign="top" width="17%" bgcolor="#C0C0C0"><p
- align="center">int</p>
- </td>
- <td valign="top" width="17%"><p align="center">int</p>
- </td>
- <td valign="top" width="17%"><p align="center">int&</p>
- </td>
- <td valign="top" width="17%"><p align="center">const
- int&</p>
- </td>
- <td valign="top" width="17%"><p align="center">int const</p>
- </td>
- <td valign="top" width="17%"><p align="center">All small
- built-in types.</p>
- </td>
- </tr>
- <tr>
- <td valign="top" width="17%" bgcolor="#C0C0C0"><p
- align="center">int*</p>
- </td>
- <td valign="top" width="17%"><p align="center">int*</p>
- </td>
- <td valign="top" width="17%"><p align="center">int*&</p>
- </td>
- <td valign="top" width="17%"><p align="center">int*const&</p>
- </td>
- <td valign="top" width="17%"><p align="center">int* const</p>
- </td>
- <td valign="top" width="17%"><p align="center">All
- pointer types.</p>
- </td>
- </tr>
- <tr>
- <td valign="top" width="17%" bgcolor="#C0C0C0"><p
- align="center">int&</p>
- </td>
- <td valign="top" width="17%"><p align="center">int&</p>
- </td>
- <td valign="top" width="17%"><p align="center">int&</p>
- </td>
- <td valign="top" width="17%"><p align="center">const
- int&</p>
- </td>
- <td valign="top" width="17%"><p align="center">int&</p>
- </td>
- <td valign="top" width="17%"><p align="center">All
- reference types.</p>
- </td>
- </tr>
- <tr>
- <td valign="top" width="17%" bgcolor="#C0C0C0"><p
- align="center">const int&</p>
- </td>
- <td valign="top" width="17%"><p align="center">const
- int&</p>
- </td>
- <td valign="top" width="17%"><p align="center">const
- int&</p>
- </td>
- <td valign="top" width="17%"><p align="center">const
- int&</p>
- </td>
- <td valign="top" width="17%"><p align="center">const
- int&</p>
- </td>
- <td valign="top" width="17%"><p align="center">All
- constant-references.</p>
- </td>
- </tr>
- <tr>
- <td valign="top" width="17%" bgcolor="#C0C0C0"><p
- align="center">int[3]</p>
- </td>
- <td valign="top" width="17%"><p align="center">const int*</p>
- </td>
- <td valign="top" width="17%"><p align="center">int(&)[3]</p>
- </td>
- <td valign="top" width="17%"><p align="center">const int(&)[3]</p>
- </td>
- <td valign="top" width="17%"><p align="center">const int*
- const</p>
- </td>
- <td valign="top" width="17%"><p align="center">All array
- types.</p>
- </td>
- </tr>
- <tr>
- <td valign="top" width="17%" bgcolor="#C0C0C0"><p
- align="center">const int[3]</p>
- </td>
- <td valign="top" width="17%"><p align="center">const int*</p>
- </td>
- <td valign="top" width="17%"><p align="center">const int(&)[3]</p>
- </td>
- <td valign="top" width="17%"><p align="center">const int(&)[3]</p>
- </td>
- <td valign="top" width="17%"><p align="center">const int*
- const</p>
- </td>
- <td valign="top" width="17%"><p align="center">All
- constant-array types.</p>
- </td>
- </tr>
- </table>
- <p> </p>
- <h4>Example 1:</h4>
- <p>The following class is a trivial class that stores some type T
- by value (see the <a href="test/call_traits_test.cpp">call_traits_test.cpp</a>
- file), the aim is to illustrate how each of the available
- call_traits typedefs may be used:</p>
- <pre>template <class T>
- struct contained
- {
- // define our typedefs first, arrays are stored by value
- // so value_type is not the same as result_type:
- typedef typename boost::call_traits<T>::param_type param_type;
- typedef typename boost::call_traits<T>::reference reference;
- typedef typename boost::call_traits<T>::const_reference const_reference;
- typedef T value_type;
- typedef typename boost::call_traits<T>::value_type result_type;
- // stored value:
- value_type v_;
-
- // constructors:
- contained() {}
- contained(param_type p) : v_(p){}
- // return byval:
- result_type value() { return v_; }
- // return by_ref:
- reference get() { return v_; }
- const_reference const_get()const { return v_; }
- // pass value:
- void call(param_type p){}
- };</pre>
- <h4><a name="refs"></a>Example 2 (the reference to reference
- problem):</h4>
- <p>Consider the definition of std::binder1st:</p>
- <pre>template <class Operation>
- class binder1st :
- public unary_function<typename Operation::second_argument_type, typename Operation::result_type>
- {
- protected:
- Operation op;
- typename Operation::first_argument_type value;
- public:
- binder1st(const Operation& x, const typename Operation::first_argument_type& y);
- typename Operation::result_type operator()(const typename Operation::second_argument_type& x) const;
- }; </pre>
- <p>Now consider what happens in the relatively common case that
- the functor takes its second argument as a reference, that
- implies that <code>Operation::second_argument_type</code> is a
- reference type, <code>operator()</code> will now end up taking a
- reference to a reference as an argument, and that is not
- currently legal. The solution here is to modify <code>operator()</code>
- to use call_traits:</p>
- <pre>typename Operation::result_type operator()(typename call_traits<typename Operation::second_argument_type>::param_type x) const;</pre>
- <p>Now in the case that <code>Operation::second_argument_type</code>
- is a reference type, the argument is passed as a reference, and
- the no "reference to reference" occurs.</p>
- <h4><a name="ex3"></a>Example 3 (the make_pair problem):</h4>
- <p>If we pass the name of an array as one (or both) arguments to <code>std::make_pair</code>,
- then template argument deduction deduces the passed parameter as
- "const reference to array of T", this also applies to
- string literals (which are really array literals). Consequently
- instead of returning a pair of pointers, it tries to return a
- pair of arrays, and since an array type is not copy-constructible
- the code fails to compile. One solution is to explicitly cast the
- arguments to make_pair to pointers, but call_traits provides a
- better (i.e. automatic) solution (and one that works safely even
- in generic code where the cast might do the wrong thing):</p>
- <pre>template <class T1, class T2>
- std::pair<
- typename boost::call_traits<T1>::value_type,
- typename boost::call_traits<T2>::value_type>
- make_pair(const T1& t1, const T2& t2)
- {
- return std::pair<
- typename boost::call_traits<T1>::value_type,
- typename boost::call_traits<T2>::value_type>(t1, t2);
- }</pre>
- <p>Here, the deduced argument types will be automatically
- degraded to pointers if the deduced types are arrays, similar
- situations occur in the standard binders and adapters: in
- principle in any function that "wraps" a temporary
- whose type is deduced. Note that the function arguments to
- make_pair are not expressed in terms of call_traits: doing so
- would prevent template argument deduction from functioning.</p>
- <h4><a name="ex4"></a>Example 4 (optimising fill):</h4>
- <p>The call_traits template will "optimize" the passing
- of a small built-in type as a function parameter, this mainly has
- an effect when the parameter is used within a loop body. In the
- following example (see <a
- href="../type_traits/examples/fill_example.cpp">fill_example.cpp</a>),
- a version of std::fill is optimized in two ways: if the type
- passed is a single byte built-in type then std::memset is used to
- effect the fill, otherwise a conventional C++ implemention is
- used, but with the passed parameter "optimized" using
- call_traits:</p>
- <pre>namespace detail{
- template <bool opt>
- struct filler
- {
- template <typename I, typename T>
- static void do_fill(I first, I last, typename boost::call_traits<T>::param_type val)
- {
- while(first != last)
- {
- *first = val;
- ++first;
- }
- }
- };
- template <>
- struct filler<true>
- {
- template <typename I, typename T>
- static void do_fill(I first, I last, T val)
- {
- memset(first, val, last-first);
- }
- };
- }
- template <class I, class T>
- inline void fill(I first, I last, const T& val)
- {
- enum{ can_opt = boost::is_pointer<I>::value
- && boost::is_arithmetic<T>::value
- && (sizeof(T) == 1) };
- typedef detail::filler<can_opt> filler_t;
- filler_t::template do_fill<I,T>(first, last, val);
- }</pre>
- <p>Footnote: the reason that this is "optimal" for
- small built-in types is that with the value passed as "T
- const" instead of "const T&" the compiler is
- able to tell both that the value is constant and that it is free
- of aliases. With this information the compiler is able to cache
- the passed value in a register, unroll the loop, or use
- explicitly parallel instructions: if any of these are supported.
- Exactly how much mileage you will get from this depends upon your
- compiler - we could really use some accurate benchmarking
- software as part of boost for cases like this.</p>
- <p>Note that the function arguments to fill are not expressed in
- terms of call_traits: doing so would prevent template argument
- deduction from functioning. Instead fill acts as a "thin
- wrapper" that is there to perform template argument
- deduction, the compiler will optimise away the call to fill all
- together, replacing it with the call to filler<>::do_fill,
- which does use call_traits.</p>
- <h3>Rationale</h3>
- <p>The following notes are intended to briefly describe the
- rational behind choices made in call_traits.</p>
- <p>All user-defined types follow "existing practice"
- and need no comment.</p>
- <p>Small built-in types (what the standard calls fundamental
- types [3.9.1]) differ from existing practice only in the <i>param_type</i>
- typedef. In this case passing "T const" is compatible
- with existing practice, but may improve performance in some cases
- (see <a href="#ex4">Example 4</a>), in any case this should never
- be any worse than existing practice.</p>
- <p>Pointers follow the same rational as small built-in types.</p>
- <p>For reference types the rational follows <a href="#refs">Example
- 2</a> - references to references are not allowed, so the
- call_traits members must be defined such that these problems do
- not occur. There is a proposal to modify the language such that
- "a reference to a reference is a reference" (issue #106,
- submitted by Bjarne Stroustrup), call_traits<T>::value_type
- and call_traits<T>::param_type both provide the same effect
- as that proposal, without the need for a language change (in
- other words it's a workaround).</p>
- <p>For array types, a function that takes an array as an argument
- will degrade the array type to a pointer type: this means that
- the type of the actual parameter is different from its declared
- type, something that can cause endless problems in template code
- that relies on the declared type of a parameter. For example:</p>
- <pre>template <class T>
- struct A
- {
- void foo(T t);
- };</pre>
- <p><font face="Times New Roman">In this case if we instantiate
- A<int[2]> then the declared type of the parameter passed to
- member function foo is int[2], but it's actual type is const int*,
- if we try to use the type T within the function body, then there
- is a strong likelyhood that our code will not compile:</font></p>
- <pre>template <class T>
- void A<T>::foo(T t)
- {
- T dup(t); // doesn't compile for case that T is an array.
- }</pre>
- <p>By using call_traits the degradation from array to pointer is
- explicit, and the type of the parameter is the same as it's
- declared type:</p>
- <pre>template <class T>
- struct A
- {
- void foo(typename call_traits<T>::value_type t);
- };
- template <class T>
- void A<T>::foo(typename call_traits<T>::value_type t)
- {
- typename call_traits<T>::value_type dup(t); // OK even if T is an array type.
- }</pre>
- <p>For value_type (return by value), again only a pointer may be
- returned, not a copy of the whole array, and again call_traits
- makes the degradation explicit. The value_type member is useful
- whenever an array must be explicitly degraded to a pointer - <a
- href="#ex3">Example 3</a> provides the test case (Footnote: the
- array specialisation for call_traits is the least well understood
- of all the call_traits specialisations, if the given semantics
- cause specific problems for you, or don't solve a particular
- array-related problem, then I would be interested to hear about
- it. Most people though will probably never need to use this
- specialisation).</p>
- <hr>
- <p>Revised 01 September 2000</p>
- <p>
- Copyright 2000 Steve Cleary, Beman Dawes, Howard
- Hinnant and John Maddock. <br/>
- Use, modification and distribution are subject to the
- Boost Software License, Version 1.0.
- (See accompanying file LICENSE_1_0.txt
- or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">
- http://www.boost.org/LICENSE_1_0.txt
- </a>).
- </p>
- </body>
- </html>
|