1 /////////////////////////////////////////////////////////////////////////////// 2 /// \file generate.hpp 3 /// Contains definition of generate\<\> class template, which end users can 4 /// specialize for generating domain-specific expression wrappers. 5 // 6 // Copyright 2008 Eric Niebler. Distributed under the Boost 7 // Software License, Version 1.0. (See accompanying file 8 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 9 10 #ifndef BOOST_PROTO_GENERATE_HPP_EAN_02_13_2007 11 #define BOOST_PROTO_GENERATE_HPP_EAN_02_13_2007 12 13 #include <boost/config.hpp> 14 #include <boost/version.hpp> 15 #include <boost/preprocessor/cat.hpp> 16 #include <boost/preprocessor/iteration/iterate.hpp> 17 #include <boost/preprocessor/facilities/intercept.hpp> 18 #include <boost/preprocessor/repetition/enum_params.hpp> 19 #include <boost/preprocessor/repetition/enum_binary_params.hpp> 20 #include <boost/preprocessor/repetition/enum_trailing_params.hpp> 21 #include <boost/mpl/bool.hpp> 22 #include <boost/utility/enable_if.hpp> 23 #include <boost/utility/result_of.hpp> 24 #include <boost/proto/proto_fwd.hpp> 25 #include <boost/proto/args.hpp> 26 27 #if defined(_MSC_VER) 28 # pragma warning(push) 29 # pragma warning(disable : 4714) // function 'xxx' marked as __forceinline not inlined 30 #endif 31 32 namespace boost { namespace proto 33 { 34 35 namespace detail 36 { 37 template<typename Expr> 38 struct by_value_generator_; 39 40 template<typename Tag, typename Arg> 41 struct by_value_generator_<proto::expr<Tag, term<Arg>, 0> > 42 { 43 typedef 44 proto::expr< 45 Tag 46 , term<typename detail::term_traits<Arg>::value_type> 47 , 0 48 > 49 type; 50 51 BOOST_FORCEINLINE callboost::proto::detail::by_value_generator_52 static type const call(proto::expr<Tag, term<Arg>, 0> const &e) 53 { 54 type that = {e.child0}; 55 return that; 56 } 57 }; 58 59 template<typename Tag, typename Arg> 60 struct by_value_generator_<proto::basic_expr<Tag, term<Arg>, 0> > 61 { 62 typedef 63 proto::basic_expr< 64 Tag 65 , term<typename detail::term_traits<Arg>::value_type> 66 , 0 67 > 68 type; 69 70 BOOST_FORCEINLINE callboost::proto::detail::by_value_generator_71 static type const call(proto::basic_expr<Tag, term<Arg>, 0> const &e) 72 { 73 type that = {e.child0}; 74 return that; 75 } 76 }; 77 78 // Include the other specializations of by_value_generator_ 79 #include <boost/proto/detail/generate_by_value.hpp> 80 } 81 82 /// \brief Annotate a generator to indicate that it would 83 /// prefer to be passed instances of \c proto::basic_expr\<\> rather 84 /// than \c proto::expr\<\>. <tt>use_basic_expr\<Generator\></tt> is 85 /// itself a generator. 86 /// 87 template<typename Generator> 88 struct use_basic_expr 89 : Generator 90 { 91 BOOST_PROTO_USE_BASIC_EXPR() 92 }; 93 94 /// \brief A simple generator that passes an expression 95 /// through unchanged. 96 /// 97 /// Generators are intended for use as the first template parameter 98 /// to the \c domain\<\> class template and control if and how 99 /// expressions within that domain are to be customized. 100 /// The \c default_generator makes no modifications to the expressions 101 /// passed to it. 102 struct default_generator 103 { 104 BOOST_PROTO_CALLABLE() 105 106 template<typename Sig> 107 struct result; 108 109 template<typename This, typename Expr> 110 struct result<This(Expr)> 111 { 112 typedef Expr type; 113 }; 114 115 /// \param expr A Proto expression 116 /// \return expr 117 template<typename Expr> 118 BOOST_FORCEINLINE BOOST_PROTO_RETURN_TYPE_STRICT_LOOSEboost::proto::default_generator119 BOOST_PROTO_RETURN_TYPE_STRICT_LOOSE(Expr, Expr const &) 120 operator ()(Expr const &e) const 121 { 122 return e; 123 } 124 }; 125 126 /// \brief A simple generator that passes an expression 127 /// through unchanged and specifies a preference for 128 /// \c proto::basic_expr\<\> over \c proto::expr\<\>. 129 /// 130 /// Generators are intended for use as the first template parameter 131 /// to the \c domain\<\> class template and control if and how 132 /// expressions within that domain are to be customized. 133 /// The \c default_generator makes no modifications to the expressions 134 /// passed to it. 135 struct basic_default_generator 136 : proto::use_basic_expr<default_generator> 137 {}; 138 139 /// \brief A generator that wraps expressions passed 140 /// to it in the specified extension wrapper. 141 /// 142 /// Generators are intended for use as the first template parameter 143 /// to the \c domain\<\> class template and control if and how 144 /// expressions within that domain are to be customized. 145 /// \c generator\<\> wraps each expression passed to it in 146 /// the \c Extends\<\> wrapper. 147 template<template<typename> class Extends> 148 struct generator 149 { 150 BOOST_PROTO_CALLABLE() 151 BOOST_PROTO_USE_BASIC_EXPR() 152 153 template<typename Sig> 154 struct result; 155 156 template<typename This, typename Expr> 157 struct result<This(Expr)> 158 { 159 typedef Extends<Expr> type; 160 }; 161 162 template<typename This, typename Expr> 163 struct result<This(Expr &)> 164 { 165 typedef Extends<Expr> type; 166 }; 167 168 template<typename This, typename Expr> 169 struct result<This(Expr const &)> 170 { 171 typedef Extends<Expr> type; 172 }; 173 174 /// \param expr A Proto expression 175 /// \return Extends<Expr>(expr) 176 template<typename Expr> 177 BOOST_FORCEINLINE operator ()boost::proto::generator178 Extends<Expr> operator ()(Expr const &e) const 179 { 180 return Extends<Expr>(e); 181 } 182 }; 183 184 /// \brief A generator that wraps expressions passed 185 /// to it in the specified extension wrapper and uses 186 /// aggregate initialization for the wrapper. 187 /// 188 /// Generators are intended for use as the first template parameter 189 /// to the \c domain\<\> class template and control if and how 190 /// expressions within that domain are to be customized. 191 /// \c pod_generator\<\> wraps each expression passed to it in 192 /// the \c Extends\<\> wrapper, and uses aggregate initialzation 193 /// for the wrapped object. 194 template<template<typename> class Extends> 195 struct pod_generator 196 { 197 BOOST_PROTO_CALLABLE() 198 BOOST_PROTO_USE_BASIC_EXPR() 199 200 template<typename Sig> 201 struct result; 202 203 template<typename This, typename Expr> 204 struct result<This(Expr)> 205 { 206 typedef Extends<Expr> type; 207 }; 208 209 template<typename This, typename Expr> 210 struct result<This(Expr &)> 211 { 212 typedef Extends<Expr> type; 213 }; 214 215 template<typename This, typename Expr> 216 struct result<This(Expr const &)> 217 { 218 typedef Extends<Expr> type; 219 }; 220 221 /// \param expr The expression to wrap 222 /// \return <tt>Extends\<Expr\> that = {expr}; return that;</tt> 223 template<typename Expr> 224 BOOST_FORCEINLINE operator ()boost::proto::pod_generator225 Extends<Expr> operator ()(Expr const &e) const 226 { 227 Extends<Expr> that = {e}; 228 return that; 229 } 230 231 // Work-around for: 232 // https://connect.microsoft.com/VisualStudio/feedback/details/765449/codegen-stack-corruption-using-runtime-checks-when-aggregate-initializing-struct 233 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1700)) 234 template<typename Class, typename Member> 235 BOOST_FORCEINLINE operator ()boost::proto::pod_generator236 Extends<expr<tag::terminal, proto::term<Member Class::*> > > operator ()(expr<tag::terminal, proto::term<Member Class::*> > const &e) const 237 { 238 Extends<expr<tag::terminal, proto::term<Member Class::*> > > that; 239 proto::value(that.proto_expr_) = proto::value(e); 240 return that; 241 } 242 243 template<typename Class, typename Member> 244 BOOST_FORCEINLINE operator ()boost::proto::pod_generator245 Extends<basic_expr<tag::terminal, proto::term<Member Class::*> > > operator ()(basic_expr<tag::terminal, proto::term<Member Class::*> > const &e) const 246 { 247 Extends<basic_expr<tag::terminal, proto::term<Member Class::*> > > that; 248 proto::value(that.proto_expr_) = proto::value(e); 249 return that; 250 } 251 #endif 252 }; 253 254 /// \brief A generator that replaces child nodes held by 255 /// reference with ones held by value. Use with 256 /// \c compose_generators to forward that result to another 257 /// generator. 258 /// 259 /// Generators are intended for use as the first template parameter 260 /// to the \c domain\<\> class template and control if and how 261 /// expressions within that domain are to be customized. 262 /// \c by_value_generator ensures all child nodes are 263 /// held by value. This generator is typically composed with a 264 /// second generator for further processing, as 265 /// <tt>compose_generators\<by_value_generator, MyGenerator\></tt>. 266 struct by_value_generator 267 { 268 BOOST_PROTO_CALLABLE() 269 270 template<typename Sig> 271 struct result; 272 273 template<typename This, typename Expr> 274 struct result<This(Expr)> 275 { 276 typedef 277 typename detail::by_value_generator_<Expr>::type 278 type; 279 }; 280 281 template<typename This, typename Expr> 282 struct result<This(Expr &)> 283 { 284 typedef 285 typename detail::by_value_generator_<Expr>::type 286 type; 287 }; 288 289 template<typename This, typename Expr> 290 struct result<This(Expr const &)> 291 { 292 typedef 293 typename detail::by_value_generator_<Expr>::type 294 type; 295 }; 296 297 /// \param expr The expression to modify. 298 /// \return <tt>deep_copy(expr)</tt> 299 template<typename Expr> 300 BOOST_FORCEINLINE operator ()boost::proto::by_value_generator301 typename result<by_value_generator(Expr)>::type operator ()(Expr const &e) const 302 { 303 return detail::by_value_generator_<Expr>::call(e); 304 } 305 }; 306 307 /// \brief A composite generator that first applies one 308 /// transform to an expression and then forwards the result 309 /// on to another generator for further transformation. 310 /// 311 /// Generators are intended for use as the first template parameter 312 /// to the \c domain\<\> class template and control if and how 313 /// expressions within that domain are to be customized. 314 /// \c compose_generators\<\> is a composite generator that first 315 /// applies one transform to an expression and then forwards the 316 /// result on to another generator for further transformation. 317 template<typename First, typename Second> 318 struct compose_generators 319 { 320 BOOST_PROTO_CALLABLE() 321 322 template<typename Sig> 323 struct result; 324 325 template<typename This, typename Expr> 326 struct result<This(Expr)> 327 { 328 typedef 329 typename Second::template result< 330 Second(typename First::template result<First(Expr)>::type) 331 >::type 332 type; 333 }; 334 335 template<typename This, typename Expr> 336 struct result<This(Expr &)> 337 { 338 typedef 339 typename Second::template result< 340 Second(typename First::template result<First(Expr)>::type) 341 >::type 342 type; 343 }; 344 345 template<typename This, typename Expr> 346 struct result<This(Expr const &)> 347 { 348 typedef 349 typename Second::template result< 350 Second(typename First::template result<First(Expr)>::type) 351 >::type 352 type; 353 }; 354 355 /// \param expr The expression to modify. 356 /// \return Second()(First()(expr)) 357 template<typename Expr> 358 BOOST_FORCEINLINE operator ()boost::proto::compose_generators359 typename result<compose_generators(Expr)>::type operator ()(Expr const &e) const 360 { 361 return Second()(First()(e)); 362 } 363 }; 364 365 /// \brief Tests a generator to see whether it would prefer 366 /// to be passed instances of \c proto::basic_expr\<\> rather than 367 /// \c proto::expr\<\>. 368 /// 369 template<typename Generator, typename Void> 370 struct wants_basic_expr 371 : mpl::false_ 372 {}; 373 374 template<typename Generator> 375 struct wants_basic_expr<Generator, typename Generator::proto_use_basic_expr_> 376 : mpl::true_ 377 {}; 378 379 /// INTERNAL ONLY 380 template<> 381 struct is_callable<default_generator> 382 : mpl::true_ 383 {}; 384 385 /// INTERNAL ONLY 386 template<template<typename> class Extends> 387 struct is_callable<generator<Extends> > 388 : mpl::true_ 389 {}; 390 391 /// INTERNAL ONLY 392 template<template<typename> class Extends> 393 struct is_callable<pod_generator<Extends> > 394 : mpl::true_ 395 {}; 396 397 /// INTERNAL ONLY 398 template<> 399 struct is_callable<by_value_generator> 400 : mpl::true_ 401 {}; 402 403 /// INTERNAL ONLY 404 template<typename First, typename Second> 405 struct is_callable<compose_generators<First, Second> > 406 : mpl::true_ 407 {}; 408 409 }} 410 411 // Specializations of boost::result_of and boost::tr1_result_of to eliminate 412 // some unnecessary template instantiations 413 namespace boost 414 { 415 template<typename Expr> 416 struct result_of<proto::default_domain(Expr)> 417 { 418 typedef Expr type; 419 }; 420 421 template<typename Expr> 422 struct result_of<proto::basic_default_domain(Expr)> 423 { 424 typedef Expr type; 425 }; 426 427 template<typename Expr> 428 struct result_of<proto::default_generator(Expr)> 429 { 430 typedef Expr type; 431 }; 432 433 template<typename Expr> 434 struct result_of<proto::basic_default_generator(Expr)> 435 { 436 typedef Expr type; 437 }; 438 439 #if BOOST_VERSION >= 104400 440 template<typename Expr> 441 struct tr1_result_of<proto::default_domain(Expr)> 442 { 443 typedef Expr type; 444 }; 445 446 template<typename Expr> 447 struct tr1_result_of<proto::basic_default_domain(Expr)> 448 { 449 typedef Expr type; 450 }; 451 452 template<typename Expr> 453 struct tr1_result_of<proto::default_generator(Expr)> 454 { 455 typedef Expr type; 456 }; 457 458 template<typename Expr> 459 struct tr1_result_of<proto::basic_default_generator(Expr)> 460 { 461 typedef Expr type; 462 }; 463 #endif 464 } 465 466 #if defined(_MSC_VER) 467 # pragma warning(pop) 468 #endif 469 470 #endif // BOOST_PROTO_GENERATE_HPP_EAN_02_13_2007 471