]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/spirit/classic/phoenix/doc/operators_revisited.html
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / spirit / classic / phoenix / doc / operators_revisited.html
1 <html>
2 <head>
3 <!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
4 <title>Operators revisited</title>
5 <link rel="stylesheet" href="theme/style.css" type="text/css">
6 <link rel="prev" href="composites_revisited.html">
7 <link rel="next" href="interfacing.html">
8 </head>
9 <body>
10 <table width="100%" height="48" border="0" background="theme/bkd2.gif" cellspacing="2">
11 <tr>
12 <td width="10">
13 </td>
14 <td width="85%">
15 <font size="6" face="Verdana, Arial, Helvetica, sans-serif"><b>Operators revisited</b></font>
16 </td>
17 <td width="112"><a href="http://spirit.sf.net"><img src="theme/spirit.gif" align="right" border="0"></a></td>
18 </tr>
19 </table>
20 <br>
21 <table border="0">
22 <tr>
23 <td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
24 <td width="30"><a href="composites_revisited.html"><img src="theme/l_arr.gif" border="0"></a></td>
25 <td width="20"><a href="interfacing.html"><img src="theme/r_arr.gif" border="0"></a></td>
26 </tr>
27 </table>
28 <p>
29 Each C++ operator has a special tag type associated with it. For example the binary + operator has a plus_op tag type associated with it. This operator tag is used to specialize either:</p>
30 <ol><li>unary_operator&lt;TagT, T0&gt;</li><li>binary_operator&lt;TagT, T0, T1&gt;</li></ol><p>
31 template classes (see unary_operator and binary_operator below). Specializations of these unary_operator and binary_operator are the actual workhorses that implement the operations. The behavior of each lazy operator depends on these unary_operator and binary_operator specializations.</p>
32 <p>
33 Preset specializations conform to the canonical operator rules modeled by the behavior of integers and pointers:</p>
34 <ul><li>Prefix -, + and ~ accept constant arguments and return an object by value.</li><li>The ! accept constant arguments and returns a boolean result.</li><li>The &amp; (address-of), * (dereference) both return a reference to an object.</li><li>Prefix ++ returns a reference to its mutable argument after it is incremented.</li><li>Postfix ++ returns the mutable argument by value before it is incremented.</li><li>The += and its family accept mutable right hand side (rhs) operand and return a reference to the rhs operand.</li><li>Infix + and its family accept constant arguments and return an object by value.</li><li>The == and its family accept constant arguments and return a boolean result.</li><li>Operators &amp;&amp; and || accept constant arguments and return a boolean result and are short circuit evaluated as expected.</li></ul><a name="special_operators_and_extensibility"></a><h2>Special operators and extensibility</h2><p>
35 It is of course possible to override the standard operator behavior when appropriate. For example, the behavior of std::cout does not conform to the canonocal shift left operator &lt;&lt; (i.e. the rhs std::cout is a mutable reference). Odd balls such as this are placed in special_ops.hpp. There you will find specializations for various classes found in the standard lib.</p>
36 <p>
37 The library is meant to be extensible. Users may implement their own specializations to allow other libraries to be adapted to be partial-function-evaluation savvy. Later on, in the section &quot;Interfacing (to applications, libraries and frameworks)&quot;, discussion will be focused on interfacing and extending the framework.</p>
38 <a name="operator_tags"></a><h2>Operator tags</h2><p>
39 Each C++ operator has a corresponding tag type. This is used as a means for specializing the unary_operator and binary_operator (see below). The tag also serves as the lazy operator type compatible with a composite as an operation (see composite). Here are two examples of operator tags:</p>
40 <p>
41 Unary example:</p>
42 <code><pre>
43 <span class=keyword>struct </span><span class=identifier>negative_op </span><span class=special>{
44
45 </span><span class=keyword>template </span><span class=special>&lt;</span><span class=keyword>typename </span><span class=identifier>T0</span><span class=special>&gt;
46 </span><span class=keyword>struct </span><span class=identifier>result </span><span class=special>{
47
48 </span><span class=keyword>typedef </span><span class=keyword>typename </span><span class=identifier>unary_operator</span><span class=special>&lt;</span><span class=identifier>negative_op</span><span class=special>, </span><span class=identifier>T0</span><span class=special>&gt;
49 ::</span><span class=identifier>result_type </span><span class=identifier>type</span><span class=special>;
50 };
51
52 </span><span class=keyword>template </span><span class=special>&lt;</span><span class=keyword>typename </span><span class=identifier>T0</span><span class=special>&gt;
53 </span><span class=keyword>typename </span><span class=identifier>unary_operator</span><span class=special>&lt;</span><span class=identifier>negative_op</span><span class=special>, </span><span class=identifier>T0</span><span class=special>&gt;::</span><span class=identifier>result_type
54 </span><span class=keyword>operator</span><span class=special>()(</span><span class=identifier>T0</span><span class=special>&amp; </span><span class=identifier>_0</span><span class=special>) </span><span class=keyword>const
55 </span><span class=special>{ </span><span class=keyword>return </span><span class=identifier>unary_operator</span><span class=special>&lt;</span><span class=identifier>negative_op</span><span class=special>, </span><span class=identifier>T0</span><span class=special>&gt;::</span><span class=identifier>eval</span><span class=special>(</span><span class=identifier>_0</span><span class=special>); }
56 };
57 </span></pre></code>
58 <p>
59 Binary example:</p>
60 <code><pre>
61 <span class=keyword>struct </span><span class=identifier>plus_op </span><span class=special>{
62
63 </span><span class=keyword>template </span><span class=special>&lt;</span><span class=keyword>typename </span><span class=identifier>T0</span><span class=special>, </span><span class=keyword>typename </span><span class=identifier>T1</span><span class=special>&gt;
64 </span><span class=keyword>struct </span><span class=identifier>result </span><span class=special>{
65
66 </span><span class=keyword>typedef </span><span class=keyword>typename </span><span class=identifier>binary_operator</span><span class=special>&lt;</span><span class=identifier>plus_op</span><span class=special>, </span><span class=identifier>T0</span><span class=special>, </span><span class=identifier>T1</span><span class=special>&gt;
67 ::</span><span class=identifier>result_type </span><span class=identifier>type</span><span class=special>;
68 };
69
70 </span><span class=keyword>template </span><span class=special>&lt;</span><span class=keyword>typename </span><span class=identifier>T0</span><span class=special>, </span><span class=keyword>typename </span><span class=identifier>T1</span><span class=special>&gt;
71 </span><span class=keyword>typename </span><span class=identifier>binary_operator</span><span class=special>&lt;</span><span class=identifier>plus_op</span><span class=special>, </span><span class=identifier>T0</span><span class=special>, </span><span class=identifier>T1</span><span class=special>&gt;::</span><span class=identifier>result_type
72 </span><span class=keyword>operator</span><span class=special>()(</span><span class=identifier>T0</span><span class=special>&amp; </span><span class=identifier>_0</span><span class=special>, </span><span class=identifier>T1</span><span class=special>&amp; </span><span class=identifier>_1</span><span class=special>) </span><span class=keyword>const
73 </span><span class=special>{ </span><span class=keyword>return </span><span class=identifier>binary_operator</span><span class=special>&lt;</span><span class=identifier>plus_op</span><span class=special>, </span><span class=identifier>T0</span><span class=special>, </span><span class=identifier>T1</span><span class=special>&gt;::</span><span class=identifier>eval</span><span class=special>(</span><span class=identifier>_0</span><span class=special>, </span><span class=identifier>_1</span><span class=special>); }
74 };
75 </span></pre></code>
76 <p>
77 Notice that these are again perfect examples of a composite operation. This style of specialized function is ubiquitous in the framework. We shall see how the unary_operator&lt;negative_op, T0&gt; and the binary_operator&lt;plus_op, T0, T1&gt; template classes, work in a short while.</p>
78 <p>
79 Here are the complete list of operator tags:</p>
80 <code><pre>
81 <span class=comment>// Unary operator tags
82
83 </span><span class=keyword>struct </span><span class=identifier>negative_op</span><span class=special>; </span><span class=keyword>struct </span><span class=identifier>positive_op</span><span class=special>;
84 </span><span class=keyword>struct </span><span class=identifier>logical_not_op</span><span class=special>; </span><span class=keyword>struct </span><span class=identifier>invert_op</span><span class=special>;
85 </span><span class=keyword>struct </span><span class=identifier>reference_op</span><span class=special>; </span><span class=keyword>struct </span><span class=identifier>dereference_op</span><span class=special>;
86 </span><span class=keyword>struct </span><span class=identifier>pre_incr_op</span><span class=special>; </span><span class=keyword>struct </span><span class=identifier>pre_decr_op</span><span class=special>;
87 </span><span class=keyword>struct </span><span class=identifier>post_incr_op</span><span class=special>; </span><span class=keyword>struct </span><span class=identifier>post_decr_op</span><span class=special>;
88
89 // </span><span class=identifier>Binary </span><span class=keyword>operator </span><span class=identifier>tags
90
91 </span><span class=keyword>struct </span><span class=identifier>assign_op</span><span class=special>; </span><span class=keyword>struct </span><span class=identifier>index_op</span><span class=special>;
92 </span><span class=keyword>struct </span><span class=identifier>plus_assign_op</span><span class=special>; </span><span class=keyword>struct </span><span class=identifier>minus_assign_op</span><span class=special>;
93 </span><span class=keyword>struct </span><span class=identifier>times_assign_op</span><span class=special>; </span><span class=keyword>struct </span><span class=identifier>divide_assign_op</span><span class=special>; </span><span class=keyword>struct </span><span class=identifier>mod_assign_op</span><span class=special>;
94 </span><span class=keyword>struct </span><span class=identifier>and_assign_op</span><span class=special>; </span><span class=keyword>struct </span><span class=identifier>or_assign_op</span><span class=special>; </span><span class=keyword>struct </span><span class=identifier>xor_assign_op</span><span class=special>;
95 </span><span class=keyword>struct </span><span class=identifier>shift_l_assign_op</span><span class=special>; </span><span class=keyword>struct </span><span class=identifier>shift_r_assign_op</span><span class=special>;
96
97 </span><span class=keyword>struct </span><span class=identifier>plus_op</span><span class=special>; </span><span class=keyword>struct </span><span class=identifier>minus_op</span><span class=special>;
98 </span><span class=keyword>struct </span><span class=identifier>times_op</span><span class=special>; </span><span class=keyword>struct </span><span class=identifier>divide_op</span><span class=special>; </span><span class=keyword>struct </span><span class=identifier>mod_op</span><span class=special>;
99 </span><span class=keyword>struct </span><span class=identifier>and_op</span><span class=special>; </span><span class=keyword>struct </span><span class=identifier>or_op</span><span class=special>; </span><span class=keyword>struct </span><span class=identifier>xor_op</span><span class=special>;
100 </span><span class=keyword>struct </span><span class=identifier>shift_l_op</span><span class=special>; </span><span class=keyword>struct </span><span class=identifier>shift_r_op</span><span class=special>;
101
102 </span><span class=keyword>struct </span><span class=identifier>eq_op</span><span class=special>; </span><span class=keyword>struct </span><span class=identifier>not_eq_op</span><span class=special>;
103 </span><span class=keyword>struct </span><span class=identifier>lt_op</span><span class=special>; </span><span class=keyword>struct </span><span class=identifier>lt_eq_op</span><span class=special>;
104 </span><span class=keyword>struct </span><span class=identifier>gt_op</span><span class=special>; </span><span class=keyword>struct </span><span class=identifier>gt_eq_op</span><span class=special>;
105 </span><span class=keyword>struct </span><span class=identifier>logical_and_op</span><span class=special>; </span><span class=keyword>struct </span><span class=identifier>logical_or_op</span><span class=special>;
106 </span></pre></code>
107 <a name="unary_operator"></a><h3>unary_operator</h3><p>
108 The unary_operator class implements most of the C++ unary operators. Each specialization is basically a simple static eval function plus a result_type typedef that determines the return type of the eval function.</p>
109 <p>
110 TagT is one of the unary operator tags above and T is the data type (argument) involved in the operation. Here is an example:</p>
111 <code><pre>
112 <span class=keyword>template </span><span class=special>&lt;</span><span class=keyword>typename </span><span class=identifier>T</span><span class=special>&gt;
113 </span><span class=keyword>struct </span><span class=identifier>unary_operator</span><span class=special>&lt;</span><span class=identifier>negative_op</span><span class=special>, </span><span class=identifier>T</span><span class=special>&gt; {
114
115 </span><span class=keyword>typedef </span><span class=identifier>T </span><span class=keyword>const </span><span class=identifier>result_type</span><span class=special>;
116 </span><span class=keyword>static </span><span class=identifier>result_type </span><span class=identifier>eval</span><span class=special>(</span><span class=identifier>T </span><span class=keyword>const</span><span class=special>&amp; </span><span class=identifier>v</span><span class=special>)
117 { </span><span class=keyword>return </span><span class=special>-</span><span class=identifier>v</span><span class=special>; }
118 };
119 </span></pre></code>
120 <p>
121 This example is exactly what was being referred to by the first example we saw in the section on operator tags.</p>
122 <p>
123 Only the behavior of C/C++ built-in types are taken into account in the specializations provided in operator.hpp. For user-defined types, these specializations may still be used provided that the operator overloads of such types adhere to the standard behavior of built-in types.</p>
124 <p>
125 A separate special_ops.hpp file implements more STL savvy specializations. Other more specialized unary_operator implementations may be defined by the client for specific unary operator tags/data types.</p>
126 <a name="binary_operator"></a><h3>binary_operator</h3><p>
127 The binary_operator class implements most of the C++ binary operators. Each specialization is basically a simple static eval function plus a result_type typedef that determines the return type of the eval function.</p>
128 <p>
129 TagT is one of the binary operator tags above T0 and T1 are the (arguments') data types involved in the operation. Here is an example:</p>
130 <code><pre>
131 <span class=keyword>template </span><span class=special>&lt;</span><span class=keyword>typename </span><span class=identifier>T0</span><span class=special>, </span><span class=keyword>typename </span><span class=identifier>T1</span><span class=special>&gt;
132 </span><span class=keyword>struct </span><span class=identifier>binary_operator</span><span class=special>&lt;</span><span class=identifier>plus_op</span><span class=special>, </span><span class=identifier>T0</span><span class=special>, </span><span class=identifier>T1</span><span class=special>&gt; {
133
134 </span><span class=keyword>typedef </span><span class=keyword>typename </span><span class=identifier>higher_rank</span><span class=special>&lt;</span><span class=identifier>T0</span><span class=special>, </span><span class=identifier>T1</span><span class=special>&gt;::</span><span class=identifier>type </span><span class=keyword>const </span><span class=identifier>result_type</span><span class=special>;
135 </span><span class=keyword>static </span><span class=identifier>result_type </span><span class=identifier>eval</span><span class=special>(</span><span class=identifier>T0 </span><span class=keyword>const</span><span class=special>&amp; </span><span class=identifier>lhs</span><span class=special>, </span><span class=identifier>T1 </span><span class=keyword>const</span><span class=special>&amp; </span><span class=identifier>rhs</span><span class=special>)
136 { </span><span class=keyword>return </span><span class=identifier>lhs </span><span class=special>+ </span><span class=identifier>rhs</span><span class=special>; }
137 };
138 </span></pre></code>
139 <p>
140 This example is exactly what was being referred to by the second example we saw in the section on operator tags. higher_rank&lt;T0, T1&gt; is a type computer. We shall see how this works in a short while, pardon the forward information.</p>
141 <p>
142 Only the behavior of C/C++ built-in types are taken into account in the specializations provided in operator.hpp. For user-defined types, these specializations may still be used provided that the operator overloads of such types adhere to the standard behavior of built-in types.</p>
143 <p>
144 A separate special_ops.hpp file implements more STL savvy specializations. Other more specialized unary_operator implementations may be defined by the client for specific unary operator tags/data types.</p>
145 <p>
146 All binary_operator except the logical_and_op and logical_or_op have an eval static function that carries out the actual operation. The logical_and_op and logical_or_op d are special because these two operators are short-circuit evaluated.</p>
147 <table width="80%" border="0" align="center">
148 <tr>
149 <td class="note_box">
150 <img src="theme/lens.gif"></img> <b>Short Circuiting || and &amp;&amp;</b><br><br>The logical_and_op and logical_or_op are special due to the C/C++ short circuiting rule, i.e. a || b and a &amp;&amp; b are short circuit evaluated. A forwarding operation cannot be used because all function arguments are evaluated before a function is called. logical_and_op and logical_or_op are specialized composites with implied operations. </td>
151 </tr>
152 </table>
153 <a name="rank"></a><h2>rank</h2><p>
154 rank&lt;T&gt; class has a static int constant 'value' that defines the absolute rank of a type. rank&lt;T&gt; is used to choose the result type of binary operators such as +. The type with the higher rank wins and is used as the operator's return type. A generic user defined type has a very high rank and always wins when compared against a user defined type. If this is not desireable, one can write a rank specialization for the type. Here are some predefined examples:</p>
155 <code><pre>
156 <span class=keyword>template </span><span class=special>&lt;&gt; </span><span class=keyword>struct </span><span class=identifier>rank</span><span class=special>&lt;</span><span class=keyword>char</span><span class=special>&gt; { </span><span class=keyword>static </span><span class=keyword>int </span><span class=keyword>const </span><span class=identifier>value </span><span class=special>= </span><span class=number>20</span><span class=special>; };
157 </span><span class=keyword>template </span><span class=special>&lt;&gt; </span><span class=keyword>struct </span><span class=identifier>rank</span><span class=special>&lt;</span><span class=keyword>signed </span><span class=keyword>char</span><span class=special>&gt; { </span><span class=keyword>static </span><span class=keyword>int </span><span class=keyword>const </span><span class=identifier>value </span><span class=special>= </span><span class=number>20</span><span class=special>; };
158 </span><span class=keyword>template </span><span class=special>&lt;&gt; </span><span class=keyword>struct </span><span class=identifier>rank</span><span class=special>&lt;</span><span class=keyword>unsigned </span><span class=keyword>char</span><span class=special>&gt; { </span><span class=keyword>static </span><span class=keyword>int </span><span class=keyword>const </span><span class=identifier>value </span><span class=special>= </span><span class=number>30</span><span class=special>; };
159 </span><span class=keyword>template </span><span class=special>&lt;&gt; </span><span class=keyword>struct </span><span class=identifier>rank</span><span class=special>&lt;</span><span class=keyword>wchar_t</span><span class=special>&gt; { </span><span class=keyword>static </span><span class=keyword>int </span><span class=keyword>const </span><span class=identifier>value </span><span class=special>= </span><span class=number>40</span><span class=special>; };
160 </span></pre></code>
161 <p>
162 Take note that ranks 0..9999 are reserved by the framework.</p>
163 <p>
164 A template type computer higher_rank&lt;T0, T1&gt; chooses the type (T0 or T1) with the higher rank. We saw in the binary_operator for plus_op how it was used. Specifically:</p>
165 <code><pre>
166 <span class=identifier>higher_rank</span><span class=special>&lt;</span><span class=identifier>T0</span><span class=special>, </span><span class=identifier>T1</span><span class=special>&gt;::</span><span class=identifier>type
167 </span></pre></code>
168 <p>
169 returns either T0 or T1 depending on which has a higher rank. In some operator applications such as a + b, the result is actually the one with the higher rank. For example if a is of type int and b is of type double, the result will be of type double. This facility can also be quite useful for evaluating some functions. For instance if we have a sum(a, b, c, d, e) function, we can call this type computer to get the type with the highest rank:</p>
170 <code><pre>
171 <span class=identifier>higher_rank</span><span class=special>&lt;</span><span class=identifier>TA</span><span class=special>,
172 </span><span class=identifier>higher_rank</span><span class=special>&lt;</span><span class=identifier>TB</span><span class=special>,
173 </span><span class=identifier>higher_rank</span><span class=special>&lt;</span><span class=identifier>TC</span><span class=special>,
174 </span><span class=identifier>higher_rank</span><span class=special>&lt;</span><span class=identifier>TD</span><span class=special>, </span><span class=identifier>TE</span><span class=special>&gt;::</span><span class=identifier>type
175 </span><span class=special>&gt;::</span><span class=identifier>type
176 </span><span class=special>&gt;::</span><span class=identifier>type
177 </span><span class=special>&gt;::</span><span class=identifier>type
178 </span></pre></code>
179 <table width="80%" border="0" align="center">
180 <tr>
181 <td class="note_box">
182 <img src="theme/alert.gif"></img> When used within templates, be sure to use 'typename' appropriately. See binary_operator&lt;plus_op, T0, T1&gt; above. </td>
183 </tr>
184 </table>
185 <table border="0">
186 <tr>
187 <td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
188 <td width="30"><a href="composites_revisited.html"><img src="theme/l_arr.gif" border="0"></a></td>
189 <td width="20"><a href="interfacing.html"><img src="theme/r_arr.gif" border="0"></a></td>
190 </tr>
191 </table>
192 <br>
193 <hr size="1">
194 <p class="copyright">Copyright &copy; 2001-2002 Joel de Guzman<br>
195 <br>
196 <font size="2">Use, modification and distribution is subject to the Boost Software
197 License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
198 http://www.boost.org/LICENSE_1_0.txt) </font> </p>
199 </body>
200 </html>