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/make.hpp"> 10 <para> 11 Contains definition of the 12 <computeroutput> 13 <classname alt="boost::proto::make">proto::make<></classname> 14 </computeroutput> 15 and 16 <computeroutput> 17 <classname alt="boost::proto::protect">proto::protect<></classname> 18 </computeroutput> 19 transforms. 20 </para> 21 <namespace name="boost"> 22 <namespace name="proto"> 23 <struct name="noinvoke"> 24 <template> 25 <template-type-parameter name="T"/> 26 </template> 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> 30 <description> 31 <para> 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 39 in these situations. 40 </para> 41 <para> 42 Example: 43 <programlisting>struct Test 44 : <classname>proto::when</classname>< 45 <classname>_</classname> 46 , proto::noinvoke< 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>> 51 > 52 >() 53 > 54{}; 55 56void test_noinvoke() 57{ 58 typedef <classname>proto::terminal</classname><int>::type Int; 59 60 BOOST_MPL_ASSERT(( 61 boost::is_same< 62 boost::result_of<Test(Int)>::type 63 , boost::remove_pointer<Int *> 64 > 65 )); 66 67 Int i = {42}; 68 boost::remove_pointer<Int *> t = Test()(i); 69}</programlisting> 70 </para> 71 </description> 72 </struct> 73 <struct name="protect"> 74 <template> 75 <template-type-parameter name="PrimitiveTransform"/> 76 </template> 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> 81 <description> 82 <para> 83 When building higher order transforms with 84 <computeroutput> 85 <classname alt="proto::make">proto::make<></classname> 86 </computeroutput> or 87 <computeroutput> 88 <classname alt="proto::lazy">proto::lazy<></classname> 89 </computeroutput>, 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>: 96 </para> 97 <para> 98 <programlisting>template<typename T> 99struct Bar 100{}; 101 102struct Foo : 103 <classname>proto::when</classname><<classname>proto::_</classname>, Bar<<classname>proto::_</classname>>() > 104{}; 105 106<classname>proto::terminal</classname><int>::type i = {0}; 107 108int main() { 109 Foo()(i); 110 std::cout << typeid(Foo()(i)).name() << std::endl; 111}</programlisting> 112 </para> 113 <para> 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: 118 </para> 119 <para> 120 <programlisting>// OK: replace anything with Bar<_>() 121struct Foo : 122 <classname>proto::when</classname><<classname>proto::_</classname>, Bar<<classname>proto::protect</classname><<classname>proto::_</classname>> >() > 123{};</programlisting> 124 </para> 125 </description> 126 <struct name="impl"> 127 <template> 128 <template-type-parameter name=""/> 129 <template-type-parameter name=""/> 130 <template-type-parameter name=""/> 131 </template> 132 <typedef name="result_type"> 133 <type>PrimitiveTransform</type> 134 </typedef> 135 </struct> 136 </struct> 137 138 <struct name="make"> 139 <template> 140 <template-type-parameter name="T"/> 141 </template> 142 143 <inherit><classname>proto::transform</classname>< make<T> ></inherit> 144 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> 147 148 <description> 149 <para> 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 153 how to apply it. 154 </para> 155 156 <para> 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> 161 class template. 162 </para> 163 </description> 164 165 <struct name="impl"> 166 <template> 167 <template-type-parameter name="Expr"/> 168 <template-type-parameter name="State"/> 169 <template-type-parameter name="Data"/> 170 </template> 171 <inherit><classname>proto::transform_impl</classname>< Expr, State, Data ></inherit> 172 <typedef name="result_type"> 173 <type><emphasis>see-below</emphasis></type> 174 <description> 175 <para> 176 <computeroutput><classname>proto::make</classname><T>::impl<Expr, State, Data>::result_type</computeroutput> is 177 computed as follows: 178 </para> 179 <para> 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: 187 </para> 188 <para> 189 <itemizedlist> 190 <listitem> 191 <para> 192 If <computeroutput><classname>proto::is_transform</classname><O>::value</computeroutput> is 193 <computeroutput>true</computeroutput>, then let the result type be 194 <computeroutput> 195 boost::result_of<<classname>proto::when</classname><<classname>_</classname>, O>(Expr, State, Data)>::type 196 </computeroutput>. 197 Note that a substitution took place. 198 </para> 199 </listitem> 200 <listitem> 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: 204 <itemizedlist> 205 <listitem> 206 <para> 207 For each <computeroutput>i</computeroutput> in 208 <computeroutput>[0,n]</computeroutput>, let <computeroutput> 209 X<subscript>i</subscript>' 210 </computeroutput> be 211 <computeroutput> 212 boost::result_of<<classname>proto::make</classname><X<subscript>i</subscript>>(Expr, State, Data)>::type 213 </computeroutput> 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> 217 otherwise.) 218 </para> 219 </listitem> 220 <listitem> 221 <para> 222 The result type is 223 <computeroutput> 224 S<X<subscript>0</subscript>',…X<subscript>n</subscript>'> 225 </computeroutput>. 226 </para> 227 </listitem> 228 </itemizedlist> 229 </listitem> 230 <listitem> 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: 234 <itemizedlist> 235 <listitem> 236 <para> 237 For each <computeroutput>i</computeroutput> in 238 <computeroutput>[0,n]</computeroutput>, let <computeroutput> 239 X<subscript>i</subscript>' 240 </computeroutput> be 241 <computeroutput> 242 boost::result_of<<classname>proto::make</classname><X<subscript>i</subscript>>(Expr, State, Data)>::type 243 </computeroutput> 244 (which evaluates this procedure recursively). Note whether any substitutions took place during 245 this operation. 246 </para> 247 </listitem> 248 <listitem> 249 <para> 250 If any substitutions took place in the above step and 251 <computeroutput> 252 S<X<subscript>0</subscript>',…X<subscript>n</subscript>'> 253 </computeroutput> has a nested 254 <computeroutput>type</computeroutput> typedef, the result type is 255 <computeroutput> 256 S<X<subscript>0</subscript>',…X<subscript>n</subscript>'>::type 257 </computeroutput>. 258 </para> 259 </listitem> 260 <listitem> 261 <para> 262 Otherwise, the result type is 263 <computeroutput> 264 S<X<subscript>0</subscript>',…X<subscript>n</subscript>'> 265 </computeroutput>. 266 </para> 267 </listitem> 268 </itemizedlist> 269 </listitem> 270 <listitem> 271 Otherwise, the result type is <computeroutput>O</computeroutput>, and note that no 272 substitution took place. 273 </listitem> 274 </itemizedlist> 275 </para> 276 <para> 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. 281 </para> 282 </description> 283 </typedef> 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> 289 </parameter> 290 <parameter name="state"> 291 <paramtype>typename impl::state_param</paramtype> 292 </parameter> 293 <parameter name="data"> 294 <paramtype>typename impl::data_param</paramtype> 295 </parameter> 296 <description> 297 <para> 298 <computeroutput> 299 <classname>proto::make</classname><T>::impl<Expr,State,Data>::operator() 300 </computeroutput> 301 behaves as follows: 302 </para> 303 <para> 304 <itemizedlist> 305 <listitem> 306 <para> 307 If <computeroutput>T</computeroutput> is of the form 308 <computeroutput>O(A<subscript>0</subscript>,…A<subscript>n</subscript>)</computeroutput>, then: 309 </para> 310 <itemizedlist> 311 <listitem> 312 <para> 313 If <computeroutput> 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), 319 … 320 <classname>proto::when</classname><<classname>_</classname>, A<subscript>n</subscript>>()(expr, state, data) 321};</programlisting> 322 </para> 323 </listitem> 324 <listitem> 325 <para> 326 Otherwise, construct 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), 330 … 331 <classname>proto::when</classname><<classname>_</classname>, A<subscript>n</subscript>>()(expr, state, data) 332);</programlisting> 333 </para> 334 </listitem> 335 </itemizedlist> 336 </listitem> 337 <listitem> 338 <para> 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> 345 </para> 346 </listitem> 347 <listitem> 348 <para> 349 Otherwise, construct and return an object <computeroutput>that</computeroutput> 350 as follows: <programlisting>result_type that = result_type();</programlisting> 351 </para> 352 </listitem> 353 </itemizedlist> 354 </para> 355 </description> 356 </method> 357 </method-group> 358 </struct> 359 </struct> 360 </namespace> 361 </namespace> 362</header> 363