436 lines
15 KiB
HTML
436 lines
15 KiB
HTML
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||
<html>
|
||
<head>
|
||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||
<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.79.1">
|
||
<link rel="home" href="../index.html" title="The Boost C++ Libraries BoostBook Documentation Subset">
|
||
<link rel="up" href="../lambda.html" title="Chapter 20. 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 20.2. Action types">Table 20.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 20.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>
|