1<html> 2<head> 3<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> 4<title>Extending Actors</title> 5<link rel="stylesheet" href="../../../../../../doc/src/boostbook.css" type="text/css"> 6<meta name="generator" content="DocBook XSL Stylesheets V1.79.1"> 7<link rel="home" href="../../index.html" title="Chapter 1. Phoenix 3.2.0"> 8<link rel="up" href="../examples.html" title="Advanced Examples"> 9<link rel="prev" href="../examples.html" title="Advanced Examples"> 10<link rel="next" href="adding_an_expression.html" title="Adding an expression"> 11</head> 12<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"> 13<table cellpadding="2" width="100%"><tr> 14<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../boost.png"></td> 15<td align="center"><a href="../../../../../../index.html">Home</a></td> 16<td align="center"><a href="../../../../../../libs/libraries.htm">Libraries</a></td> 17<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td> 18<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td> 19<td align="center"><a href="../../../../../../more/index.htm">More</a></td> 20</tr></table> 21<hr> 22<div class="spirit-nav"> 23<a accesskey="p" href="../examples.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../examples.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="adding_an_expression.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a> 24</div> 25<div class="section"> 26<div class="titlepage"><div><div><h3 class="title"> 27<a name="phoenix.examples.extending_actors"></a><a class="link" href="extending_actors.html" title="Extending Actors">Extending Actors</a> 28</h3></div></div></div> 29<p> 30 <a class="link" href="../inside/actor.html" title="Actors in Detail">Actors</a> are one of the main parts 31 of the library, and one of the many customization points. The default actor 32 implementation provides several operator() overloads which deal with the 33 evaluation of expressions. 34 </p> 35<p> 36 For some use cases this might not be enough. For convenience it is thinkable 37 to provide custom member functions which generate new expressions. An example 38 is the <a class="link" href="../modules/statement/___if_else_____statement.html" title="if_else_ Statement">if_else_ 39Statement</a> 40 which provides an additional else member for generating a lazy if-else expression. 41 With this the actual Phoenix expression becomes more expressive. 42 </p> 43<p> 44 Another scenario is to give actors the semantics of a certain well known 45 interface or concept. This tutorial like section will provide information 46 on how to implement a custom actor which is usable as if it were a <a href="http://www.sgi.com/tech/stl/Container.html" target="_top">STL Container</a>. 47 </p> 48<h5> 49<a name="phoenix.examples.extending_actors.h0"></a> 50 <span class="phrase"><a name="phoenix.examples.extending_actors.requirements"></a></span><a class="link" href="extending_actors.html#phoenix.examples.extending_actors.requirements">Requirements</a> 51 </h5> 52<p> 53 Let's repeat what we want to have: 54 </p> 55<div class="informaltable"><table class="table"> 56<colgroup> 57<col> 58<col> 59</colgroup> 60<thead><tr> 61<th> 62 <p> 63 Expression 64 </p> 65 </th> 66<th> 67 <p> 68 Semantics 69 </p> 70 </th> 71</tr></thead> 72<tbody> 73<tr> 74<td> 75 <p> 76 <code class="computeroutput"><span class="identifier">a</span><span class="special">.</span><span class="identifier">begin</span><span class="special">()</span></code> 77 </p> 78 </td> 79<td> 80 <p> 81 Returns an iterator pointing to the first element in the container. 82 </p> 83 </td> 84</tr> 85<tr> 86<td> 87 <p> 88 <code class="computeroutput"><span class="identifier">a</span><span class="special">.</span><span class="identifier">end</span><span class="special">()</span></code> 89 </p> 90 </td> 91<td> 92 <p> 93 Returns an iterator pointing one past the last element in the container. 94 </p> 95 </td> 96</tr> 97<tr> 98<td> 99 <p> 100 <code class="computeroutput"><span class="identifier">a</span><span class="special">.</span><span class="identifier">size</span><span class="special">()</span></code> 101 </p> 102 </td> 103<td> 104 <p> 105 Returns the size of the container, that is, its number of elements. 106 </p> 107 </td> 108</tr> 109<tr> 110<td> 111 <p> 112 <code class="computeroutput"><span class="identifier">a</span><span class="special">.</span><span class="identifier">max_size</span><span class="special">()</span></code> 113 </p> 114 </td> 115<td> 116 <p> 117 Returns the largest size that this container can ever have. 118 </p> 119 </td> 120</tr> 121<tr> 122<td> 123 <p> 124 <code class="computeroutput"><span class="identifier">a</span><span class="special">.</span><span class="identifier">empty</span><span class="special">()</span></code> 125 </p> 126 </td> 127<td> 128 <p> 129 Equivalent to a.size() == 0. (But possibly faster.) 130 </p> 131 </td> 132</tr> 133<tr> 134<td> 135 <p> 136 <code class="computeroutput"><span class="identifier">a</span><span class="special">.</span><span class="identifier">swap</span><span class="special">(</span><span class="identifier">b</span><span class="special">)</span></code> 137 </p> 138 </td> 139<td> 140 <p> 141 Equivalent to swap(a,b) 142 </p> 143 </td> 144</tr> 145</tbody> 146</table></div> 147<p> 148 Additionally, we want all the operator() overloads of the regular actor. 149 </p> 150<h5> 151<a name="phoenix.examples.extending_actors.h1"></a> 152 <span class="phrase"><a name="phoenix.examples.extending_actors.defining_the_actor"></a></span><a class="link" href="extending_actors.html#phoenix.examples.extending_actors.defining_the_actor">Defining the 153 actor</a> 154 </h5> 155<p> 156 The first version of our <code class="computeroutput"><span class="identifier">container_actor</span></code> 157 interface will show the general principle. This will be continually extended. 158 For the sake of simplicity, every member function generator will return 159 <a class="link" href="../modules/core/nothing.html" title="Nothing"><code class="computeroutput"><span class="identifier">nothing</span></code></a> 160 at first. 161 </p> 162<pre class="programlisting"><span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">Expr</span><span class="special">></span> 163<span class="keyword">struct</span> <span class="identifier">container_actor</span> 164 <span class="special">:</span> <span class="identifier">actor</span><span class="special"><</span><span class="identifier">Expr</span><span class="special">></span> 165<span class="special">{</span> 166 <span class="keyword">typedef</span> <span class="identifier">actor</span><span class="special"><</span><span class="identifier">Expr</span><span class="special">></span> <span class="identifier">base_type</span><span class="special">;</span> 167 <span class="keyword">typedef</span> <span class="identifier">container_actor</span><span class="special"><</span><span class="identifier">Expr</span><span class="special">></span> <span class="identifier">that_type</span><span class="special">;</span> 168 169 <span class="identifier">container_actor</span><span class="special">(</span> <span class="identifier">base_type</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">base</span> <span class="special">)</span> 170 <span class="special">:</span> <span class="identifier">base_type</span><span class="special">(</span> <span class="identifier">base</span> <span class="special">)</span> <span class="special">{}</span> 171 172 <span class="identifier">expression</span><span class="special">::</span><span class="identifier">null</span><span class="special"><</span><span class="identifier">mpl</span><span class="special">::</span><span class="identifier">void_</span><span class="special">>::</span><span class="identifier">type</span> <span class="keyword">const</span> <span class="identifier">begin</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">{</span> <span class="keyword">return</span> <span class="identifier">nothing</span><span class="special">;</span> <span class="special">}</span> 173 <span class="identifier">expression</span><span class="special">::</span><span class="identifier">null</span><span class="special"><</span><span class="identifier">mpl</span><span class="special">::</span><span class="identifier">void_</span><span class="special">>::</span><span class="identifier">type</span> <span class="keyword">const</span> <span class="identifier">end</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">{</span> <span class="keyword">return</span> <span class="identifier">nothing</span><span class="special">;</span> <span class="special">}</span> 174 <span class="identifier">expression</span><span class="special">::</span><span class="identifier">null</span><span class="special"><</span><span class="identifier">mpl</span><span class="special">::</span><span class="identifier">void_</span><span class="special">>::</span><span class="identifier">type</span> <span class="keyword">const</span> <span class="identifier">size</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">{</span> <span class="keyword">return</span> <span class="identifier">nothing</span><span class="special">;</span> <span class="special">}</span> 175 <span class="identifier">expression</span><span class="special">::</span><span class="identifier">null</span><span class="special"><</span><span class="identifier">mpl</span><span class="special">::</span><span class="identifier">void_</span><span class="special">>::</span><span class="identifier">type</span> <span class="keyword">const</span> <span class="identifier">max_size</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">{</span> <span class="keyword">return</span> <span class="identifier">nothing</span><span class="special">;</span> <span class="special">}</span> 176 <span class="identifier">expression</span><span class="special">::</span><span class="identifier">null</span><span class="special"><</span><span class="identifier">mpl</span><span class="special">::</span><span class="identifier">void_</span><span class="special">>::</span><span class="identifier">type</span> <span class="keyword">const</span> <span class="identifier">empty</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">{</span> <span class="keyword">return</span> <span class="identifier">nothing</span><span class="special">;</span> <span class="special">}</span> 177 178 <span class="comment">// Note that swap is the only function needing another container.</span> 179 <span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">Container</span><span class="special">></span> 180 <span class="identifier">expression</span><span class="special">::</span><span class="identifier">null</span><span class="special"><</span><span class="identifier">mpl</span><span class="special">::</span><span class="identifier">void_</span><span class="special">>::</span><span class="identifier">type</span> <span class="keyword">const</span> <span class="identifier">swap</span><span class="special">(</span> <span class="identifier">actor</span><span class="special"><</span><span class="identifier">Container</span><span class="special">></span> <span class="keyword">const</span><span class="special">&</span> <span class="special">)</span> <span class="keyword">const</span> <span class="special">{</span> <span class="keyword">return</span> <span class="identifier">nothing</span><span class="special">;</span> <span class="special">}</span> 181<span class="special">};</span> 182</pre> 183<h5> 184<a name="phoenix.examples.extending_actors.h2"></a> 185 <span class="phrase"><a name="phoenix.examples.extending_actors.using_the_actor"></a></span><a class="link" href="extending_actors.html#phoenix.examples.extending_actors.using_the_actor">Using 186 the actor</a> 187 </h5> 188<p> 189 Although the member functions do nothing right now, we want to test if we 190 can use our new actor. 191 </p> 192<p> 193 First, lets create a generator which wraps the <code class="computeroutput"><span class="identifier">container_actor</span></code> 194 around any other expression: 195 </p> 196<pre class="programlisting"><span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">Expr</span><span class="special">></span> 197<span class="identifier">container_actor</span><span class="special"><</span><span class="identifier">Expr</span><span class="special">></span> <span class="keyword">const</span> 198<span class="identifier">container</span><span class="special">(</span> <span class="identifier">actor</span><span class="special"><</span><span class="identifier">Expr</span><span class="special">></span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">expr</span> <span class="special">)</span> 199<span class="special">{</span> 200 <span class="keyword">return</span> <span class="identifier">expr</span><span class="special">;</span> 201<span class="special">}</span> 202</pre> 203<p> 204 Now let's test this: 205 </p> 206<pre class="programlisting"><span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special"><</span><span class="keyword">int</span><span class="special">></span> <span class="identifier">v</span><span class="special">;</span> 207<span class="identifier">v</span><span class="special">.</span><span class="identifier">push_back</span><span class="special">(</span><span class="number">0</span><span class="special">);</span> 208<span class="identifier">v</span><span class="special">.</span><span class="identifier">push_back</span><span class="special">(</span><span class="number">1</span><span class="special">);</span> 209<span class="identifier">v</span><span class="special">.</span><span class="identifier">push_back</span><span class="special">(</span><span class="number">2</span><span class="special">);</span> 210<span class="identifier">v</span><span class="special">.</span><span class="identifier">push_back</span><span class="special">(</span><span class="number">3</span><span class="special">);</span> 211 212<span class="special">(</span><span class="identifier">container</span><span class="special">(</span><span class="identifier">arg1</span><span class="special">).</span><span class="identifier">size</span><span class="special">())(</span><span class="identifier">v</span><span class="special">);</span> 213</pre> 214<p> 215 Granted, this is not really elegant and not very practical (we could have 216 just used phoenix::begin(v) from the <a class="link" href="../modules/stl/algorithm.html" title="Algorithm">Phoenix 217 algorithm module</a>, but we can do better. 218 </p> 219<p> 220 Let's have an <a class="link" href="../modules/core/arguments.html" title="Arguments">argument placeholder</a> 221 which is usable as if it was a STL container: 222 </p> 223<pre class="programlisting"><span class="identifier">container_actor</span><span class="special"><</span><span class="identifier">expression</span><span class="special">::</span><span class="identifier">argument</span><span class="special"><</span><span class="number">1</span><span class="special">>::</span><span class="identifier">type</span><span class="special">></span> <span class="keyword">const</span> <span class="identifier">con1</span><span class="special">;</span> 224<span class="comment">// and so on ...</span> 225</pre> 226<p> 227 The above example can be rewritten as: 228 </p> 229<pre class="programlisting"><span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special"><</span><span class="keyword">int</span><span class="special">></span> <span class="identifier">v</span><span class="special">;</span> 230<span class="identifier">v</span><span class="special">.</span><span class="identifier">push_back</span><span class="special">(</span><span class="number">0</span><span class="special">);</span> 231<span class="identifier">v</span><span class="special">.</span><span class="identifier">push_back</span><span class="special">(</span><span class="number">1</span><span class="special">);</span> 232<span class="identifier">v</span><span class="special">.</span><span class="identifier">push_back</span><span class="special">(</span><span class="number">2</span><span class="special">);</span> 233<span class="identifier">v</span><span class="special">.</span><span class="identifier">push_back</span><span class="special">(</span><span class="number">3</span><span class="special">);</span> 234 235<span class="special">(</span><span class="identifier">con1</span><span class="special">.</span><span class="identifier">size</span><span class="special">())(</span><span class="identifier">v</span><span class="special">);</span> 236</pre> 237<p> 238 Wow, that was easy! 239 </p> 240<h5> 241<a name="phoenix.examples.extending_actors.h3"></a> 242 <span class="phrase"><a name="phoenix.examples.extending_actors.adding_life_to_the_actor"></a></span><a class="link" href="extending_actors.html#phoenix.examples.extending_actors.adding_life_to_the_actor">Adding 243 life to the actor</a> 244 </h5> 245<p> 246 This one will be even easier! 247 </p> 248<p> 249 First, we define a <a class="link" href="../modules/function.html" title="Function">lazy function</a> 250 which evaluates the expression we want to implement. Following is the implementation 251 of the size function: 252 </p> 253<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">size_impl</span> 254<span class="special">{</span> 255 <span class="comment">// result_of protocol:</span> 256 <span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">Sig</span><span class="special">></span> 257 <span class="keyword">struct</span> <span class="identifier">result</span><span class="special">;</span> 258 259 <span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">This</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Container</span><span class="special">></span> 260 <span class="keyword">struct</span> <span class="identifier">result</span><span class="special"><</span><span class="identifier">This</span><span class="special">(</span><span class="identifier">Container</span><span class="special">)></span> 261 <span class="special">{</span> 262 <span class="comment">// Note, remove reference here, because Container can be anything</span> 263 <span class="keyword">typedef</span> <span class="keyword">typename</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">remove_reference</span><span class="special"><</span><span class="identifier">Container</span><span class="special">>::</span><span class="identifier">type</span> <span class="identifier">container_type</span><span class="special">;</span> 264 265 <span class="comment">// The result will be size_type</span> 266 <span class="keyword">typedef</span> <span class="keyword">typename</span> <span class="identifier">container_type</span><span class="special">::</span><span class="identifier">size_type</span> <span class="identifier">type</span><span class="special">;</span> 267 <span class="special">};</span> 268 269 <span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">Container</span><span class="special">></span> 270 <span class="keyword">typename</span> <span class="identifier">result</span><span class="special"><</span><span class="identifier">size_impl</span><span class="special">(</span><span class="identifier">Container</span> <span class="keyword">const</span><span class="special">&)>::</span><span class="identifier">type</span> 271 <span class="keyword">operator</span><span class="special">()(</span><span class="identifier">Container</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">container</span><span class="special">)</span> <span class="keyword">const</span> 272 <span class="special">{</span> 273 <span class="keyword">return</span> <span class="identifier">container</span><span class="special">.</span><span class="identifier">size</span><span class="special">();</span> 274 <span class="special">}</span> 275<span class="special">};</span> 276</pre> 277<p> 278 Good, this was the first part. The second part will be to implement the size 279 member function of <code class="computeroutput"><span class="identifier">container_actor</span></code>: 280 </p> 281<pre class="programlisting"><span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">Expr</span><span class="special">></span> 282<span class="keyword">struct</span> <span class="identifier">container_actor</span> 283 <span class="special">:</span> <span class="identifier">actor</span><span class="special"><</span><span class="identifier">Expr</span><span class="special">></span> 284<span class="special">{</span> 285 <span class="keyword">typedef</span> <span class="identifier">actor</span><span class="special"><</span><span class="identifier">Expr</span><span class="special">></span> <span class="identifier">base_type</span><span class="special">;</span> 286 <span class="keyword">typedef</span> <span class="identifier">container_actor</span><span class="special"><</span><span class="identifier">Expr</span><span class="special">></span> <span class="identifier">that_type</span><span class="special">;</span> 287 288 <span class="identifier">container_actor</span><span class="special">(</span> <span class="identifier">base_type</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">base</span> <span class="special">)</span> 289 <span class="special">:</span> <span class="identifier">base_type</span><span class="special">(</span> <span class="identifier">base</span> <span class="special">)</span> <span class="special">{}</span> 290 291 <span class="keyword">typename</span> <span class="identifier">expression</span><span class="special">::</span><span class="identifier">function</span><span class="special"><</span><span class="identifier">size_impl</span><span class="special">,</span> <span class="identifier">that_type</span><span class="special">>::</span><span class="identifier">type</span> <span class="keyword">const</span> 292 <span class="identifier">size</span><span class="special">()</span> <span class="keyword">const</span> 293 <span class="special">{</span> 294 <span class="identifier">function</span><span class="special"><</span><span class="identifier">size_impl</span><span class="special">></span> <span class="keyword">const</span> <span class="identifier">f</span> <span class="special">=</span> <span class="identifier">size_impl</span><span class="special">();</span> 295 <span class="keyword">return</span> <span class="identifier">f</span><span class="special">(*</span><span class="keyword">this</span><span class="special">);</span> 296 <span class="special">}</span> 297 298 <span class="comment">// the rest ...</span> 299<span class="special">};</span> 300</pre> 301<p> 302 It is left as an exercise to the user to implement the missing parts by reusing 303 functions from the <a class="link" href="../modules/stl/algorithm.html" title="Algorithm">Phoenix 304 Algorithm Module</a> (the impatient take a look here: <a href="../../../../example/container_actor.cpp" target="_top">container_actor.cpp</a>). 305 </p> 306</div> 307<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr> 308<td align="left"></td> 309<td align="right"><div class="copyright-footer">Copyright © 2002-2005, 2010, 2014, 2015 Joel de Guzman, Dan Marsden, Thomas 310 Heller, John Fletcher<p> 311 Distributed under the Boost Software License, Version 1.0. (See accompanying 312 file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>) 313 </p> 314</div></td> 315</tr></table> 316<hr> 317<div class="spirit-nav"> 318<a accesskey="p" href="../examples.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../examples.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="adding_an_expression.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a> 319</div> 320</body> 321</html> 322