1 <?xml version=
"1.0" encoding=
"utf-8"?>
3 Copyright 2012 Eric Niebler
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)
9 <header name=
"boost/proto/transform/make.hpp">
11 Contains definition of the
13 <classname alt=
"boost::proto::make">proto::make
<></classname>
17 <classname alt=
"boost::proto::protect">proto::protect
<></classname>
21 <namespace name=
"boost">
22 <namespace name=
"proto">
23 <struct name=
"noinvoke">
25 <template-type-parameter name=
"T"/>
27 <purpose>A type annotation in an
<conceptname>ObjectTransform
</conceptname> which instructs
28 Proto not to look for a nested
<computeroutput>::type
</computeroutput> within
29 <computeroutput>T
</computeroutput> after type substitution.
</purpose>
32 <conceptname>ObjectTransform
</conceptname>s are evaluated by
33 <computeroutput><classname alt=
"proto::make">proto::make
<></classname></computeroutput>,
34 which finds all nested transforms and replaces them with the result of their applications.
35 If any substitutions are performed, the result is first assumed to be a metafunction to be applied;
36 that is, Proto checks to see if the result has a nested
<computeroutput>::type
</computeroutput>
37 typedef. If it does, that becomes the result. The purpose of
<computeroutput>proto::noinvoke
<></computeroutput>
38 is to prevent Proto from looking for a nested
<computeroutput>::type
</computeroutput> typedef
43 <programlisting>struct Test
44 :
<classname>proto::when
</classname><
45 <classname>_
</classname>
47 // This remove_pointer invocation is bloked by noinvoke
48 boost::remove_pointer
<
49 // This add_pointer invocation is *not* blocked by noinvoke
50 boost::add_pointer
<<classname>_
</classname>>
58 typedef
<classname>proto::terminal
</classname><int
>::type Int;
62 boost::result_of
<Test(Int)
>::type
63 , boost::remove_pointer
<Int *
>
68 boost::remove_pointer
<Int *
> t = Test()(i);
73 <struct name=
"protect">
75 <template-type-parameter name=
"PrimitiveTransform"/>
77 <inherit><classname>proto::transform
</classname>< protect
<PrimitiveTransform
> ></inherit>
78 <purpose>A
<conceptname>PrimitiveTransform
</conceptname> which prevents another
79 <conceptname>PrimitiveTransform
</conceptname> from being applied in an
80 <conceptname>ObjectTransform
</conceptname>.
</purpose>
83 When building higher order transforms with
85 <classname alt=
"proto::make">proto::make
<></classname>
88 <classname alt=
"proto::lazy">proto::lazy
<></classname>
90 you sometimes would like to build types that are parameterized with Proto transforms. In such
91 lambda-style transforms, Proto will unhelpfully find all nested transforms and apply them, even
92 if you don't want them to be applied. Consider the following transform, which will replace the
93 <computeroutput>proto::_
</computeroutput> in
94 <computeroutput>Bar
<proto::_
>()
</computeroutput>
95 with
<computeroutput>proto::terminal
<int
>::type
</computeroutput>:
98 <programlisting>template
<typename T
>
103 <classname>proto::when
</classname><<classname>proto::_
</classname>, Bar
<<classname>proto::_
</classname>>()
>
106 <classname>proto::terminal
</classname><int
>::type i = {
0};
110 std::cout
<< typeid(Foo()(i)).name()
<< std::endl;
114 If you actually wanted to default-construct an object of type
115 <computeroutput>Bar
<proto::_
></computeroutput>, you would have to protect the
116 <computeroutput>_
</computeroutput> to prevent it from being applied. You can
117 use
<computeroutput>proto::protect
<></computeroutput> as follows:
120 <programlisting>// OK: replace anything with Bar
<_
>()
122 <classname>proto::when
</classname><<classname>proto::_
</classname>, Bar
<<classname>proto::protect
</classname><<classname>proto::_
</classname>> >()
>
128 <template-type-parameter name=
""/>
129 <template-type-parameter name=
""/>
130 <template-type-parameter name=
""/>
132 <typedef name=
"result_type">
133 <type>PrimitiveTransform
</type>
140 <template-type-parameter name=
"T"/>
143 <inherit><classname>proto::transform
</classname>< make
<T
> ></inherit>
145 <purpose>A
<conceptname>PrimitiveTransform
</conceptname> that computes a type by evaluating
146 any nested transforms and then constructs an object of that type.
</purpose>
150 The purpose of
<computeroutput>proto::make
<></computeroutput> is to annotate a transform as
151 an
<conceptname>ObjectTransform
</conceptname> so that
152 <computeroutput><classname alt=
"proto::when">proto::when
<></classname></computeroutput> knows
157 For the full description of the behavior of the
158 <computeroutput><classname alt=
"proto::make">proto::make
<></classname></computeroutput>
159 transform, see the documentation for the nested
160 <computeroutput><classname alt=
"proto::make::impl">proto::make::impl
<></classname></computeroutput>
167 <template-type-parameter name=
"Expr"/>
168 <template-type-parameter name=
"State"/>
169 <template-type-parameter name=
"Data"/>
171 <inherit><classname>proto::transform_impl
</classname>< Expr, State, Data
></inherit>
172 <typedef name=
"result_type">
173 <type><emphasis>see-below
</emphasis></type>
176 <computeroutput><classname>proto::make
</classname><T
>::impl
<Expr, State, Data
>::result_type
</computeroutput> is
180 If
<computeroutput>T
</computeroutput> is an
<conceptname>ObjectTransform
</conceptname> of the form
181 <computeroutput>Object(A
<subscript>0</subscript>,…A
<subscript>n
</subscript>)
</computeroutput> or
182 <computeroutput>Object(A
<subscript>0</subscript>,…A
<subscript>n
</subscript> ...)
</computeroutput>,
183 then let
<computeroutput>O
</computeroutput> be the return type
184 <computeroutput>Object
</computeroutput>. Otherwise, let
<computeroutput>O
</computeroutput>
185 be
<computeroutput>T
</computeroutput>. The
<computeroutput>result_type
</computeroutput> typedef is
186 then computed as follows:
192 If
<computeroutput><classname>proto::is_transform
</classname><O
>::value
</computeroutput> is
193 <computeroutput>true
</computeroutput>, then let the result type be
195 boost::result_of
<<classname>proto::when
</classname><<classname>_
</classname>, O
>(Expr, State, Data)
>::type
197 Note that a substitution took place.
201 If
<computeroutput>O
</computeroutput> is a template like
202 <computeroutput><classname>proto::noinvoke
</classname><S
<X
<subscript>0</subscript>,…X
<subscript>n
</subscript>> ></computeroutput>,
203 then the result type is calculated as follows:
207 For each
<computeroutput>i
</computeroutput> in
208 <computeroutput>[
0,n]
</computeroutput>, let
<computeroutput>
209 X
<subscript>i
</subscript>'
212 boost::result_of
<<classname>proto::make
</classname><X
<subscript>i
</subscript>>(Expr, State, Data)
>::type
214 (which evaluates this procedure recursively). Note that a substitution took place. (In this case,
215 Proto merely assumes that a substitution took place for the sake of compile-time efficiency. There
216 would be no reason to use
<computeroutput><classname>proto::noinvoke
<></classname></computeroutput>
224 S
<X
<subscript>0</subscript>',…X
<subscript>n
</subscript>'
>
231 If
<computeroutput>O
</computeroutput> is a template like
232 <computeroutput>S
<X
<subscript>0</subscript>,…X
<subscript>n
</subscript>></computeroutput>,
233 then the result type is calculated as follows:
237 For each
<computeroutput>i
</computeroutput> in
238 <computeroutput>[
0,n]
</computeroutput>, let
<computeroutput>
239 X
<subscript>i
</subscript>'
242 boost::result_of
<<classname>proto::make
</classname><X
<subscript>i
</subscript>>(Expr, State, Data)
>::type
244 (which evaluates this procedure recursively). Note whether any substitutions took place during
250 If any substitutions took place in the above step and
252 S
<X
<subscript>0</subscript>',…X
<subscript>n
</subscript>'
>
253 </computeroutput> has a nested
254 <computeroutput>type
</computeroutput> typedef, the result type is
256 S
<X
<subscript>0</subscript>',…X
<subscript>n
</subscript>'
>::type
262 Otherwise, the result type is
264 S
<X
<subscript>0</subscript>',…X
<subscript>n
</subscript>'
>
271 Otherwise, the result type is
<computeroutput>O
</computeroutput>, and note that no
272 substitution took place.
277 Note that
<computeroutput><classname alt=
"proto::when">proto::when
<></classname></computeroutput> is implemented
278 in terms of
<computeroutput><classname alt=
"proto::call">proto::call
<></classname></computeroutput>
279 and
<computeroutput><classname alt=
"proto::make">proto::make
<></classname></computeroutput>, so the
280 above procedure is evaluated recursively.
284 <method-group name=
"public member functions">
285 <method name=
"operator()" cv=
"const">
286 <type>result_type
</type>
287 <parameter name=
"expr">
288 <paramtype>typename impl::expr_param
</paramtype>
290 <parameter name=
"state">
291 <paramtype>typename impl::state_param
</paramtype>
293 <parameter name=
"data">
294 <paramtype>typename impl::data_param
</paramtype>
299 <classname>proto::make
</classname><T
>::impl
<Expr,State,Data
>::operator()
307 If
<computeroutput>T
</computeroutput> is of the form
308 <computeroutput>O(A
<subscript>0</subscript>,…A
<subscript>n
</subscript>)
</computeroutput>, then:
314 <classname>proto::is_aggregate
</classname><result_type
>::value
315 </computeroutput> is
<computeroutput>true
</computeroutput>, then construct
316 and return an object
<computeroutput>that
</computeroutput> as follows:
317 <programlisting>result_type that = {
318 <classname>proto::when
</classname><<classname>_
</classname>, A
<subscript>0</subscript>>()(expr, state, data),
320 <classname>proto::when
</classname><<classname>_
</classname>, A
<subscript>n
</subscript>>()(expr, state, data)
327 and return an object
<computeroutput>that
</computeroutput> as follows:
328 <programlisting>result_type that(
329 <classname>proto::when
</classname><<classname>_
</classname>, A
<subscript>0</subscript>>()(expr, state, data),
331 <classname>proto::when
</classname><<classname>_
</classname>, A
<subscript>n
</subscript>>()(expr, state, data)
339 If
<computeroutput>T
</computeroutput> is of the form
340 <computeroutput>O(A
<subscript>0</subscript>,…A
<subscript>n
</subscript> ...)
</computeroutput>,
341 then let
<computeroutput>T
'</computeroutput> be
<computeroutput>O(A
<subscript>0</subscript>,…A
<subscript>n-
1</subscript>,
<replaceable>S
</replaceable>)
</computeroutput>,
342 where
<replaceable>S
</replaceable> is a type sequence computed from the unpacking expression
<computeroutput>A
<subscript>n
</subscript></computeroutput>
343 as described in the reference for
<computeroutput><classname>proto::pack
</classname></computeroutput>. Then, return:
344 <programlisting>proto::make
<T
'>()(expr, state, data)
</programlisting>
349 Otherwise, construct and return an object
<computeroutput>that
</computeroutput>
350 as follows:
<programlisting>result_type that = result_type();
</programlisting>