| <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="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> |
| |