1<?xml version="1.0" encoding="utf-8"?>
2<!--
3  Copyright 2012 Eric Niebler
4
5  Distributed under the Boost
6  Software License, Version 1.0. (See accompanying
7  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
8  -->
9<header name="boost/proto/transform/impl.hpp">
10  <para>Contains definition of transform&lt;&gt; and transform_impl&lt;&gt; helpers. </para>
11  <namespace name="boost">
12    <namespace name="proto">
13
14      <!-- proto::transform -->
15      <struct name="transform">
16        <template>
17          <template-type-parameter name="PrimitiveTransform"/>
18        </template>
19        <purpose>Inherit from this to make your type a <conceptname>PrimitiveTransform</conceptname>.</purpose>
20        <struct-specialization name="result">
21          <template>
22            <template-type-parameter name="This"/>
23            <template-type-parameter name="Expr"/>
24          </template>
25          <specialization>
26            <template-arg>This(Expr)</template-arg>
27          </specialization>
28          <typedef name="type">
29            <type>typename PrimitiveTransform::template impl&lt; Expr, <replaceable>unspecified</replaceable>, <replaceable>unspecified</replaceable> &gt;::result_type</type>
30          </typedef>
31        </struct-specialization>
32        <struct-specialization name="result">
33          <template>
34            <template-type-parameter name="This"/>
35            <template-type-parameter name="Expr"/>
36            <template-type-parameter name="State"/>
37          </template>
38          <specialization>
39            <template-arg>This(Expr, State)</template-arg>
40          </specialization>
41          <typedef name="type">
42            <type>typename PrimitiveTransform::template impl&lt; Expr, State, <replaceable>unspecified</replaceable> &gt;::result_type</type>
43          </typedef>
44        </struct-specialization>
45        <struct-specialization name="result">
46          <template>
47            <template-type-parameter name="This"/>
48            <template-type-parameter name="Expr"/>
49            <template-type-parameter name="State"/>
50            <template-type-parameter name="Data"/>
51          </template>
52          <specialization>
53            <template-arg>This(Expr, State, Data)</template-arg>
54          </specialization>
55          <typedef name="type">
56            <type>typename PrimitiveTransform::template impl&lt; Expr, State, Data &gt;::result_type</type>
57          </typedef>
58        </struct-specialization>
59        <typedef name="transform_type">
60          <type>PrimitiveTransform</type>
61        </typedef>
62        <method-group name="public member functions">
63          <method name="operator()" cv="const">
64            <type>typename PrimitiveTransform::template impl&lt;Expr &amp;, <replaceable>unspecified</replaceable>, <replaceable>unspecified</replaceable>&gt;::result_type</type>
65            <template>
66              <template-type-parameter name="Expr"/>
67            </template>
68            <parameter name="expr">
69              <paramtype>Expr &amp;</paramtype>
70            </parameter>
71            <returns>
72              <computeroutput>
73                typename PrimitiveTransform::template impl&lt;Expr &amp;, <replaceable>unspecified</replaceable>, <replaceable>unspecified</replaceable>&gt;()(expr, <replaceable>unspecified</replaceable>, <replaceable>unspecified</replaceable>)
74              </computeroutput>
75            </returns>
76          </method>
77          <method name="operator()" cv="const">
78            <type>typename PrimitiveTransform::template impl&lt;Expr &amp;, State &amp;, <replaceable>unspecified</replaceable>&gt;::result_type</type>
79            <template>
80              <template-type-parameter name="Expr"/>
81              <template-type-parameter name="State"/>
82            </template>
83            <parameter name="expr">
84              <paramtype>Expr &amp;</paramtype>
85            </parameter>
86            <parameter name="state">
87              <paramtype>State &amp;</paramtype>
88            </parameter>
89            <returns>
90              <computeroutput>
91                typename PrimitiveTransform::template impl&lt;Expr &amp;, State &amp;, <replaceable>unspecified</replaceable>&gt;()(expr, state, <replaceable>unspecified</replaceable>)
92              </computeroutput>
93            </returns>
94          </method>
95          <method name="operator()" cv="const">
96            <type>typename PrimitiveTransform::template impl&lt;Expr &amp;, State const &amp;, <replaceable>unspecified</replaceable>&gt;::result_type</type>
97            <template>
98              <template-type-parameter name="Expr"/>
99              <template-type-parameter name="State"/>
100            </template>
101            <parameter name="expr">
102              <paramtype>Expr &amp;</paramtype>
103            </parameter>
104            <parameter name="state">
105              <paramtype>State const &amp;</paramtype>
106            </parameter>
107            <returns>
108              <computeroutput>
109                typename PrimitiveTransform::template impl&lt;Expr &amp;, State const &amp;, <replaceable>unspecified</replaceable>&gt;()(expr, state, <replaceable>unspecified</replaceable>)
110              </computeroutput>
111            </returns>
112          </method>
113          <method name="operator()" cv="const">
114            <type>typename PrimitiveTransform::template impl&lt;Expr &amp;, State &amp;, Data &amp;&gt;::result_type</type>
115            <template>
116              <template-type-parameter name="Expr"/>
117              <template-type-parameter name="State"/>
118              <template-type-parameter name="Data"/>
119            </template>
120            <parameter name="expr">
121              <paramtype>Expr &amp;</paramtype>
122            </parameter>
123            <parameter name="state">
124              <paramtype>State &amp;</paramtype>
125            </parameter>
126            <parameter name="data">
127              <paramtype>Data &amp;</paramtype>
128            </parameter>
129            <returns>
130              <computeroutput>
131                typename PrimitiveTransform::template impl&lt;Expr &amp;, State &amp;, Data &amp;&gt;()(expr, state, data)
132              </computeroutput>
133            </returns>
134          </method>
135          <method name="operator()" cv="const">
136            <type>typename PrimitiveTransform::template impl&lt;Expr &amp;, State const &amp;, Data &amp;&gt;::result_type</type>
137            <template>
138              <template-type-parameter name="Expr"/>
139              <template-type-parameter name="State"/>
140              <template-type-parameter name="Data"/>
141            </template>
142            <parameter name="expr">
143              <paramtype>Expr &amp;</paramtype>
144            </parameter>
145            <parameter name="state">
146              <paramtype>State const &amp;</paramtype>
147            </parameter>
148            <parameter name="data">
149              <paramtype>Data &amp;</paramtype>
150            </parameter>
151            <returns>
152              <computeroutput>
153                typename PrimitiveTransform::template impl&lt;Expr &amp;, State const &amp;, Data &amp;&gt;()(expr, state, data)
154              </computeroutput>
155            </returns>
156          </method>
157        </method-group>
158      </struct>
159
160      <!-- proto::transform_impl -->
161      <struct name="transform_impl">
162        <template>
163          <template-type-parameter name="Expr"/>
164          <template-type-parameter name="State"/>
165          <template-type-parameter name="Data"/>
166        </template>
167        <typedef name="expr">
168          <type>typename boost::remove_reference&lt;Expr const&gt;::type</type>
169        </typedef>
170        <typedef name="expr_param">
171          <type>typename boost::add_reference&lt;Expr const&gt;::type</type>
172        </typedef>
173        <typedef name="state">
174          <type>typename boost::remove_reference&lt;State const&gt;::type</type>
175        </typedef>
176        <typedef name="state_param">
177          <type>typename boost::add_reference&lt;State const&gt;::type</type>
178        </typedef>
179        <typedef name="data">
180          <type>typename boost::remove_reference&lt;Data const&gt;::type</type>
181        </typedef>
182        <typedef name="data_param">
183          <type>typename boost::add_reference&lt;Data const&gt;::type</type>
184        </typedef>
185      </struct>
186
187      <!-- proto::pack -->
188      <struct name="pack">
189        <purpose>To turn an expression into a pseudo-parameter pack containing the
190        expression's children, for the purpose of expanding the pack expression within
191        a <conceptname>CallableTransform</conceptname> or
192        <conceptname>ObjectTransform</conceptname>.</purpose>
193        <description>
194          <para>
195            <computeroutput>proto::pack</computeroutput> is useful within
196            <conceptname>CallableTransform</conceptname>s and
197            <conceptname>ObjectTransform</conceptname>s when one wishes to unpack an expression
198            into a function call or an object constructor. <computeroutput>proto::pack</computeroutput>
199            turns a Proto expression into a pseudo-parameter pack, which may appear in an unpacking
200            pattern to be expanded with the "<computeroutput>...</computeroutput>" syntax.
201          </para>
202
203          <para>
204            <emphasis role="bold">Example:</emphasis>
205          </para>
206
207          <para>
208            <programlisting>// The following demonstrates how to use a pseudo-pack expansion
209// to unpack an expression into a function call.
210
211struct do_sum : <classname alt="boost::proto::callable">proto::callable</classname>
212{
213    typedef int result_type;
214
215    int operator()(int i) const { return i; }
216    int operator()(int i, int j) const { return i + j; }
217    int operator()(int i, int j, int k) const { return i + j + k; }
218};
219
220// Take any n-ary expression where the children are all int terminals and sum all the ints
221struct sum
222  : <classname alt="boost::proto::when">proto::when</classname>&lt;
223
224        // Match any nary expression where the children are all int terminals
225        <classname alt="boost::proto::nary_expr">proto::nary_expr</classname>&lt;<classname alt="boost::proto::_">_</classname>, <classname alt="boost::proto::vararg">proto::vararg</classname>&lt;<classname alt="boost::proto::terminal">proto::terminal</classname>&lt;int&gt; &gt; &gt;
226
227        // Turn the current expression into a pseudo-parameter pack, then expand it,
228        // extracting the value from each child in turn.
229      , do_sum(<classname alt="boost::proto::_value">proto::_value</classname>(proto::pack(<classname alt="boost::proto::_">_</classname>))...)
230    &gt;
231{};
232
233int main()
234{
235    <classname alt="boost::proto::terminal">proto::terminal</classname>&lt;int&gt;::type i = {42};
236    int result = sum()( i(3,5) ); // Creates a ternary functional-call expression
237    std::cout &lt;&lt; "Sum of 42, 3, and 5 : " &lt;&lt; result &lt;&lt; std::endl;
238}</programlisting>
239          </para>
240
241          <para>
242            The above program displays:
243          </para>
244
245          <para>
246            <computeroutput>Sum of 42, 3, and 5 : 50</computeroutput>
247          </para>
248
249          <para>
250            In the above example, the type
251            <computeroutput>
252              <classname alt="boost::proto::_value">proto::_value</classname>(proto::pack(<classname alt="boost::proto::_">_</classname>))
253            </computeroutput>
254            is a so-called <emphasis>unpacking pattern</emphasis>, described below.
255          </para>
256
257          <para>
258            <emphasis role="bold">Unpacking Patterns:</emphasis>
259          </para>
260
261          <para>
262            Composite transforms (either <conceptname>CallableTransform</conceptname>s or
263            <conceptname>ObjectTransform</conceptname>s) usually have the form
264            <computeroutput>X(A<subscript>0</subscript>,…A<subscript>n</subscript>)</computeroutput>.
265            However, when the argument list in a composite transform is terminated with a C-style
266            vararg ellipsis as in <computeroutput>X(A<subscript>0</subscript>,…A<subscript>n</subscript> ...)</computeroutput>,
267            the final argument <computeroutput>A<subscript>n</subscript></computeroutput> is treated
268            as an <emphasis>unpacking pattern</emphasis>.
269          </para>
270
271          <para>
272            An unpacking pattern must itself be a composite transform; that is, it must be a
273            function type representing either a <conceptname>CallableTransform</conceptname> or
274            an <conceptname>ObjectTransform</conceptname>. The type <computeroutput>proto::pack(_)</computeroutput>
275            must appear exactly once in the unpacking pattern. This type will receive a substitution
276            when the unpacking pattern is expanded.
277          </para>
278
279          <para>
280            A composite transform like <computeroutput>X(A<subscript>0</subscript>,…A<subscript>n</subscript> ...)</computeroutput>,
281            when evaluated against a given expression <replaceable>E</replaceable>, state and data, is evaluated as if it were
282            <computeroutput>X(A<subscript>0</subscript>,…A<subscript>n-1</subscript>,<replaceable>S</replaceable>)</computeroutput>
283            where <replaceable>S</replaceable> is a type sequence computed as follows:
284          </para>
285          <para>
286            Let <computeroutput><replaceable>SUB</replaceable>(A,B)</computeroutput> be a type function that replaces every occurence of
287            <computeroutput>proto::pack(_)</computeroutput> within <computeroutput>A</computeroutput> with <computeroutput>B</computeroutput>.
288            <itemizedlist>
289              <listitem>
290                If the expression <replaceable>E</replaceable> is a terminal (i.e. it has arity 0), <replaceable>S</replaceable>
291                is the one-element sequence containing <computeroutput><replaceable>SUB</replaceable>(A<subscript>n</subscript>, <classname alt="boost::proto::_value">proto::_value</classname>)</computeroutput>.
292              </listitem>
293              <listitem>
294                If the expression <replaceable>E</replaceable> is a non-terminal, <replaceable>S</replaceable> is the sequence
295                <computeroutput><replaceable>SUB</replaceable>(A<subscript>n</subscript>, <classname alt="boost::proto::_child_c">proto::_child_c</classname>&lt;0&gt;),…
296                <replaceable>SUB</replaceable>(A<subscript>n</subscript>, <classname alt="boost::proto::_child_c">proto::_child_c</classname>&lt;<replaceable>M</replaceable>-1&gt;)</computeroutput>, where
297                <replaceable>M</replaceable> is the arity of the expression <replaceable>E</replaceable>.
298              </listitem>
299            </itemizedlist>
300          </para>
301        </description>
302      </struct>
303
304    </namespace>
305  </namespace>
306</header>
307