1 | <html> |
---|
2 | <head> |
---|
3 | <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> |
---|
4 | <title>Extending return type deduction system</title> |
---|
5 | <link rel="stylesheet" href="../boostbook.css" type="text/css"> |
---|
6 | <meta name="generator" content="DocBook XSL Stylesheets V1.68.1"> |
---|
7 | <link rel="start" href="../index.html" title="The Boost C++ Libraries BoostBook Documentation Subset"> |
---|
8 | <link rel="up" href="../lambda.html" title="Chapter 8. Boost.Lambda"> |
---|
9 | <link rel="prev" href="le_in_details.html" title="Lambda expressions in details"> |
---|
10 | <link rel="next" href="s07.html" title="Practical considerations"> |
---|
11 | </head> |
---|
12 | <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"> |
---|
13 | <table cellpadding="2" width="100%"> |
---|
14 | <td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../boost.png"></td> |
---|
15 | <td align="center"><a href="../../../index.htm">Home</a></td> |
---|
16 | <td align="center"><a href="../../../libs/libraries.htm">Libraries</a></td> |
---|
17 | <td align="center"><a href="../../../people/people.htm">People</a></td> |
---|
18 | <td align="center"><a href="../../../more/faq.htm">FAQ</a></td> |
---|
19 | <td align="center"><a href="../../../more/index.htm">More</a></td> |
---|
20 | </table> |
---|
21 | <hr> |
---|
22 | <div class="spirit-nav"> |
---|
23 | <a accesskey="p" href="le_in_details.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../lambda.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="s07.html"><img src="../images/next.png" alt="Next"></a> |
---|
24 | </div> |
---|
25 | <div class="section" lang="en"> |
---|
26 | <div class="titlepage"><div><div><h2 class="title" style="clear: both"> |
---|
27 | <a name="lambda.extending"></a>Extending return type deduction system</h2></div></div></div> |
---|
28 | <p> |
---|
29 | |
---|
30 | |
---|
31 | In this section, we explain how to extend the return type deduction system |
---|
32 | to cover user defined operators. |
---|
33 | |
---|
34 | In many cases this is not necessary, |
---|
35 | as the BLL defines default return types for operators. |
---|
36 | |
---|
37 | For example, the default return type for all comparison operators is |
---|
38 | <code class="literal">bool</code>, and as long as the user defined comparison operators |
---|
39 | have a bool return type, there is no need to write new specializations |
---|
40 | for the return type deduction classes. |
---|
41 | |
---|
42 | Sometimes this cannot be avoided, though. |
---|
43 | |
---|
44 | </p> |
---|
45 | <p> |
---|
46 | The overloadable user defined operators are either unary or binary. |
---|
47 | |
---|
48 | For each arity, there are two traits templates that define the |
---|
49 | return types of the different operators. |
---|
50 | |
---|
51 | Hence, the return type system can be extended by providing more |
---|
52 | specializations for these templates. |
---|
53 | |
---|
54 | The templates for unary functors are |
---|
55 | |
---|
56 | <code class="literal"> |
---|
57 | plain_return_type_1<Action, A> |
---|
58 | </code> |
---|
59 | |
---|
60 | and |
---|
61 | |
---|
62 | <code class="literal"> |
---|
63 | return_type_1<Action, A> |
---|
64 | </code>, and |
---|
65 | |
---|
66 | <code class="literal"> |
---|
67 | plain_return_type_2<Action, A, B> |
---|
68 | </code> |
---|
69 | |
---|
70 | and |
---|
71 | |
---|
72 | <code class="literal"> |
---|
73 | return_type_2<Action, A, B> |
---|
74 | </code> |
---|
75 | |
---|
76 | respectively for binary functors. |
---|
77 | |
---|
78 | </p> |
---|
79 | <p> |
---|
80 | The first parameter (<code class="literal">Action</code>) to all these templates |
---|
81 | is the <span class="emphasis"><em>action</em></span> class, which specifies the operator. |
---|
82 | |
---|
83 | Operators with similar return type rules are grouped together into |
---|
84 | <span class="emphasis"><em>action groups</em></span>, |
---|
85 | and only the action class and action group together define the operator |
---|
86 | unambiguously. |
---|
87 | |
---|
88 | As an example, the action type |
---|
89 | <code class="literal">arithmetic_action<plus_action></code> stands for |
---|
90 | <code class="literal">operator+</code>. |
---|
91 | |
---|
92 | The complete listing of different action types is shown in |
---|
93 | <a href="extending.html#table:actions" title="Table 8.2. Action types">Table 8.2, “Action types”</a>. |
---|
94 | </p> |
---|
95 | <p> |
---|
96 | The latter parameters, <code class="literal">A</code> in the unary case, |
---|
97 | or <code class="literal">A</code> and <code class="literal">B</code> in the binary case, |
---|
98 | stand for the argument types of the operator call. |
---|
99 | |
---|
100 | The two sets of templates, |
---|
101 | <code class="literal">plain_return_type_<em class="parameter"><code>n</code></em></code> and |
---|
102 | <code class="literal">return_type_<em class="parameter"><code>n</code></em></code> |
---|
103 | (<em class="parameter"><code>n</code></em> is 1 or 2) differ in the way how parameter types |
---|
104 | are presented to them. |
---|
105 | |
---|
106 | For the former templates, the parameter types are always provided as |
---|
107 | non-reference types, and do not have const or volatile qualifiers. |
---|
108 | |
---|
109 | This makes specializing easy, as commonly one specialization for each |
---|
110 | user defined operator, or operator group, is enough. |
---|
111 | |
---|
112 | On the other hand, if a particular operator is overloaded for different |
---|
113 | cv-qualifications of the same argument types, |
---|
114 | and the return types of these overloaded versions differ, a more fine-grained control is needed. |
---|
115 | |
---|
116 | Hence, for the latter templates, the parameter types preserve the |
---|
117 | cv-qualifiers, and are non-reference types as well. |
---|
118 | |
---|
119 | The downside is, that for an overloaded set of operators of the |
---|
120 | kind described above, one may end up needing up to |
---|
121 | 16 <code class="literal">return_type_2</code> specializations. |
---|
122 | </p> |
---|
123 | <p> |
---|
124 | Suppose the user has overloaded the following operators for some user defined |
---|
125 | types <code class="literal">X</code>, <code class="literal">Y</code> and <code class="literal">Z</code>: |
---|
126 | |
---|
127 | </p> |
---|
128 | <pre class="programlisting"> |
---|
129 | Z operator+(const X&, const Y&); |
---|
130 | Z operator-(const X&, const Y&); |
---|
131 | </pre> |
---|
132 | <p> |
---|
133 | |
---|
134 | Now, one can add a specialization stating, that if the left hand argument |
---|
135 | is of type <code class="literal">X</code>, and the right hand one of type |
---|
136 | <code class="literal">Y</code>, the return type of all such binary arithmetic |
---|
137 | operators is <code class="literal">Z</code>: |
---|
138 | |
---|
139 | </p> |
---|
140 | <pre class="programlisting"> |
---|
141 | namespace boost { |
---|
142 | namespace lambda { |
---|
143 | |
---|
144 | template<class Act> |
---|
145 | struct plain_return_type_2<arithmetic_action<Act>, X, Y> { |
---|
146 | typedef Z type; |
---|
147 | }; |
---|
148 | |
---|
149 | } |
---|
150 | } |
---|
151 | </pre> |
---|
152 | <p> |
---|
153 | |
---|
154 | Having this specialization defined, BLL is capable of correctly |
---|
155 | deducing the return type of the above two operators. |
---|
156 | |
---|
157 | Note, that the specializations must be in the same namespace, |
---|
158 | <code class="literal">::boost::lambda</code>, with the primary template. |
---|
159 | |
---|
160 | For brevity, we do not show the namespace definitions in the examples below. |
---|
161 | </p> |
---|
162 | <p> |
---|
163 | It is possible to specialize on the level of an individual operator as well, |
---|
164 | in addition to providing a specialization for a group of operators. |
---|
165 | Say, we add a new arithmetic operator for argument types <code class="literal">X</code> |
---|
166 | and <code class="literal">Y</code>: |
---|
167 | |
---|
168 | </p> |
---|
169 | <pre class="programlisting"> |
---|
170 | X operator*(const X&, const Y&); |
---|
171 | </pre> |
---|
172 | <p> |
---|
173 | |
---|
174 | Our first rule for all arithmetic operators specifies that the return |
---|
175 | type of this operator is <code class="literal">Z</code>, |
---|
176 | which obviously is not the case. |
---|
177 | Hence, we provide a new rule for the multiplication operator: |
---|
178 | |
---|
179 | </p> |
---|
180 | <pre class="programlisting"> |
---|
181 | template<> |
---|
182 | struct plain_return_type_2<arithmetic_action<multiply_action>, X, Y> { |
---|
183 | typedef X type; |
---|
184 | }; |
---|
185 | </pre> |
---|
186 | <p> |
---|
187 | </p> |
---|
188 | <p> |
---|
189 | The specializations can define arbitrary mappings from the argument types |
---|
190 | to the return type. |
---|
191 | |
---|
192 | Suppose we have some mathematical vector type, templated on the element type: |
---|
193 | |
---|
194 | </p> |
---|
195 | <pre class="programlisting"> |
---|
196 | template <class T> class my_vector; |
---|
197 | </pre> |
---|
198 | <p> |
---|
199 | |
---|
200 | Suppose the addition operator is defined between any two |
---|
201 | <code class="literal">my_vector</code> instantiations, |
---|
202 | as long as the addition operator is defined between their element types. |
---|
203 | |
---|
204 | Furthermore, the element type of the resulting <code class="literal">my_vector</code> |
---|
205 | is the same as the result type of the addition between the element types. |
---|
206 | |
---|
207 | E.g., adding <code class="literal">my_vector<int></code> and |
---|
208 | <code class="literal">my_vector<double></code> results in |
---|
209 | <code class="literal">my_vector<double></code>. |
---|
210 | |
---|
211 | The BLL has traits classes to perform the implicit built-in and standard |
---|
212 | type conversions between integral, floating point, and complex classes. |
---|
213 | |
---|
214 | Using BLL tools, the addition operator described above can be defined as: |
---|
215 | |
---|
216 | </p> |
---|
217 | <pre class="programlisting"> |
---|
218 | template<class A, class B> |
---|
219 | my_vector<typename return_type_2<arithmetic_action<plus_action>, A, B>::type> |
---|
220 | operator+(const my_vector<A>& a, const my_vector<B>& b) |
---|
221 | { |
---|
222 | typedef typename |
---|
223 | return_type_2<arithmetic_action<plus_action>, A, B>::type res_type; |
---|
224 | return my_vector<res_type>(); |
---|
225 | } |
---|
226 | </pre> |
---|
227 | <p> |
---|
228 | </p> |
---|
229 | <p> |
---|
230 | To allow BLL to deduce the type of <code class="literal">my_vector</code> |
---|
231 | additions correctly, we can define: |
---|
232 | |
---|
233 | </p> |
---|
234 | <pre class="programlisting"> |
---|
235 | template<class A, class B> |
---|
236 | class plain_return_type_2<arithmetic_action<plus_action>, |
---|
237 | my_vector<A>, my_vector<B> > { |
---|
238 | typedef typename |
---|
239 | return_type_2<arithmetic_action<plus_action>, A, B>::type res_type; |
---|
240 | public: |
---|
241 | typedef my_vector<res_type> type; |
---|
242 | }; |
---|
243 | </pre> |
---|
244 | <p> |
---|
245 | Note, that we are reusing the existing specializations for the |
---|
246 | BLL <code class="literal">return_type_2</code> template, |
---|
247 | which require that the argument types are references. |
---|
248 | </p> |
---|
249 | <div class="table"> |
---|
250 | <a name="table:actions"></a><p class="title"><b>Table 8.2. Action types</b></p> |
---|
251 | <table class="table" summary="Action types"> |
---|
252 | <colgroup> |
---|
253 | <col> |
---|
254 | <col> |
---|
255 | </colgroup> |
---|
256 | <tbody> |
---|
257 | <tr> |
---|
258 | <td><code class="literal">+</code></td> |
---|
259 | <td><code class="literal">arithmetic_action<plus_action></code></td> |
---|
260 | </tr> |
---|
261 | <tr> |
---|
262 | <td><code class="literal">-</code></td> |
---|
263 | <td><code class="literal">arithmetic_action<minus_action></code></td> |
---|
264 | </tr> |
---|
265 | <tr> |
---|
266 | <td><code class="literal">*</code></td> |
---|
267 | <td><code class="literal">arithmetic_action<multiply_action></code></td> |
---|
268 | </tr> |
---|
269 | <tr> |
---|
270 | <td><code class="literal">/</code></td> |
---|
271 | <td><code class="literal">arithmetic_action<divide_action></code></td> |
---|
272 | </tr> |
---|
273 | <tr> |
---|
274 | <td><code class="literal">%</code></td> |
---|
275 | <td><code class="literal">arithmetic_action<remainder_action></code></td> |
---|
276 | </tr> |
---|
277 | <tr> |
---|
278 | <td><code class="literal">+</code></td> |
---|
279 | <td><code class="literal">unary_arithmetic_action<plus_action></code></td> |
---|
280 | </tr> |
---|
281 | <tr> |
---|
282 | <td><code class="literal">-</code></td> |
---|
283 | <td><code class="literal">unary_arithmetic_action<minus_action></code></td> |
---|
284 | </tr> |
---|
285 | <tr> |
---|
286 | <td><code class="literal">&</code></td> |
---|
287 | <td><code class="literal">bitwise_action<and_action></code></td> |
---|
288 | </tr> |
---|
289 | <tr> |
---|
290 | <td><code class="literal">|</code></td> |
---|
291 | <td><code class="literal">bitwise_action<or_action></code></td> |
---|
292 | </tr> |
---|
293 | <tr> |
---|
294 | <td><code class="literal">~</code></td> |
---|
295 | <td><code class="literal">bitwise_action<not_action></code></td> |
---|
296 | </tr> |
---|
297 | <tr> |
---|
298 | <td><code class="literal">^</code></td> |
---|
299 | <td><code class="literal">bitwise_action<xor_action></code></td> |
---|
300 | </tr> |
---|
301 | <tr> |
---|
302 | <td><code class="literal"><<</code></td> |
---|
303 | <td><code class="literal">bitwise_action<leftshift_action_no_stream></code></td> |
---|
304 | </tr> |
---|
305 | <tr> |
---|
306 | <td><code class="literal">>></code></td> |
---|
307 | <td><code class="literal">bitwise_action<rightshift_action_no_stream></code></td> |
---|
308 | </tr> |
---|
309 | <tr> |
---|
310 | <td><code class="literal">&&</code></td> |
---|
311 | <td><code class="literal">logical_action<and_action></code></td> |
---|
312 | </tr> |
---|
313 | <tr> |
---|
314 | <td><code class="literal">||</code></td> |
---|
315 | <td><code class="literal">logical_action<or_action></code></td> |
---|
316 | </tr> |
---|
317 | <tr> |
---|
318 | <td><code class="literal">!</code></td> |
---|
319 | <td><code class="literal">logical_action<not_action></code></td> |
---|
320 | </tr> |
---|
321 | <tr> |
---|
322 | <td><code class="literal"><</code></td> |
---|
323 | <td><code class="literal">relational_action<less_action></code></td> |
---|
324 | </tr> |
---|
325 | <tr> |
---|
326 | <td><code class="literal">></code></td> |
---|
327 | <td><code class="literal">relational_action<greater_action></code></td> |
---|
328 | </tr> |
---|
329 | <tr> |
---|
330 | <td><code class="literal"><=</code></td> |
---|
331 | <td><code class="literal">relational_action<lessorequal_action></code></td> |
---|
332 | </tr> |
---|
333 | <tr> |
---|
334 | <td><code class="literal">>=</code></td> |
---|
335 | <td><code class="literal">relational_action<greaterorequal_action></code></td> |
---|
336 | </tr> |
---|
337 | <tr> |
---|
338 | <td><code class="literal">==</code></td> |
---|
339 | <td><code class="literal">relational_action<equal_action></code></td> |
---|
340 | </tr> |
---|
341 | <tr> |
---|
342 | <td><code class="literal">!=</code></td> |
---|
343 | <td><code class="literal">relational_action<notequal_action></code></td> |
---|
344 | </tr> |
---|
345 | <tr> |
---|
346 | <td><code class="literal">+=</code></td> |
---|
347 | <td><code class="literal">arithmetic_assignment_action<plus_action></code></td> |
---|
348 | </tr> |
---|
349 | <tr> |
---|
350 | <td><code class="literal">-=</code></td> |
---|
351 | <td><code class="literal">arithmetic_assignment_action<minus_action></code></td> |
---|
352 | </tr> |
---|
353 | <tr> |
---|
354 | <td><code class="literal">*=</code></td> |
---|
355 | <td><code class="literal">arithmetic_assignment_action<multiply_action></code></td> |
---|
356 | </tr> |
---|
357 | <tr> |
---|
358 | <td><code class="literal">/=</code></td> |
---|
359 | <td><code class="literal">arithmetic_assignment_action<divide_action></code></td> |
---|
360 | </tr> |
---|
361 | <tr> |
---|
362 | <td><code class="literal">%=</code></td> |
---|
363 | <td><code class="literal">arithmetic_assignment_action<remainder_action></code></td> |
---|
364 | </tr> |
---|
365 | <tr> |
---|
366 | <td><code class="literal">&=</code></td> |
---|
367 | <td><code class="literal">bitwise_assignment_action<and_action></code></td> |
---|
368 | </tr> |
---|
369 | <tr> |
---|
370 | <td><code class="literal">=|</code></td> |
---|
371 | <td><code class="literal">bitwise_assignment_action<or_action></code></td> |
---|
372 | </tr> |
---|
373 | <tr> |
---|
374 | <td><code class="literal">^=</code></td> |
---|
375 | <td><code class="literal">bitwise_assignment_action<xor_action></code></td> |
---|
376 | </tr> |
---|
377 | <tr> |
---|
378 | <td><code class="literal"><<=</code></td> |
---|
379 | <td><code class="literal">bitwise_assignment_action<leftshift_action></code></td> |
---|
380 | </tr> |
---|
381 | <tr> |
---|
382 | <td><code class="literal">>>=</code></td> |
---|
383 | <td><code class="literal">bitwise_assignment_action<rightshift_action></code></td> |
---|
384 | </tr> |
---|
385 | <tr> |
---|
386 | <td><code class="literal">++</code></td> |
---|
387 | <td><code class="literal">pre_increment_decrement_action<increment_action></code></td> |
---|
388 | </tr> |
---|
389 | <tr> |
---|
390 | <td><code class="literal">--</code></td> |
---|
391 | <td><code class="literal">pre_increment_decrement_action<decrement_action></code></td> |
---|
392 | </tr> |
---|
393 | <tr> |
---|
394 | <td><code class="literal">++</code></td> |
---|
395 | <td><code class="literal">post_increment_decrement_action<increment_action></code></td> |
---|
396 | </tr> |
---|
397 | <tr> |
---|
398 | <td><code class="literal">--</code></td> |
---|
399 | <td><code class="literal">post_increment_decrement_action<decrement_action></code></td> |
---|
400 | </tr> |
---|
401 | <tr> |
---|
402 | <td><code class="literal">&</code></td> |
---|
403 | <td><code class="literal">other_action<address_of_action></code></td> |
---|
404 | </tr> |
---|
405 | <tr> |
---|
406 | <td><code class="literal">*</code></td> |
---|
407 | <td><code class="literal">other_action<contents_of_action></code></td> |
---|
408 | </tr> |
---|
409 | <tr> |
---|
410 | <td><code class="literal">,</code></td> |
---|
411 | <td><code class="literal">other_action<comma_action></code></td> |
---|
412 | </tr> |
---|
413 | <tr> |
---|
414 | <td><code class="literal">->*</code></td> |
---|
415 | <td><code class="literal">other_action<member_pointer_action></code></td> |
---|
416 | </tr> |
---|
417 | </tbody> |
---|
418 | </table> |
---|
419 | </div> |
---|
420 | </div> |
---|
421 | <table width="100%"><tr> |
---|
422 | <td align="left"></td> |
---|
423 | <td align="right"><small>Copyright © 1999-2004 Jaakko Järvi, Gary Powell</small></td> |
---|
424 | </tr></table> |
---|
425 | <hr> |
---|
426 | <div class="spirit-nav"> |
---|
427 | <a accesskey="p" href="le_in_details.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../lambda.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="s07.html"><img src="../images/next.png" alt="Next"></a> |
---|
428 | </div> |
---|
429 | </body> |
---|
430 | </html> |
---|