1 /////////////////////////////////////////////////////////////////////////////// 2 /// \file traits.hpp 3 /// Contains definitions for child\<\>, child_c\<\>, left\<\>, 4 /// right\<\>, tag_of\<\>, and the helper functions child(), child_c(), 5 /// value(), left() and right(). 6 // 7 // Copyright 2008 Eric Niebler. Distributed under the Boost 8 // Software License, Version 1.0. (See accompanying file 9 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 10 11 #ifndef BOOST_PROTO_ARG_TRAITS_HPP_EAN_04_01_2005 12 #define BOOST_PROTO_ARG_TRAITS_HPP_EAN_04_01_2005 13 14 #include <boost/config.hpp> 15 #include <boost/detail/workaround.hpp> 16 #include <boost/preprocessor/iteration/iterate.hpp> 17 #include <boost/preprocessor/repetition/enum.hpp> 18 #include <boost/preprocessor/repetition/enum_params.hpp> 19 #include <boost/preprocessor/repetition/enum_trailing_params.hpp> 20 #include <boost/preprocessor/repetition/repeat.hpp> 21 #include <boost/preprocessor/repetition/repeat_from_to.hpp> 22 #include <boost/preprocessor/facilities/intercept.hpp> 23 #include <boost/preprocessor/arithmetic/sub.hpp> 24 #include <boost/static_assert.hpp> 25 #include <boost/mpl/bool.hpp> 26 #include <boost/proto/detail/template_arity.hpp> 27 #include <boost/type_traits/is_pod.hpp> 28 #include <boost/type_traits/is_same.hpp> 29 #include <boost/type_traits/add_const.hpp> 30 #include <boost/proto/proto_fwd.hpp> 31 #include <boost/proto/args.hpp> 32 #include <boost/proto/domain.hpp> 33 #include <boost/proto/transform/pass_through.hpp> 34 35 #if BOOST_WORKAROUND( BOOST_MSVC, >= 1400 ) 36 #pragma warning(push) 37 #pragma warning(disable: 4180) // warning C4180: qualifier applied to function type has no meaning; ignored 38 #endif 39 40 namespace boost { namespace proto 41 { 42 namespace detail 43 { 44 template<typename T, typename Void = void> 45 struct if_vararg 46 {}; 47 48 template<typename T> 49 struct if_vararg<T, typename T::proto_is_vararg_> 50 : T 51 {}; 52 53 template<typename T, typename Void = void> 54 struct is_callable2_ 55 : mpl::false_ 56 {}; 57 58 template<typename T> 59 struct is_callable2_<T, typename T::proto_is_callable_> 60 : mpl::true_ 61 {}; 62 63 template<typename T BOOST_PROTO_TEMPLATE_ARITY_PARAM(long Arity = boost::proto::detail::template_arity<T>::value)> 64 struct is_callable_ 65 : is_callable2_<T> 66 {}; 67 68 } 69 70 /// \brief Boolean metafunction which detects whether a type is 71 /// a callable function object type or not. 72 /// 73 /// <tt>is_callable\<\></tt> is used by the <tt>when\<\></tt> transform 74 /// to determine whether a function type <tt>R(A1,A2,...AN)</tt> is a 75 /// callable transform or an object transform. (The former are evaluated 76 /// using <tt>call\<\></tt> and the later with <tt>make\<\></tt>.) If 77 /// <tt>is_callable\<R\>::value</tt> is \c true, the function type is 78 /// a callable transform; otherwise, it is an object transform. 79 /// 80 /// Unless specialized for a type \c T, <tt>is_callable\<T\>::value</tt> 81 /// is computed as follows: 82 /// 83 /// \li If \c T is a template type <tt>X\<Y0,Y1,...YN\></tt>, where all \c Yx 84 /// are types for \c x in <tt>[0,N]</tt>, <tt>is_callable\<T\>::value</tt> 85 /// is <tt>is_same\<YN, proto::callable\>::value</tt>. 86 /// \li If \c T has a nested type \c proto_is_callable_ that is a typedef 87 /// for \c void, <tt>is_callable\<T\>::value</tt> is \c true. (Note: this is 88 /// the case for any type that derives from \c proto::callable.) 89 /// \li Otherwise, <tt>is_callable\<T\>::value</tt> is \c false. 90 template<typename T> 91 struct is_callable 92 : proto::detail::is_callable_<T> 93 {}; 94 95 /// INTERNAL ONLY 96 /// 97 template<> 98 struct is_callable<proto::_> 99 : mpl::true_ 100 {}; 101 102 /// INTERNAL ONLY 103 /// 104 template<> 105 struct is_callable<proto::callable> 106 : mpl::false_ 107 {}; 108 109 /// INTERNAL ONLY 110 /// 111 template<typename PrimitiveTransform, typename X> 112 struct is_callable<proto::transform<PrimitiveTransform, X> > 113 : mpl::false_ 114 {}; 115 116 #if BOOST_WORKAROUND(__GNUC__, == 3) || (__GNUC__ == 4 && __GNUC_MINOR__ == 0) 117 // work around GCC bug 118 template<typename Tag, typename Args, long N> 119 struct is_callable<proto::expr<Tag, Args, N> > 120 : mpl::false_ 121 {}; 122 123 // work around GCC bug 124 template<typename Tag, typename Args, long N> 125 struct is_callable<proto::basic_expr<Tag, Args, N> > 126 : mpl::false_ 127 {}; 128 #endif 129 130 /// \brief Boolean metafunction which detects whether a type is 131 /// a PrimitiveTransform type or not. 132 /// 133 /// <tt>is_transform\<\></tt> is used by the <tt>call\<\></tt> transform 134 /// to determine whether the function types <tt>R()</tt>, <tt>R(A1)</tt>, 135 /// and <tt>R(A1, A2)</tt> should be passed the expression, state and data 136 /// parameters (as needed). 137 /// 138 /// Unless specialized for a type \c T, <tt>is_transform\<T\>::value</tt> 139 /// is computed as follows: 140 /// 141 /// \li If \c T has a nested type \c proto_is_transform_ that is a typedef 142 /// for \c void, <tt>is_transform\<T\>::value</tt> is \c true. (Note: this is 143 /// the case for any type that derives from an instantiation of \c proto::transform.) 144 /// \li Otherwise, <tt>is_transform\<T\>::value</tt> is \c false. 145 template<typename T, typename Void /*= void*/> 146 struct is_transform 147 : mpl::false_ 148 {}; 149 150 template<typename T> 151 struct is_transform<T, typename T::proto_is_transform_> 152 : mpl::true_ 153 {}; 154 155 /// \brief A Boolean metafunction that indicates whether a type requires 156 /// aggregate initialization. 157 /// 158 /// <tt>is_aggregate\<\></tt> is used by the <tt>make\<\></tt> transform 159 /// to determine how to construct an object of some type \c T, given some 160 /// initialization arguments <tt>a0,a1,...aN</tt>. 161 /// If <tt>is_aggregate\<T\>::value</tt> is \c true, then an object of 162 /// type T will be initialized as <tt>T t = {a0,a1,...aN};</tt>. Otherwise, 163 /// it will be initialized as <tt>T t(a0,a1,...aN)</tt>. 164 template<typename T, typename Void> 165 struct is_aggregate 166 : is_pod<T> 167 {}; 168 169 /// \brief Specialization of <tt>is_aggregate\<\></tt> that indicates 170 /// that objects of <tt>expr\<\></tt> type require aggregate initialization. 171 template<typename Tag, typename Args, long N> 172 struct is_aggregate<proto::expr<Tag, Args, N>, void> 173 : mpl::true_ 174 {}; 175 176 template<typename Tag, typename Args, long N> 177 struct is_aggregate<proto::basic_expr<Tag, Args, N>, void> 178 : mpl::true_ 179 {}; 180 181 /// INTERNAL ONLY 182 template<typename T> 183 struct is_aggregate<T, typename T::proto_is_aggregate_> 184 : mpl::true_ 185 {}; 186 187 /// \brief A Boolean metafunction that indicates whether a given 188 /// type \c T is a Proto expression type. 189 /// 190 /// If \c T has a nested type \c proto_is_expr_ that is a typedef 191 /// for \c void, <tt>is_expr\<T\>::value</tt> is \c true. (Note, this 192 /// is the case for <tt>proto::expr\<\></tt>, any type that is derived 193 /// from <tt>proto::extends\<\></tt> or that uses the 194 /// <tt>BOOST_PROTO_BASIC_EXTENDS()</tt> macro.) Otherwise, 195 /// <tt>is_expr\<T\>::value</tt> is \c false. 196 template<typename T, typename Void /* = void*/> 197 struct is_expr 198 : mpl::false_ 199 {}; 200 201 /// \brief A Boolean metafunction that indicates whether a given 202 /// type \c T is a Proto expression type. 203 /// 204 /// If \c T has a nested type \c proto_is_expr_ that is a typedef 205 /// for \c void, <tt>is_expr\<T\>::value</tt> is \c true. (Note, this 206 /// is the case for <tt>proto::expr\<\></tt>, any type that is derived 207 /// from <tt>proto::extends\<\></tt> or that uses the 208 /// <tt>BOOST_PROTO_BASIC_EXTENDS()</tt> macro.) Otherwise, 209 /// <tt>is_expr\<T\>::value</tt> is \c false. 210 template<typename T> 211 struct is_expr<T, typename T::proto_is_expr_> 212 : mpl::true_ 213 {}; 214 215 template<typename T> 216 struct is_expr<T &, void> 217 : is_expr<T> 218 {}; 219 220 /// \brief A metafunction that returns the tag type of a 221 /// Proto expression. 222 template<typename Expr> 223 struct tag_of 224 { 225 typedef typename Expr::proto_tag type; 226 }; 227 228 template<typename Expr> 229 struct tag_of<Expr &> 230 { 231 typedef typename Expr::proto_tag type; 232 }; 233 234 /// \brief A metafunction that returns the arity of a 235 /// Proto expression. 236 template<typename Expr> 237 struct arity_of 238 : Expr::proto_arity 239 {}; 240 241 template<typename Expr> 242 struct arity_of<Expr &> 243 : Expr::proto_arity 244 {}; 245 246 namespace result_of 247 { 248 /// \brief A metafunction that computes the return type of the \c as_expr() 249 /// function. 250 template<typename T, typename Domain /*= default_domain*/> 251 struct as_expr 252 { 253 typedef typename Domain::template as_expr<T>::result_type type; 254 }; 255 256 /// \brief A metafunction that computes the return type of the \c as_child() 257 /// function. 258 template<typename T, typename Domain /*= default_domain*/> 259 struct as_child 260 { 261 typedef typename Domain::template as_child<T>::result_type type; 262 }; 263 264 /// \brief A metafunction that returns the type of the Nth child 265 /// of a Proto expression, where N is an MPL Integral Constant. 266 /// 267 /// <tt>result_of::child\<Expr, N\></tt> is equivalent to 268 /// <tt>result_of::child_c\<Expr, N::value\></tt>. 269 template<typename Expr, typename N /* = mpl::long_<0>*/> 270 struct child 271 : child_c<Expr, N::value> 272 {}; 273 274 /// \brief A metafunction that returns the type of the value 275 /// of a terminal Proto expression. 276 /// 277 template<typename Expr> 278 struct value 279 { 280 /// Verify that we are actually operating on a terminal 281 BOOST_STATIC_ASSERT(0 == Expr::proto_arity_c); 282 283 /// The raw type of the Nth child as it is stored within 284 /// \c Expr. This may be a value or a reference 285 typedef typename Expr::proto_child0 value_type; 286 287 /// The "value" type of the child, suitable for storage by value, 288 /// computed as follows: 289 /// \li <tt>T const(&)[N]</tt> becomes <tt>T[N]</tt> 290 /// \li <tt>T[N]</tt> becomes <tt>T[N]</tt> 291 /// \li <tt>T(&)[N]</tt> becomes <tt>T[N]</tt> 292 /// \li <tt>R(&)(A0,...)</tt> becomes <tt>R(&)(A0,...)</tt> 293 /// \li <tt>T const &</tt> becomes <tt>T</tt> 294 /// \li <tt>T &</tt> becomes <tt>T</tt> 295 /// \li <tt>T</tt> becomes <tt>T</tt> 296 typedef typename detail::term_traits<typename Expr::proto_child0>::value_type type; 297 }; 298 299 template<typename Expr> 300 struct value<Expr &> 301 { 302 /// Verify that we are actually operating on a terminal 303 BOOST_STATIC_ASSERT(0 == Expr::proto_arity_c); 304 305 /// The raw type of the Nth child as it is stored within 306 /// \c Expr. This may be a value or a reference 307 typedef typename Expr::proto_child0 value_type; 308 309 /// The "reference" type of the child, suitable for storage by 310 /// reference, computed as follows: 311 /// \li <tt>T const(&)[N]</tt> becomes <tt>T const(&)[N]</tt> 312 /// \li <tt>T[N]</tt> becomes <tt>T(&)[N]</tt> 313 /// \li <tt>T(&)[N]</tt> becomes <tt>T(&)[N]</tt> 314 /// \li <tt>R(&)(A0,...)</tt> becomes <tt>R(&)(A0,...)</tt> 315 /// \li <tt>T const &</tt> becomes <tt>T const &</tt> 316 /// \li <tt>T &</tt> becomes <tt>T &</tt> 317 /// \li <tt>T</tt> becomes <tt>T &</tt> 318 typedef typename detail::term_traits<typename Expr::proto_child0>::reference type; 319 }; 320 321 template<typename Expr> 322 struct value<Expr const &> 323 { 324 /// Verify that we are actually operating on a terminal 325 BOOST_STATIC_ASSERT(0 == Expr::proto_arity_c); 326 327 /// The raw type of the Nth child as it is stored within 328 /// \c Expr. This may be a value or a reference 329 typedef typename Expr::proto_child0 value_type; 330 331 /// The "const reference" type of the child, suitable for storage by 332 /// const reference, computed as follows: 333 /// \li <tt>T const(&)[N]</tt> becomes <tt>T const(&)[N]</tt> 334 /// \li <tt>T[N]</tt> becomes <tt>T const(&)[N]</tt> 335 /// \li <tt>T(&)[N]</tt> becomes <tt>T(&)[N]</tt> 336 /// \li <tt>R(&)(A0,...)</tt> becomes <tt>R(&)(A0,...)</tt> 337 /// \li <tt>T const &</tt> becomes <tt>T const &</tt> 338 /// \li <tt>T &</tt> becomes <tt>T &</tt> 339 /// \li <tt>T</tt> becomes <tt>T const &</tt> 340 typedef typename detail::term_traits<typename Expr::proto_child0>::const_reference type; 341 }; 342 343 /// \brief A metafunction that returns the type of the left child 344 /// of a binary Proto expression. 345 /// 346 /// <tt>result_of::left\<Expr\></tt> is equivalent to 347 /// <tt>result_of::child_c\<Expr, 0\></tt>. 348 template<typename Expr> 349 struct left 350 : child_c<Expr, 0> 351 {}; 352 353 /// \brief A metafunction that returns the type of the right child 354 /// of a binary Proto expression. 355 /// 356 /// <tt>result_of::right\<Expr\></tt> is equivalent to 357 /// <tt>result_of::child_c\<Expr, 1\></tt>. 358 template<typename Expr> 359 struct right 360 : child_c<Expr, 1> 361 {}; 362 363 } // namespace result_of 364 365 /// \brief A metafunction for generating terminal expression types, 366 /// a grammar element for matching terminal expressions, and a 367 /// PrimitiveTransform that returns the current expression unchanged. 368 template<typename T> 369 struct terminal 370 : proto::transform<terminal<T>, int> 371 { 372 typedef proto::expr<proto::tag::terminal, term<T>, 0> type; 373 typedef proto::basic_expr<proto::tag::terminal, term<T>, 0> proto_grammar; 374 375 template<typename Expr, typename State, typename Data> 376 struct impl : transform_impl<Expr, State, Data> 377 { 378 typedef Expr result_type; 379 380 /// \param e The current expression 381 /// \pre <tt>matches\<Expr, terminal\<T\> \>::value</tt> is \c true. 382 /// \return \c e 383 /// \throw nothrow 384 #ifdef BOOST_PROTO_STRICT_RESULT_OF 385 result_type 386 #else 387 typename impl::expr_param 388 #endif operator ()boost::proto::terminal::impl389 operator ()( 390 typename impl::expr_param e 391 , typename impl::state_param 392 , typename impl::data_param 393 ) const 394 { 395 return e; 396 } 397 }; 398 399 /// INTERNAL ONLY 400 typedef proto::tag::terminal proto_tag; 401 /// INTERNAL ONLY 402 typedef T proto_child0; 403 }; 404 405 /// \brief A metafunction for generating ternary conditional expression types, 406 /// a grammar element for matching ternary conditional expressions, and a 407 /// PrimitiveTransform that dispatches to the <tt>pass_through\<\></tt> 408 /// transform. 409 template<typename T, typename U, typename V> 410 struct if_else_ 411 : proto::transform<if_else_<T, U, V>, int> 412 { 413 typedef proto::expr<proto::tag::if_else_, list3<T, U, V>, 3> type; 414 typedef proto::basic_expr<proto::tag::if_else_, list3<T, U, V>, 3> proto_grammar; 415 416 template<typename Expr, typename State, typename Data> 417 struct impl 418 : detail::pass_through_impl<if_else_, Expr, State, Data> 419 {}; 420 421 /// INTERNAL ONLY 422 typedef proto::tag::if_else_ proto_tag; 423 /// INTERNAL ONLY 424 typedef T proto_child0; 425 /// INTERNAL ONLY 426 typedef U proto_child1; 427 /// INTERNAL ONLY 428 typedef V proto_child2; 429 }; 430 431 /// \brief A metafunction for generating nullary expression types with a 432 /// specified tag type, 433 /// a grammar element for matching nullary expressions, and a 434 /// PrimitiveTransform that returns the current expression unchanged. 435 /// 436 /// Use <tt>nullary_expr\<_, _\></tt> as a grammar element to match any 437 /// nullary expression. 438 template<typename Tag, typename T> 439 struct nullary_expr 440 : proto::transform<nullary_expr<Tag, T>, int> 441 { 442 typedef proto::expr<Tag, term<T>, 0> type; 443 typedef proto::basic_expr<Tag, term<T>, 0> proto_grammar; 444 445 template<typename Expr, typename State, typename Data> 446 struct impl : transform_impl<Expr, State, Data> 447 { 448 typedef Expr result_type; 449 450 /// \param e The current expression 451 /// \pre <tt>matches\<Expr, nullary_expr\<Tag, T\> \>::value</tt> is \c true. 452 /// \return \c e 453 /// \throw nothrow 454 #ifdef BOOST_PROTO_STRICT_RESULT_OF 455 result_type 456 #else 457 typename impl::expr_param 458 #endif operator ()boost::proto::nullary_expr::impl459 operator ()( 460 typename impl::expr_param e 461 , typename impl::state_param 462 , typename impl::data_param 463 ) const 464 { 465 return e; 466 } 467 }; 468 469 /// INTERNAL ONLY 470 typedef Tag proto_tag; 471 /// INTERNAL ONLY 472 typedef T proto_child0; 473 }; 474 475 /// \brief A metafunction for generating unary expression types with a 476 /// specified tag type, 477 /// a grammar element for matching unary expressions, and a 478 /// PrimitiveTransform that dispatches to the <tt>pass_through\<\></tt> 479 /// transform. 480 /// 481 /// Use <tt>unary_expr\<_, _\></tt> as a grammar element to match any 482 /// unary expression. 483 template<typename Tag, typename T> 484 struct unary_expr 485 : proto::transform<unary_expr<Tag, T>, int> 486 { 487 typedef proto::expr<Tag, list1<T>, 1> type; 488 typedef proto::basic_expr<Tag, list1<T>, 1> proto_grammar; 489 490 template<typename Expr, typename State, typename Data> 491 struct impl 492 : detail::pass_through_impl<unary_expr, Expr, State, Data> 493 {}; 494 495 /// INTERNAL ONLY 496 typedef Tag proto_tag; 497 /// INTERNAL ONLY 498 typedef T proto_child0; 499 }; 500 501 /// \brief A metafunction for generating binary expression types with a 502 /// specified tag type, 503 /// a grammar element for matching binary expressions, and a 504 /// PrimitiveTransform that dispatches to the <tt>pass_through\<\></tt> 505 /// transform. 506 /// 507 /// Use <tt>binary_expr\<_, _, _\></tt> as a grammar element to match any 508 /// binary expression. 509 template<typename Tag, typename T, typename U> 510 struct binary_expr 511 : proto::transform<binary_expr<Tag, T, U>, int> 512 { 513 typedef proto::expr<Tag, list2<T, U>, 2> type; 514 typedef proto::basic_expr<Tag, list2<T, U>, 2> proto_grammar; 515 516 template<typename Expr, typename State, typename Data> 517 struct impl 518 : detail::pass_through_impl<binary_expr, Expr, State, Data> 519 {}; 520 521 /// INTERNAL ONLY 522 typedef Tag proto_tag; 523 /// INTERNAL ONLY 524 typedef T proto_child0; 525 /// INTERNAL ONLY 526 typedef U proto_child1; 527 }; 528 529 #define BOOST_PROTO_DEFINE_UNARY_METAFUNCTION(Op) \ 530 template<typename T> \ 531 struct Op \ 532 : proto::transform<Op<T>, int> \ 533 { \ 534 typedef proto::expr<proto::tag::Op, list1<T>, 1> type; \ 535 typedef proto::basic_expr<proto::tag::Op, list1<T>, 1> proto_grammar; \ 536 \ 537 template<typename Expr, typename State, typename Data> \ 538 struct impl \ 539 : detail::pass_through_impl<Op, Expr, State, Data> \ 540 {}; \ 541 \ 542 typedef proto::tag::Op proto_tag; \ 543 typedef T proto_child0; \ 544 }; \ 545 /**/ 546 547 #define BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(Op) \ 548 template<typename T, typename U> \ 549 struct Op \ 550 : proto::transform<Op<T, U>, int> \ 551 { \ 552 typedef proto::expr<proto::tag::Op, list2<T, U>, 2> type; \ 553 typedef proto::basic_expr<proto::tag::Op, list2<T, U>, 2> proto_grammar; \ 554 \ 555 template<typename Expr, typename State, typename Data> \ 556 struct impl \ 557 : detail::pass_through_impl<Op, Expr, State, Data> \ 558 {}; \ 559 \ 560 typedef proto::tag::Op proto_tag; \ 561 typedef T proto_child0; \ 562 typedef U proto_child1; \ 563 }; \ 564 /**/ 565 566 BOOST_PROTO_DEFINE_UNARY_METAFUNCTION(unary_plus) 567 BOOST_PROTO_DEFINE_UNARY_METAFUNCTION(negate) 568 BOOST_PROTO_DEFINE_UNARY_METAFUNCTION(dereference) 569 BOOST_PROTO_DEFINE_UNARY_METAFUNCTION(complement) 570 BOOST_PROTO_DEFINE_UNARY_METAFUNCTION(address_of) 571 BOOST_PROTO_DEFINE_UNARY_METAFUNCTION(logical_not) 572 BOOST_PROTO_DEFINE_UNARY_METAFUNCTION(pre_inc) 573 BOOST_PROTO_DEFINE_UNARY_METAFUNCTION(pre_dec) 574 BOOST_PROTO_DEFINE_UNARY_METAFUNCTION(post_inc) 575 BOOST_PROTO_DEFINE_UNARY_METAFUNCTION(post_dec) 576 577 BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(shift_left) 578 BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(shift_right) 579 BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(multiplies) 580 BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(divides) 581 BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(modulus) 582 BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(plus) 583 BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(minus) 584 BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(less) 585 BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(greater) 586 BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(less_equal) 587 BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(greater_equal) 588 BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(equal_to) 589 BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(not_equal_to) 590 BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(logical_or) 591 BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(logical_and) 592 BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(bitwise_or) 593 BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(bitwise_and) 594 BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(bitwise_xor) 595 BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(comma) 596 BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(mem_ptr) 597 BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(assign) 598 BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(shift_left_assign) 599 BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(shift_right_assign) 600 BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(multiplies_assign) 601 BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(divides_assign) 602 BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(modulus_assign) 603 BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(plus_assign) 604 BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(minus_assign) 605 BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(bitwise_or_assign) 606 BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(bitwise_and_assign) 607 BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(bitwise_xor_assign) 608 BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(subscript) 609 BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(member) 610 611 #undef BOOST_PROTO_DEFINE_UNARY_METAFUNCTION 612 #undef BOOST_PROTO_DEFINE_BINARY_METAFUNCTION 613 614 #include <boost/proto/detail/traits.hpp> 615 616 namespace functional 617 { 618 /// \brief A callable PolymorphicFunctionObject that is 619 /// equivalent to the \c as_expr() function. 620 template<typename Domain /* = default_domain*/> 621 struct as_expr 622 { 623 BOOST_PROTO_CALLABLE() 624 625 template<typename Sig> 626 struct result; 627 628 template<typename This, typename T> 629 struct result<This(T)> 630 { 631 typedef typename Domain::template as_expr<T>::result_type type; 632 }; 633 634 template<typename This, typename T> 635 struct result<This(T &)> 636 { 637 typedef typename Domain::template as_expr<T>::result_type type; 638 }; 639 640 /// \brief Wrap an object in a Proto terminal if it isn't a 641 /// Proto expression already. 642 /// \param t The object to wrap. 643 /// \return <tt>proto::as_expr\<Domain\>(t)</tt> 644 template<typename T> 645 typename add_const<typename result<as_expr(T &)>::type>::type operator ()boost::proto::functional::as_expr646 operator ()(T &t) const 647 { 648 return typename Domain::template as_expr<T>()(t); 649 } 650 651 /// \overload 652 /// 653 template<typename T> 654 typename add_const<typename result<as_expr(T const &)>::type>::type operator ()boost::proto::functional::as_expr655 operator ()(T const &t) const 656 { 657 return typename Domain::template as_expr<T const>()(t); 658 } 659 660 #if BOOST_WORKAROUND(BOOST_MSVC, == 1310) 661 template<typename T, std::size_t N_> 662 typename add_const<typename result<as_expr(T (&)[N_])>::type>::type operator ()boost::proto::functional::as_expr663 operator ()(T (&t)[N_]) const 664 { 665 return typename Domain::template as_expr<T[N_]>()(t); 666 } 667 668 template<typename T, std::size_t N_> 669 typename add_const<typename result<as_expr(T const (&)[N_])>::type>::type operator ()boost::proto::functional::as_expr670 operator ()(T const (&t)[N_]) const 671 { 672 return typename Domain::template as_expr<T const[N_]>()(t); 673 } 674 #endif 675 }; 676 677 /// \brief A callable PolymorphicFunctionObject that is 678 /// equivalent to the \c as_child() function. 679 template<typename Domain /* = default_domain*/> 680 struct as_child 681 { 682 BOOST_PROTO_CALLABLE() 683 684 template<typename Sig> 685 struct result; 686 687 template<typename This, typename T> 688 struct result<This(T)> 689 { 690 typedef typename Domain::template as_child<T>::result_type type; 691 }; 692 693 template<typename This, typename T> 694 struct result<This(T &)> 695 { 696 typedef typename Domain::template as_child<T>::result_type type; 697 }; 698 699 /// \brief Wrap an object in a Proto terminal if it isn't a 700 /// Proto expression already. 701 /// \param t The object to wrap. 702 /// \return <tt>proto::as_child\<Domain\>(t)</tt> 703 template<typename T> 704 typename add_const<typename result<as_child(T &)>::type>::type operator ()boost::proto::functional::as_child705 operator ()(T &t) const 706 { 707 return typename Domain::template as_child<T>()(t); 708 } 709 710 /// \overload 711 /// 712 template<typename T> 713 typename add_const<typename result<as_child(T const &)>::type>::type operator ()boost::proto::functional::as_child714 operator ()(T const &t) const 715 { 716 return typename Domain::template as_child<T const>()(t); 717 } 718 }; 719 720 /// \brief A callable PolymorphicFunctionObject that is 721 /// equivalent to the \c child_c() function. 722 template<long N> 723 struct child_c 724 { 725 BOOST_PROTO_CALLABLE() 726 727 template<typename Sig> 728 struct result; 729 730 template<typename This, typename Expr> 731 struct result<This(Expr)> 732 { 733 typedef typename result_of::child_c<Expr, N>::type type; 734 }; 735 736 /// \brief Return the Nth child of the given expression. 737 /// \param expr The expression node. 738 /// \pre <tt>is_expr\<Expr\>::value</tt> is \c true 739 /// \pre <tt>N \< Expr::proto_arity::value</tt> 740 /// \return <tt>proto::child_c\<N\>(expr)</tt> 741 /// \throw nothrow 742 template<typename Expr> 743 typename result_of::child_c<Expr &, N>::type operator ()boost::proto::functional::child_c744 operator ()(Expr &e) const 745 { 746 return result_of::child_c<Expr &, N>::call(e); 747 } 748 749 /// \overload 750 /// 751 template<typename Expr> 752 typename result_of::child_c<Expr const &, N>::type operator ()boost::proto::functional::child_c753 operator ()(Expr const &e) const 754 { 755 return result_of::child_c<Expr const &, N>::call(e); 756 } 757 }; 758 759 /// \brief A callable PolymorphicFunctionObject that is 760 /// equivalent to the \c child() function. 761 /// 762 /// A callable PolymorphicFunctionObject that is 763 /// equivalent to the \c child() function. \c N is required 764 /// to be an MPL Integral Constant. 765 template<typename N /* = mpl::long_<0>*/> 766 struct child 767 { 768 BOOST_PROTO_CALLABLE() 769 770 template<typename Sig> 771 struct result; 772 773 template<typename This, typename Expr> 774 struct result<This(Expr)> 775 { 776 typedef typename result_of::child<Expr, N>::type type; 777 }; 778 779 /// \brief Return the Nth child of the given expression. 780 /// \param expr The expression node. 781 /// \pre <tt>is_expr\<Expr\>::value</tt> is \c true 782 /// \pre <tt>N::value \< Expr::proto_arity::value</tt> 783 /// \return <tt>proto::child\<N\>(expr)</tt> 784 /// \throw nothrow 785 template<typename Expr> 786 typename result_of::child<Expr &, N>::type operator ()boost::proto::functional::child787 operator ()(Expr &e) const 788 { 789 return result_of::child<Expr &, N>::call(e); 790 } 791 792 /// \overload 793 /// 794 template<typename Expr> 795 typename result_of::child<Expr const &, N>::type operator ()boost::proto::functional::child796 operator ()(Expr const &e) const 797 { 798 return result_of::child<Expr const &, N>::call(e); 799 } 800 }; 801 802 /// \brief A callable PolymorphicFunctionObject that is 803 /// equivalent to the \c value() function. 804 struct value 805 { 806 BOOST_PROTO_CALLABLE() 807 808 template<typename Sig> 809 struct result; 810 811 template<typename This, typename Expr> 812 struct result<This(Expr)> 813 { 814 typedef typename result_of::value<Expr>::type type; 815 }; 816 817 /// \brief Return the value of the given terminal expression. 818 /// \param expr The terminal expression node. 819 /// \pre <tt>is_expr\<Expr\>::value</tt> is \c true 820 /// \pre <tt>0 == Expr::proto_arity::value</tt> 821 /// \return <tt>proto::value(expr)</tt> 822 /// \throw nothrow 823 template<typename Expr> 824 typename result_of::value<Expr &>::type operator ()boost::proto::functional::value825 operator ()(Expr &e) const 826 { 827 return e.proto_base().child0; 828 } 829 830 /// \overload 831 /// 832 template<typename Expr> 833 typename result_of::value<Expr const &>::type operator ()boost::proto::functional::value834 operator ()(Expr const &e) const 835 { 836 return e.proto_base().child0; 837 } 838 }; 839 840 /// \brief A callable PolymorphicFunctionObject that is 841 /// equivalent to the \c left() function. 842 struct left 843 { 844 BOOST_PROTO_CALLABLE() 845 846 template<typename Sig> 847 struct result; 848 849 template<typename This, typename Expr> 850 struct result<This(Expr)> 851 { 852 typedef typename result_of::left<Expr>::type type; 853 }; 854 855 /// \brief Return the left child of the given binary expression. 856 /// \param expr The expression node. 857 /// \pre <tt>is_expr\<Expr\>::value</tt> is \c true 858 /// \pre <tt>2 == Expr::proto_arity::value</tt> 859 /// \return <tt>proto::left(expr)</tt> 860 /// \throw nothrow 861 template<typename Expr> 862 typename result_of::left<Expr &>::type operator ()boost::proto::functional::left863 operator ()(Expr &e) const 864 { 865 return e.proto_base().child0; 866 } 867 868 /// \overload 869 /// 870 template<typename Expr> 871 typename result_of::left<Expr const &>::type operator ()boost::proto::functional::left872 operator ()(Expr const &e) const 873 { 874 return e.proto_base().child0; 875 } 876 }; 877 878 /// \brief A callable PolymorphicFunctionObject that is 879 /// equivalent to the \c right() function. 880 struct right 881 { 882 BOOST_PROTO_CALLABLE() 883 884 template<typename Sig> 885 struct result; 886 887 template<typename This, typename Expr> 888 struct result<This(Expr)> 889 { 890 typedef typename result_of::right<Expr>::type type; 891 }; 892 893 /// \brief Return the right child of the given binary expression. 894 /// \param expr The expression node. 895 /// \pre <tt>is_expr\<Expr\>::value</tt> is \c true 896 /// \pre <tt>2 == Expr::proto_arity::value</tt> 897 /// \return <tt>proto::right(expr)</tt> 898 /// \throw nothrow 899 template<typename Expr> 900 typename result_of::right<Expr &>::type operator ()boost::proto::functional::right901 operator ()(Expr &e) const 902 { 903 return e.proto_base().child1; 904 } 905 906 template<typename Expr> 907 typename result_of::right<Expr const &>::type operator ()boost::proto::functional::right908 operator ()(Expr const &e) const 909 { 910 return e.proto_base().child1; 911 } 912 }; 913 914 } 915 916 /// \brief A function that wraps non-Proto expression types in Proto 917 /// terminals and leaves Proto expression types alone. 918 /// 919 /// The <tt>as_expr()</tt> function turns objects into Proto terminals if 920 /// they are not Proto expression types already. Non-Proto types are 921 /// held by value, if possible. Types which are already Proto types are 922 /// left alone and returned by reference. 923 /// 924 /// This function can be called either with an explicitly specified 925 /// \c Domain parameter (i.e., <tt>as_expr\<Domain\>(t)</tt>), or 926 /// without (i.e., <tt>as_expr(t)</tt>). If no domain is 927 /// specified, \c default_domain is assumed. 928 /// 929 /// If <tt>is_expr\<T\>::value</tt> is \c true, then the argument is 930 /// returned unmodified, by reference. Otherwise, the argument is wrapped 931 /// in a Proto terminal expression node according to the following rules. 932 /// If \c T is a function type, let \c A be <tt>T &</tt>. Otherwise, let 933 /// \c A be the type \c T stripped of cv-qualifiers. Then, \c as_expr() 934 /// returns <tt>Domain()(terminal\<A\>::type::make(t))</tt>. 935 /// 936 /// \param t The object to wrap. 937 template<typename T> 938 typename add_const<typename result_of::as_expr<T, default_domain>::type>::type as_expr(T & t BOOST_PROTO_DISABLE_IF_IS_CONST (T)BOOST_PROTO_DISABLE_IF_IS_FUNCTION (T))939 as_expr(T &t BOOST_PROTO_DISABLE_IF_IS_CONST(T) BOOST_PROTO_DISABLE_IF_IS_FUNCTION(T)) 940 { 941 return default_domain::as_expr<T>()(t); 942 } 943 944 /// \overload 945 /// 946 template<typename T> 947 typename add_const<typename result_of::as_expr<T const, default_domain>::type>::type as_expr(T const & t)948 as_expr(T const &t) 949 { 950 return default_domain::as_expr<T const>()(t); 951 } 952 953 /// \overload 954 /// 955 template<typename Domain, typename T> 956 typename add_const<typename result_of::as_expr<T, Domain>::type>::type as_expr(T & t BOOST_PROTO_DISABLE_IF_IS_CONST (T)BOOST_PROTO_DISABLE_IF_IS_FUNCTION (T))957 as_expr(T &t BOOST_PROTO_DISABLE_IF_IS_CONST(T) BOOST_PROTO_DISABLE_IF_IS_FUNCTION(T)) 958 { 959 return typename Domain::template as_expr<T>()(t); 960 } 961 962 /// \overload 963 /// 964 template<typename Domain, typename T> 965 typename add_const<typename result_of::as_expr<T const, Domain>::type>::type as_expr(T const & t)966 as_expr(T const &t) 967 { 968 return typename Domain::template as_expr<T const>()(t); 969 } 970 971 /// \brief A function that wraps non-Proto expression types in Proto 972 /// terminals (by reference) and returns Proto expression types by 973 /// reference 974 /// 975 /// The <tt>as_child()</tt> function turns objects into Proto terminals if 976 /// they are not Proto expression types already. Non-Proto types are 977 /// held by reference. Types which are already Proto types are simply 978 /// returned as-is. 979 /// 980 /// This function can be called either with an explicitly specified 981 /// \c Domain parameter (i.e., <tt>as_child\<Domain\>(t)</tt>), or 982 /// without (i.e., <tt>as_child(t)</tt>). If no domain is 983 /// specified, \c default_domain is assumed. 984 /// 985 /// If <tt>is_expr\<T\>::value</tt> is \c true, then the argument is 986 /// returned as-is. Otherwise, \c as_child() returns 987 /// <tt>Domain()(terminal\<T &\>::type::make(t))</tt>. 988 /// 989 /// \param t The object to wrap. 990 template<typename T> 991 typename add_const<typename result_of::as_child<T, default_domain>::type>::type as_child(T & t BOOST_PROTO_DISABLE_IF_IS_CONST (T)BOOST_PROTO_DISABLE_IF_IS_FUNCTION (T))992 as_child(T &t BOOST_PROTO_DISABLE_IF_IS_CONST(T) BOOST_PROTO_DISABLE_IF_IS_FUNCTION(T)) 993 { 994 return default_domain::as_child<T>()(t); 995 } 996 997 /// \overload 998 /// 999 template<typename T> 1000 typename add_const<typename result_of::as_child<T const, default_domain>::type>::type as_child(T const & t)1001 as_child(T const &t) 1002 { 1003 return default_domain::as_child<T const>()(t); 1004 } 1005 1006 /// \overload 1007 /// 1008 template<typename Domain, typename T> 1009 typename add_const<typename result_of::as_child<T, Domain>::type>::type as_child(T & t BOOST_PROTO_DISABLE_IF_IS_CONST (T)BOOST_PROTO_DISABLE_IF_IS_FUNCTION (T))1010 as_child(T &t BOOST_PROTO_DISABLE_IF_IS_CONST(T) BOOST_PROTO_DISABLE_IF_IS_FUNCTION(T)) 1011 { 1012 return typename Domain::template as_child<T>()(t); 1013 } 1014 1015 /// \overload 1016 /// 1017 template<typename Domain, typename T> 1018 typename add_const<typename result_of::as_child<T const, Domain>::type>::type as_child(T const & t)1019 as_child(T const &t) 1020 { 1021 return typename Domain::template as_child<T const>()(t); 1022 } 1023 1024 /// \brief Return the Nth child of the specified Proto expression. 1025 /// 1026 /// Return the Nth child of the specified Proto expression. If 1027 /// \c N is not specified, as in \c child(expr), then \c N is assumed 1028 /// to be <tt>mpl::long_\<0\></tt>. The child is returned by 1029 /// reference. 1030 /// 1031 /// \param expr The Proto expression. 1032 /// \pre <tt>is_expr\<Expr\>::value</tt> is \c true. 1033 /// \pre \c N is an MPL Integral Constant. 1034 /// \pre <tt>N::value \< Expr::proto_arity::value</tt> 1035 /// \throw nothrow 1036 /// \return A reference to the Nth child 1037 template<typename N, typename Expr> 1038 typename result_of::child<Expr &, N>::type child(Expr & e BOOST_PROTO_DISABLE_IF_IS_CONST (Expr))1039 child(Expr &e BOOST_PROTO_DISABLE_IF_IS_CONST(Expr)) 1040 { 1041 return result_of::child<Expr &, N>::call(e); 1042 } 1043 1044 /// \overload 1045 /// 1046 template<typename N, typename Expr> 1047 typename result_of::child<Expr const &, N>::type child(Expr const & e)1048 child(Expr const &e) 1049 { 1050 return result_of::child<Expr const &, N>::call(e); 1051 } 1052 1053 /// \overload 1054 /// 1055 template<typename Expr2> 1056 typename detail::expr_traits<typename Expr2::proto_base_expr::proto_child0>::reference child(Expr2 & expr2 BOOST_PROTO_DISABLE_IF_IS_CONST (Expr2))1057 child(Expr2 &expr2 BOOST_PROTO_DISABLE_IF_IS_CONST(Expr2)) 1058 { 1059 return expr2.proto_base().child0; 1060 } 1061 1062 /// \overload 1063 /// 1064 template<typename Expr2> 1065 typename detail::expr_traits<typename Expr2::proto_base_expr::proto_child0>::const_reference child(Expr2 const & expr2)1066 child(Expr2 const &expr2) 1067 { 1068 return expr2.proto_base().child0; 1069 } 1070 1071 /// \brief Return the Nth child of the specified Proto expression. 1072 /// 1073 /// Return the Nth child of the specified Proto expression. The child 1074 /// is returned by reference. 1075 /// 1076 /// \param expr The Proto expression. 1077 /// \pre <tt>is_expr\<Expr\>::value</tt> is \c true. 1078 /// \pre <tt>N \< Expr::proto_arity::value</tt> 1079 /// \throw nothrow 1080 /// \return A reference to the Nth child 1081 template<long N, typename Expr> 1082 typename result_of::child_c<Expr &, N>::type child_c(Expr & e BOOST_PROTO_DISABLE_IF_IS_CONST (Expr))1083 child_c(Expr &e BOOST_PROTO_DISABLE_IF_IS_CONST(Expr)) 1084 { 1085 return result_of::child_c<Expr &, N>::call(e); 1086 } 1087 1088 /// \overload 1089 /// 1090 template<long N, typename Expr> 1091 typename result_of::child_c<Expr const &, N>::type child_c(Expr const & e)1092 child_c(Expr const &e) 1093 { 1094 return result_of::child_c<Expr const &, N>::call(e); 1095 } 1096 1097 /// \brief Return the value stored within the specified Proto 1098 /// terminal expression. 1099 /// 1100 /// Return the the value stored within the specified Proto 1101 /// terminal expression. The value is returned by 1102 /// reference. 1103 /// 1104 /// \param expr The Proto terminal expression. 1105 /// \pre <tt>N::value == 0</tt> 1106 /// \throw nothrow 1107 /// \return A reference to the terminal's value 1108 template<typename Expr> 1109 typename result_of::value<Expr &>::type value(Expr & e BOOST_PROTO_DISABLE_IF_IS_CONST (Expr))1110 value(Expr &e BOOST_PROTO_DISABLE_IF_IS_CONST(Expr)) 1111 { 1112 return e.proto_base().child0; 1113 } 1114 1115 /// \overload 1116 /// 1117 template<typename Expr> 1118 typename result_of::value<Expr const &>::type value(Expr const & e)1119 value(Expr const &e) 1120 { 1121 return e.proto_base().child0; 1122 } 1123 1124 /// \brief Return the left child of the specified binary Proto 1125 /// expression. 1126 /// 1127 /// Return the left child of the specified binary Proto expression. The 1128 /// child is returned by reference. 1129 /// 1130 /// \param expr The Proto expression. 1131 /// \pre <tt>is_expr\<Expr\>::value</tt> is \c true. 1132 /// \pre <tt>2 == Expr::proto_arity::value</tt> 1133 /// \throw nothrow 1134 /// \return A reference to the left child 1135 template<typename Expr> 1136 typename result_of::left<Expr &>::type left(Expr & e BOOST_PROTO_DISABLE_IF_IS_CONST (Expr))1137 left(Expr &e BOOST_PROTO_DISABLE_IF_IS_CONST(Expr)) 1138 { 1139 return e.proto_base().child0; 1140 } 1141 1142 /// \overload 1143 /// 1144 template<typename Expr> 1145 typename result_of::left<Expr const &>::type left(Expr const & e)1146 left(Expr const &e) 1147 { 1148 return e.proto_base().child0; 1149 } 1150 1151 /// \brief Return the right child of the specified binary Proto 1152 /// expression. 1153 /// 1154 /// Return the right child of the specified binary Proto expression. The 1155 /// child is returned by reference. 1156 /// 1157 /// \param expr The Proto expression. 1158 /// \pre <tt>is_expr\<Expr\>::value</tt> is \c true. 1159 /// \pre <tt>2 == Expr::proto_arity::value</tt> 1160 /// \throw nothrow 1161 /// \return A reference to the right child 1162 template<typename Expr> 1163 typename result_of::right<Expr &>::type right(Expr & e BOOST_PROTO_DISABLE_IF_IS_CONST (Expr))1164 right(Expr &e BOOST_PROTO_DISABLE_IF_IS_CONST(Expr)) 1165 { 1166 return e.proto_base().child1; 1167 } 1168 1169 /// \overload 1170 /// 1171 template<typename Expr> 1172 typename result_of::right<Expr const &>::type right(Expr const & e)1173 right(Expr const &e) 1174 { 1175 return e.proto_base().child1; 1176 } 1177 1178 /// INTERNAL ONLY 1179 /// 1180 template<typename Domain> 1181 struct is_callable<functional::as_expr<Domain> > 1182 : mpl::true_ 1183 {}; 1184 1185 /// INTERNAL ONLY 1186 /// 1187 template<typename Domain> 1188 struct is_callable<functional::as_child<Domain> > 1189 : mpl::true_ 1190 {}; 1191 1192 /// INTERNAL ONLY 1193 /// 1194 template<long N> 1195 struct is_callable<functional::child_c<N> > 1196 : mpl::true_ 1197 {}; 1198 1199 /// INTERNAL ONLY 1200 /// 1201 template<typename N> 1202 struct is_callable<functional::child<N> > 1203 : mpl::true_ 1204 {}; 1205 1206 }} 1207 1208 #if BOOST_WORKAROUND( BOOST_MSVC, >= 1400 ) 1209 #pragma warning(pop) 1210 #endif 1211 1212 #endif 1213