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">
10 <table width=
"100%" height=
"48" border=
"0" background=
"theme/bkd2.gif" cellspacing=
"2">
15 <font size=
"6" face=
"Verdana, Arial, Helvetica, sans-serif"><b>Operators revisited
</b></font>
17 <td width=
"112"><a href=
"http://spirit.sf.net"><img src=
"theme/spirit.gif" align=
"right" border=
"0"></a></td>
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>
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
<TagT, T0
></li><li>binary_operator
<TagT, T0, T1
></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>
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
& (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
&& 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
<< (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>
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
"Interfacing (to applications, libraries and frameworks)
", 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>
43 <span class=keyword
>struct
</span><span class=identifier
>negative_op
</span><span class=special
>{
45 </span><span class=keyword
>template
</span><span class=special
><</span><span class=keyword
>typename
</span><span class=identifier
>T0
</span><span class=special
>>
46 </span><span class=keyword
>struct
</span><span class=identifier
>result
</span><span class=special
>{
48 </span><span class=keyword
>typedef
</span><span class=keyword
>typename
</span><span class=identifier
>unary_operator
</span><span class=special
><</span><span class=identifier
>negative_op
</span><span class=special
>,
</span><span class=identifier
>T0
</span><span class=special
>>
49 ::
</span><span class=identifier
>result_type
</span><span class=identifier
>type
</span><span class=special
>;
52 </span><span class=keyword
>template
</span><span class=special
><</span><span class=keyword
>typename
</span><span class=identifier
>T0
</span><span class=special
>>
53 </span><span class=keyword
>typename
</span><span class=identifier
>unary_operator
</span><span class=special
><</span><span class=identifier
>negative_op
</span><span class=special
>,
</span><span class=identifier
>T0
</span><span class=special
>>::
</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
>& </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
><</span><span class=identifier
>negative_op
</span><span class=special
>,
</span><span class=identifier
>T0
</span><span class=special
>>::
</span><span class=identifier
>eval
</span><span class=special
>(
</span><span class=identifier
>_0
</span><span class=special
>); }
61 <span class=keyword
>struct
</span><span class=identifier
>plus_op
</span><span class=special
>{
63 </span><span class=keyword
>template
</span><span class=special
><</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
>>
64 </span><span class=keyword
>struct
</span><span class=identifier
>result
</span><span class=special
>{
66 </span><span class=keyword
>typedef
</span><span class=keyword
>typename
</span><span class=identifier
>binary_operator
</span><span class=special
><</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
>>
67 ::
</span><span class=identifier
>result_type
</span><span class=identifier
>type
</span><span class=special
>;
70 </span><span class=keyword
>template
</span><span class=special
><</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
>>
71 </span><span class=keyword
>typename
</span><span class=identifier
>binary_operator
</span><span class=special
><</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
>>::
</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
>& </span><span class=identifier
>_0
</span><span class=special
>,
</span><span class=identifier
>T1
</span><span class=special
>& </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
><</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
>>::
</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
>); }
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
<negative_op, T0
> and the binary_operator
<plus_op, T0, T1
> template classes, work in a short while.
</p>
79 Here are the complete list of operator tags:
</p>
81 <span class=comment
>// Unary operator tags
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
>;
89 //
</span><span class=identifier
>Binary
</span><span class=keyword
>operator
</span><span class=identifier
>tags
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
>;
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
>;
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
>;
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>
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>
112 <span class=keyword
>template
</span><span class=special
><</span><span class=keyword
>typename
</span><span class=identifier
>T
</span><span class=special
>>
113 </span><span class=keyword
>struct
</span><span class=identifier
>unary_operator
</span><span class=special
><</span><span class=identifier
>negative_op
</span><span class=special
>,
</span><span class=identifier
>T
</span><span class=special
>> {
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
>& </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
>; }
121 This example is exactly what was being referred to by the first example we saw in the section on operator tags.
</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>
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>
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>
131 <span class=keyword
>template
</span><span class=special
><</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
>>
132 </span><span class=keyword
>struct
</span><span class=identifier
>binary_operator
</span><span class=special
><</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
>> {
134 </span><span class=keyword
>typedef
</span><span class=keyword
>typename
</span><span class=identifier
>higher_rank
</span><span class=special
><</span><span class=identifier
>T0
</span><span class=special
>,
</span><span class=identifier
>T1
</span><span class=special
>>::
</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
>& </span><span class=identifier
>lhs
</span><span class=special
>,
</span><span class=identifier
>T1
</span><span class=keyword
>const
</span><span class=special
>& </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
>; }
140 This example is exactly what was being referred to by the second example we saw in the section on operator tags. higher_rank
<T0, T1
> is a type computer. We shall see how this works in a short while, pardon the forward information.
</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>
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>
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">
149 <td class=
"note_box">
150 <img src=
"theme/lens.gif"></img> <b>Short Circuiting || and
&&</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
&& 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>
153 <a name=
"rank"></a><h2>rank
</h2><p>
154 rank
<T
> class has a static int constant 'value' that defines the absolute rank of a type. rank
<T
> 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>
156 <span class=keyword
>template
</span><span class=special
><> </span><span class=keyword
>struct
</span><span class=identifier
>rank
</span><span class=special
><</span><span class=keyword
>char
</span><span class=special
>> {
</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
><> </span><span class=keyword
>struct
</span><span class=identifier
>rank
</span><span class=special
><</span><span class=keyword
>signed
</span><span class=keyword
>char
</span><span class=special
>> {
</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
><> </span><span class=keyword
>struct
</span><span class=identifier
>rank
</span><span class=special
><</span><span class=keyword
>unsigned
</span><span class=keyword
>char
</span><span class=special
>> {
</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
><> </span><span class=keyword
>struct
</span><span class=identifier
>rank
</span><span class=special
><</span><span class=keyword
>wchar_t
</span><span class=special
>> {
</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
>; };
162 Take note that ranks
0.
.9999 are reserved by the framework.
</p>
164 A template type computer higher_rank
<T0, T1
> 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>
166 <span class=identifier
>higher_rank
</span><span class=special
><</span><span class=identifier
>T0
</span><span class=special
>,
</span><span class=identifier
>T1
</span><span class=special
>>::
</span><span class=identifier
>type
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>
171 <span class=identifier
>higher_rank
</span><span class=special
><</span><span class=identifier
>TA
</span><span class=special
>,
172 </span><span class=identifier
>higher_rank
</span><span class=special
><</span><span class=identifier
>TB
</span><span class=special
>,
173 </span><span class=identifier
>higher_rank
</span><span class=special
><</span><span class=identifier
>TC
</span><span class=special
>,
174 </span><span class=identifier
>higher_rank
</span><span class=special
><</span><span class=identifier
>TD
</span><span class=special
>,
</span><span class=identifier
>TE
</span><span class=special
>>::
</span><span class=identifier
>type
175 </span><span class=special
>>::
</span><span class=identifier
>type
176 </span><span class=special
>>::
</span><span class=identifier
>type
177 </span><span class=special
>>::
</span><span class=identifier
>type
179 <table width=
"80%" border=
"0" align=
"center">
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
<plus_op, T0, T1
> above.
</td>
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>
194 <p class=
"copyright">Copyright
© 2001-
2002 Joel de Guzman
<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>