| <html> | |
| <head> | |
| <meta http-equiv="Content-Type" content="text/html; charset=US-ASCII"> | |
| <title>Extending return type deduction system</title> | |
| <link rel="stylesheet" href="../../../doc/src/boostbook.css" type="text/css"> | |
| <meta name="generator" content="DocBook XSL Stylesheets V1.75.2"> | |
| <link rel="home" href="../index.html" title="The Boost C++ Libraries BoostBook Documentation Subset"> | |
| <link rel="up" href="../lambda.html" title="Chapter 11. Boost.Lambda"> | |
| <link rel="prev" href="le_in_details.html" title="Lambda expressions in details"> | |
| <link rel="next" href="s07.html" title="Practical considerations"> | |
| </head> | |
| <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"> | |
| <table cellpadding="2" width="100%"><tr> | |
| <td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../boost.png"></td> | |
| <td align="center"><a href="../../../index.html">Home</a></td> | |
| <td align="center"><a href="../../../libs/libraries.htm">Libraries</a></td> | |
| <td align="center"><a href="http://www.boost.org/users/people.html">People</a></td> | |
| <td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td> | |
| <td align="center"><a href="../../../more/index.htm">More</a></td> | |
| </tr></table> | |
| <hr> | |
| <div class="spirit-nav"> | |
| <a accesskey="p" href="le_in_details.html"><img src="../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../lambda.html"><img src="../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="s07.html"><img src="../../../doc/src/images/next.png" alt="Next"></a> | |
| </div> | |
| <div class="section"> | |
| <div class="titlepage"><div><div><h2 class="title" style="clear: both"> | |
| <a name="lambda.extending"></a>Extending return type deduction system</h2></div></div></div> | |
| <p> | |
| In this section, we explain how to extend the return type deduction system | |
| to cover user defined operators. | |
| In many cases this is not necessary, | |
| as the BLL defines default return types for operators. | |
| For example, the default return type for all comparison operators is | |
| <code class="literal">bool</code>, and as long as the user defined comparison operators | |
| have a bool return type, there is no need to write new specializations | |
| for the return type deduction classes. | |
| Sometimes this cannot be avoided, though. | |
| </p> | |
| <p> | |
| The overloadable user defined operators are either unary or binary. | |
| For each arity, there are two traits templates that define the | |
| return types of the different operators. | |
| Hence, the return type system can be extended by providing more | |
| specializations for these templates. | |
| The templates for unary functors are | |
| <code class="literal"> | |
| plain_return_type_1<Action, A> | |
| </code> | |
| and | |
| <code class="literal"> | |
| return_type_1<Action, A> | |
| </code>, and | |
| <code class="literal"> | |
| plain_return_type_2<Action, A, B> | |
| </code> | |
| and | |
| <code class="literal"> | |
| return_type_2<Action, A, B> | |
| </code> | |
| respectively for binary functors. | |
| </p> | |
| <p> | |
| The first parameter (<code class="literal">Action</code>) to all these templates | |
| is the <span class="emphasis"><em>action</em></span> class, which specifies the operator. | |
| Operators with similar return type rules are grouped together into | |
| <span class="emphasis"><em>action groups</em></span>, | |
| and only the action class and action group together define the operator | |
| unambiguously. | |
| As an example, the action type | |
| <code class="literal">arithmetic_action<plus_action></code> stands for | |
| <code class="literal">operator+</code>. | |
| The complete listing of different action types is shown in | |
| <a class="xref" href="extending.html#table:actions" title="Table 11.2. Action types">Table 11.2, “Action types”</a>. | |
| </p> | |
| <p> | |
| The latter parameters, <code class="literal">A</code> in the unary case, | |
| or <code class="literal">A</code> and <code class="literal">B</code> in the binary case, | |
| stand for the argument types of the operator call. | |
| The two sets of templates, | |
| <code class="literal">plain_return_type_<em class="parameter"><code>n</code></em></code> and | |
| <code class="literal">return_type_<em class="parameter"><code>n</code></em></code> | |
| (<em class="parameter"><code>n</code></em> is 1 or 2) differ in the way how parameter types | |
| are presented to them. | |
| For the former templates, the parameter types are always provided as | |
| non-reference types, and do not have const or volatile qualifiers. | |
| This makes specializing easy, as commonly one specialization for each | |
| user defined operator, or operator group, is enough. | |
| On the other hand, if a particular operator is overloaded for different | |
| cv-qualifications of the same argument types, | |
| and the return types of these overloaded versions differ, a more fine-grained control is needed. | |
| Hence, for the latter templates, the parameter types preserve the | |
| cv-qualifiers, and are non-reference types as well. | |
| The downside is, that for an overloaded set of operators of the | |
| kind described above, one may end up needing up to | |
| 16 <code class="literal">return_type_2</code> specializations. | |
| </p> | |
| <p> | |
| Suppose the user has overloaded the following operators for some user defined | |
| types <code class="literal">X</code>, <code class="literal">Y</code> and <code class="literal">Z</code>: | |
| </p> | |
| <pre class="programlisting"> | |
| Z operator+(const X&, const Y&); | |
| Z operator-(const X&, const Y&); | |
| </pre> | |
| <p> | |
| Now, one can add a specialization stating, that if the left hand argument | |
| is of type <code class="literal">X</code>, and the right hand one of type | |
| <code class="literal">Y</code>, the return type of all such binary arithmetic | |
| operators is <code class="literal">Z</code>: | |
| </p> | |
| <pre class="programlisting"> | |
| namespace boost { | |
| namespace lambda { | |
| template<class Act> | |
| struct plain_return_type_2<arithmetic_action<Act>, X, Y> { | |
| typedef Z type; | |
| }; | |
| } | |
| } | |
| </pre> | |
| <p> | |
| Having this specialization defined, BLL is capable of correctly | |
| deducing the return type of the above two operators. | |
| Note, that the specializations must be in the same namespace, | |
| <code class="literal">::boost::lambda</code>, with the primary template. | |
| For brevity, we do not show the namespace definitions in the examples below. | |
| </p> | |
| <p> | |
| It is possible to specialize on the level of an individual operator as well, | |
| in addition to providing a specialization for a group of operators. | |
| Say, we add a new arithmetic operator for argument types <code class="literal">X</code> | |
| and <code class="literal">Y</code>: | |
| </p> | |
| <pre class="programlisting"> | |
| X operator*(const X&, const Y&); | |
| </pre> | |
| <p> | |
| Our first rule for all arithmetic operators specifies that the return | |
| type of this operator is <code class="literal">Z</code>, | |
| which obviously is not the case. | |
| Hence, we provide a new rule for the multiplication operator: | |
| </p> | |
| <pre class="programlisting"> | |
| template<> | |
| struct plain_return_type_2<arithmetic_action<multiply_action>, X, Y> { | |
| typedef X type; | |
| }; | |
| </pre> | |
| <p> | |
| </p> | |
| <p> | |
| The specializations can define arbitrary mappings from the argument types | |
| to the return type. | |
| Suppose we have some mathematical vector type, templated on the element type: | |
| </p> | |
| <pre class="programlisting"> | |
| template <class T> class my_vector; | |
| </pre> | |
| <p> | |
| Suppose the addition operator is defined between any two | |
| <code class="literal">my_vector</code> instantiations, | |
| as long as the addition operator is defined between their element types. | |
| Furthermore, the element type of the resulting <code class="literal">my_vector</code> | |
| is the same as the result type of the addition between the element types. | |
| E.g., adding <code class="literal">my_vector<int></code> and | |
| <code class="literal">my_vector<double></code> results in | |
| <code class="literal">my_vector<double></code>. | |
| The BLL has traits classes to perform the implicit built-in and standard | |
| type conversions between integral, floating point, and complex classes. | |
| Using BLL tools, the addition operator described above can be defined as: | |
| </p> | |
| <pre class="programlisting"> | |
| template<class A, class B> | |
| my_vector<typename return_type_2<arithmetic_action<plus_action>, A, B>::type> | |
| operator+(const my_vector<A>& a, const my_vector<B>& b) | |
| { | |
| typedef typename | |
| return_type_2<arithmetic_action<plus_action>, A, B>::type res_type; | |
| return my_vector<res_type>(); | |
| } | |
| </pre> | |
| <p> | |
| </p> | |
| <p> | |
| To allow BLL to deduce the type of <code class="literal">my_vector</code> | |
| additions correctly, we can define: | |
| </p> | |
| <pre class="programlisting"> | |
| template<class A, class B> | |
| class plain_return_type_2<arithmetic_action<plus_action>, | |
| my_vector<A>, my_vector<B> > { | |
| typedef typename | |
| return_type_2<arithmetic_action<plus_action>, A, B>::type res_type; | |
| public: | |
| typedef my_vector<res_type> type; | |
| }; | |
| </pre> | |
| <p> | |
| Note, that we are reusing the existing specializations for the | |
| BLL <code class="literal">return_type_2</code> template, | |
| which require that the argument types are references. | |
| </p> | |
| <div class="table"> | |
| <a name="table:actions"></a><p class="title"><b>Table 11.2. Action types</b></p> | |
| <div class="table-contents"><table class="table" summary="Action types"> | |
| <colgroup> | |
| <col> | |
| <col> | |
| </colgroup> | |
| <tbody> | |
| <tr> | |
| <td><code class="literal">+</code></td> | |
| <td><code class="literal">arithmetic_action<plus_action></code></td> | |
| </tr> | |
| <tr> | |
| <td><code class="literal">-</code></td> | |
| <td><code class="literal">arithmetic_action<minus_action></code></td> | |
| </tr> | |
| <tr> | |
| <td><code class="literal">*</code></td> | |
| <td><code class="literal">arithmetic_action<multiply_action></code></td> | |
| </tr> | |
| <tr> | |
| <td><code class="literal">/</code></td> | |
| <td><code class="literal">arithmetic_action<divide_action></code></td> | |
| </tr> | |
| <tr> | |
| <td><code class="literal">%</code></td> | |
| <td><code class="literal">arithmetic_action<remainder_action></code></td> | |
| </tr> | |
| <tr> | |
| <td><code class="literal">+</code></td> | |
| <td><code class="literal">unary_arithmetic_action<plus_action></code></td> | |
| </tr> | |
| <tr> | |
| <td><code class="literal">-</code></td> | |
| <td><code class="literal">unary_arithmetic_action<minus_action></code></td> | |
| </tr> | |
| <tr> | |
| <td><code class="literal">&</code></td> | |
| <td><code class="literal">bitwise_action<and_action></code></td> | |
| </tr> | |
| <tr> | |
| <td><code class="literal">|</code></td> | |
| <td><code class="literal">bitwise_action<or_action></code></td> | |
| </tr> | |
| <tr> | |
| <td><code class="literal">~</code></td> | |
| <td><code class="literal">bitwise_action<not_action></code></td> | |
| </tr> | |
| <tr> | |
| <td><code class="literal">^</code></td> | |
| <td><code class="literal">bitwise_action<xor_action></code></td> | |
| </tr> | |
| <tr> | |
| <td><code class="literal"><<</code></td> | |
| <td><code class="literal">bitwise_action<leftshift_action_no_stream></code></td> | |
| </tr> | |
| <tr> | |
| <td><code class="literal">>></code></td> | |
| <td><code class="literal">bitwise_action<rightshift_action_no_stream></code></td> | |
| </tr> | |
| <tr> | |
| <td><code class="literal">&&</code></td> | |
| <td><code class="literal">logical_action<and_action></code></td> | |
| </tr> | |
| <tr> | |
| <td><code class="literal">||</code></td> | |
| <td><code class="literal">logical_action<or_action></code></td> | |
| </tr> | |
| <tr> | |
| <td><code class="literal">!</code></td> | |
| <td><code class="literal">logical_action<not_action></code></td> | |
| </tr> | |
| <tr> | |
| <td><code class="literal"><</code></td> | |
| <td><code class="literal">relational_action<less_action></code></td> | |
| </tr> | |
| <tr> | |
| <td><code class="literal">></code></td> | |
| <td><code class="literal">relational_action<greater_action></code></td> | |
| </tr> | |
| <tr> | |
| <td><code class="literal"><=</code></td> | |
| <td><code class="literal">relational_action<lessorequal_action></code></td> | |
| </tr> | |
| <tr> | |
| <td><code class="literal">>=</code></td> | |
| <td><code class="literal">relational_action<greaterorequal_action></code></td> | |
| </tr> | |
| <tr> | |
| <td><code class="literal">==</code></td> | |
| <td><code class="literal">relational_action<equal_action></code></td> | |
| </tr> | |
| <tr> | |
| <td><code class="literal">!=</code></td> | |
| <td><code class="literal">relational_action<notequal_action></code></td> | |
| </tr> | |
| <tr> | |
| <td><code class="literal">+=</code></td> | |
| <td><code class="literal">arithmetic_assignment_action<plus_action></code></td> | |
| </tr> | |
| <tr> | |
| <td><code class="literal">-=</code></td> | |
| <td><code class="literal">arithmetic_assignment_action<minus_action></code></td> | |
| </tr> | |
| <tr> | |
| <td><code class="literal">*=</code></td> | |
| <td><code class="literal">arithmetic_assignment_action<multiply_action></code></td> | |
| </tr> | |
| <tr> | |
| <td><code class="literal">/=</code></td> | |
| <td><code class="literal">arithmetic_assignment_action<divide_action></code></td> | |
| </tr> | |
| <tr> | |
| <td><code class="literal">%=</code></td> | |
| <td><code class="literal">arithmetic_assignment_action<remainder_action></code></td> | |
| </tr> | |
| <tr> | |
| <td><code class="literal">&=</code></td> | |
| <td><code class="literal">bitwise_assignment_action<and_action></code></td> | |
| </tr> | |
| <tr> | |
| <td><code class="literal">=|</code></td> | |
| <td><code class="literal">bitwise_assignment_action<or_action></code></td> | |
| </tr> | |
| <tr> | |
| <td><code class="literal">^=</code></td> | |
| <td><code class="literal">bitwise_assignment_action<xor_action></code></td> | |
| </tr> | |
| <tr> | |
| <td><code class="literal"><<=</code></td> | |
| <td><code class="literal">bitwise_assignment_action<leftshift_action></code></td> | |
| </tr> | |
| <tr> | |
| <td><code class="literal">>>=</code></td> | |
| <td><code class="literal">bitwise_assignment_action<rightshift_action></code></td> | |
| </tr> | |
| <tr> | |
| <td><code class="literal">++</code></td> | |
| <td><code class="literal">pre_increment_decrement_action<increment_action></code></td> | |
| </tr> | |
| <tr> | |
| <td><code class="literal">--</code></td> | |
| <td><code class="literal">pre_increment_decrement_action<decrement_action></code></td> | |
| </tr> | |
| <tr> | |
| <td><code class="literal">++</code></td> | |
| <td><code class="literal">post_increment_decrement_action<increment_action></code></td> | |
| </tr> | |
| <tr> | |
| <td><code class="literal">--</code></td> | |
| <td><code class="literal">post_increment_decrement_action<decrement_action></code></td> | |
| </tr> | |
| <tr> | |
| <td><code class="literal">&</code></td> | |
| <td><code class="literal">other_action<address_of_action></code></td> | |
| </tr> | |
| <tr> | |
| <td><code class="literal">*</code></td> | |
| <td><code class="literal">other_action<contents_of_action></code></td> | |
| </tr> | |
| <tr> | |
| <td><code class="literal">,</code></td> | |
| <td><code class="literal">other_action<comma_action></code></td> | |
| </tr> | |
| <tr> | |
| <td><code class="literal">->*</code></td> | |
| <td><code class="literal">other_action<member_pointer_action></code></td> | |
| </tr> | |
| </tbody> | |
| </table></div> | |
| </div> | |
| <br class="table-break"> | |
| </div> | |
| <table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr> | |
| <td align="left"></td> | |
| <td align="right"><div class="copyright-footer">Copyright © 1999-2004 Jaakko Järvi, Gary Powell<p>Use, modification and distribution is subject to the Boost | |
| Software License, Version 1.0. (See accompanying file | |
| <code class="filename">LICENSE_1_0.txt</code> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)</p> | |
| </div></td> | |
| </tr></table> | |
| <hr> | |
| <div class="spirit-nav"> | |
| <a accesskey="p" href="le_in_details.html"><img src="../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../lambda.html"><img src="../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="s07.html"><img src="../../../doc/src/images/next.png" alt="Next"></a> | |
| </div> | |
| </body> | |
| </html> |