Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: /// \file operators.hpp Chris@16: /// Contains all the overloaded operators that make it possible to build Chris@16: /// Proto expression trees. Chris@16: // Chris@16: // Copyright 2008 Eric Niebler. Distributed under the Boost Chris@16: // Software License, Version 1.0. (See accompanying file Chris@16: // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) Chris@16: Chris@16: #ifndef BOOST_PROTO_OPERATORS_HPP_EAN_04_01_2005 Chris@16: #define BOOST_PROTO_OPERATORS_HPP_EAN_04_01_2005 Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@101: #if defined(_MSC_VER) Chris@16: # pragma warning(push) Chris@16: # pragma warning(disable : 4714) // function 'xxx' marked as __forceinline not inlined Chris@16: #endif Chris@16: Chris@16: namespace boost { namespace proto Chris@16: { Chris@16: namespace detail Chris@16: { Chris@16: template Chris@16: struct lazy_matches Chris@16: : proto::matches Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct enable_unary Chris@16: : boost::lazy_enable_if_c< Chris@16: boost::mpl::and_< Chris@16: Trait Chris@16: , lazy_matches, Grammar> Chris@16: >::value Chris@16: , result_of::make_expr Chris@16: > Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct enable_unary Chris@16: : boost::lazy_enable_if_c< Chris@16: Trait::value Chris@16: , result_of::make_expr Chris@16: > Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct enable_unary Chris@16: : enable_unary< Chris@16: typename domain_of::type Chris@16: , typename domain_of::type::proto_grammar Chris@16: , Trait Chris@16: , Tag Chris@16: , Arg & Chris@16: > Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct enable_binary Chris@16: : boost::lazy_enable_if_c< Chris@16: boost::mpl::and_< Chris@16: Trait Chris@16: , lazy_matches, Grammar> Chris@16: >::value Chris@16: , result_of::make_expr Chris@16: > Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct enable_binary Chris@16: : boost::lazy_enable_if_c< Chris@16: Trait::value Chris@16: , result_of::make_expr Chris@16: > Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct enable_binary Chris@16: : enable_binary< Chris@16: typename deduce_domain2::type Chris@16: , typename deduce_domain2::type::proto_grammar Chris@16: , Trait Chris@16: , Tag Chris@16: , Left & Chris@16: , Right & Chris@16: > Chris@16: {}; Chris@16: Chris@16: } // detail Chris@16: Chris@16: #define BOOST_PROTO_UNARY_OP_IS_POSTFIX_0 Chris@16: #define BOOST_PROTO_UNARY_OP_IS_POSTFIX_1 , int Chris@16: Chris@16: #ifdef BOOST_NO_CXX11_RVALUE_REFERENCES Chris@16: Chris@16: #define BOOST_PROTO_DEFINE_UNARY_OPERATOR(OP, TAG, TRAIT, DOMAIN, POST) \ Chris@16: template \ Chris@16: BOOST_PROTO_DISABLE_MSVC_C4714 BOOST_FORCEINLINE \ Chris@16: typename boost::proto::detail::enable_unary< \ Chris@16: DOMAIN \ Chris@16: , DOMAIN::proto_grammar \ Chris@16: , BOOST_PROTO_APPLY_UNARY_(TRAIT, Arg) \ Chris@16: , TAG \ Chris@16: , Arg & \ Chris@16: >::type const \ Chris@16: operator OP(Arg &arg BOOST_PROTO_UNARY_OP_IS_POSTFIX_ ## POST) \ Chris@16: { \ Chris@16: return boost::proto::detail::make_expr_()(arg); \ Chris@16: } \ Chris@16: \ Chris@16: template \ Chris@16: BOOST_PROTO_DISABLE_MSVC_C4714 BOOST_FORCEINLINE \ Chris@16: typename boost::proto::detail::enable_unary< \ Chris@16: DOMAIN \ Chris@16: , DOMAIN::proto_grammar \ Chris@16: , BOOST_PROTO_APPLY_UNARY_(TRAIT, Arg) \ Chris@16: , TAG \ Chris@16: , Arg const & \ Chris@16: >::type const \ Chris@16: operator OP(Arg const &arg BOOST_PROTO_UNARY_OP_IS_POSTFIX_ ## POST) \ Chris@16: { \ Chris@16: return boost::proto::detail::make_expr_()(arg); \ Chris@16: } \ Chris@16: /**/ Chris@16: Chris@16: #define BOOST_PROTO_DEFINE_BINARY_OPERATOR(OP, TAG, TRAIT, DOMAIN) \ Chris@16: template \ Chris@16: BOOST_PROTO_DISABLE_MSVC_C4714 BOOST_FORCEINLINE \ Chris@16: typename boost::proto::detail::enable_binary< \ Chris@16: DOMAIN \ Chris@16: , DOMAIN::proto_grammar \ Chris@16: , BOOST_PROTO_APPLY_BINARY_(TRAIT, Left, Right) \ Chris@16: , TAG \ Chris@16: , Left & \ Chris@16: , Right & \ Chris@16: >::type const \ Chris@16: operator OP(Left &left, Right &right) \ Chris@16: { \ Chris@16: return boost::proto::detail::make_expr_()(left, right); \ Chris@16: } \ Chris@16: \ Chris@16: template \ Chris@16: BOOST_PROTO_DISABLE_MSVC_C4714 BOOST_FORCEINLINE \ Chris@16: typename boost::proto::detail::enable_binary< \ Chris@16: DOMAIN \ Chris@16: , DOMAIN::proto_grammar \ Chris@16: , BOOST_PROTO_APPLY_BINARY_(TRAIT, Left, Right) \ Chris@16: , TAG \ Chris@16: , Left & \ Chris@16: , Right const & \ Chris@16: >::type const \ Chris@16: operator OP(Left &left, Right const &right) \ Chris@16: { \ Chris@16: return boost::proto::detail::make_expr_()(left, right); \ Chris@16: } \ Chris@16: \ Chris@16: template \ Chris@16: BOOST_PROTO_DISABLE_MSVC_C4714 BOOST_FORCEINLINE \ Chris@16: typename boost::proto::detail::enable_binary< \ Chris@16: DOMAIN \ Chris@16: , DOMAIN::proto_grammar \ Chris@16: , BOOST_PROTO_APPLY_BINARY_(TRAIT, Left, Right) \ Chris@16: , TAG \ Chris@16: , Left const & \ Chris@16: , Right & \ Chris@16: >::type const \ Chris@16: operator OP(Left const &left, Right &right) \ Chris@16: { \ Chris@16: return boost::proto::detail::make_expr_()(left, right); \ Chris@16: } \ Chris@16: \ Chris@16: template \ Chris@16: BOOST_PROTO_DISABLE_MSVC_C4714 BOOST_FORCEINLINE \ Chris@16: typename boost::proto::detail::enable_binary< \ Chris@16: DOMAIN \ Chris@16: , DOMAIN::proto_grammar \ Chris@16: , BOOST_PROTO_APPLY_BINARY_(TRAIT, Left, Right) \ Chris@16: , TAG \ Chris@16: , Left const & \ Chris@16: , Right const & \ Chris@16: >::type const \ Chris@16: operator OP(Left const &left, Right const &right) \ Chris@16: { \ Chris@16: return boost::proto::detail::make_expr_()(left, right);\ Chris@16: } \ Chris@16: /**/ Chris@16: Chris@16: #else Chris@16: Chris@16: #define BOOST_PROTO_DEFINE_UNARY_OPERATOR(OP, TAG, TRAIT, DOMAIN, POST) \ Chris@16: template \ Chris@16: BOOST_PROTO_DISABLE_MSVC_C4714 BOOST_FORCEINLINE \ Chris@16: typename boost::proto::detail::enable_unary< \ Chris@16: DOMAIN \ Chris@16: , DOMAIN::proto_grammar \ Chris@16: , BOOST_PROTO_APPLY_UNARY_(TRAIT, Arg) \ Chris@16: , TAG \ Chris@16: , Arg const & \ Chris@16: >::type const \ Chris@16: operator OP(Arg &&arg BOOST_PROTO_UNARY_OP_IS_POSTFIX_ ## POST) \ Chris@16: { \ Chris@16: return boost::proto::detail::make_expr_()(arg); \ Chris@16: } \ Chris@16: /**/ Chris@16: Chris@16: #define BOOST_PROTO_DEFINE_BINARY_OPERATOR(OP, TAG, TRAIT, DOMAIN) \ Chris@16: template \ Chris@16: BOOST_PROTO_DISABLE_MSVC_C4714 BOOST_FORCEINLINE \ Chris@16: typename boost::proto::detail::enable_binary< \ Chris@16: DOMAIN \ Chris@16: , DOMAIN::proto_grammar \ Chris@16: , BOOST_PROTO_APPLY_BINARY_(TRAIT, Left, Right) \ Chris@16: , TAG \ Chris@16: , Left const & \ Chris@16: , Right const & \ Chris@16: >::type const \ Chris@16: operator OP(Left &&left, Right &&right) \ Chris@16: { \ Chris@16: return boost::proto::detail::make_expr_()(left, right);\ Chris@16: } \ Chris@16: /**/ Chris@16: Chris@16: #endif Chris@16: Chris@16: #define BOOST_PROTO_DEFINE_OPERATORS(TRAIT, DOMAIN) \ Chris@16: BOOST_PROTO_DEFINE_UNARY_OPERATOR(+, boost::proto::tag::unary_plus, TRAIT, DOMAIN, 0) \ Chris@16: BOOST_PROTO_DEFINE_UNARY_OPERATOR(-, boost::proto::tag::negate, TRAIT, DOMAIN, 0) \ Chris@16: BOOST_PROTO_DEFINE_UNARY_OPERATOR(*, boost::proto::tag::dereference, TRAIT, DOMAIN, 0) \ Chris@16: BOOST_PROTO_DEFINE_UNARY_OPERATOR(~, boost::proto::tag::complement, TRAIT, DOMAIN, 0) \ Chris@16: BOOST_PROTO_DEFINE_UNARY_OPERATOR(&, boost::proto::tag::address_of, TRAIT, DOMAIN, 0) \ Chris@16: BOOST_PROTO_DEFINE_UNARY_OPERATOR(!, boost::proto::tag::logical_not, TRAIT, DOMAIN, 0) \ Chris@16: BOOST_PROTO_DEFINE_UNARY_OPERATOR(++, boost::proto::tag::pre_inc, TRAIT, DOMAIN, 0) \ Chris@16: BOOST_PROTO_DEFINE_UNARY_OPERATOR(--, boost::proto::tag::pre_dec, TRAIT, DOMAIN, 0) \ Chris@16: BOOST_PROTO_DEFINE_UNARY_OPERATOR(++, boost::proto::tag::post_inc, TRAIT, DOMAIN, 1) \ Chris@16: BOOST_PROTO_DEFINE_UNARY_OPERATOR(--, boost::proto::tag::post_dec, TRAIT, DOMAIN, 1) \ Chris@16: BOOST_PROTO_DEFINE_BINARY_OPERATOR(<<, boost::proto::tag::shift_left, TRAIT, DOMAIN) \ Chris@16: BOOST_PROTO_DEFINE_BINARY_OPERATOR(>>, boost::proto::tag::shift_right, TRAIT, DOMAIN) \ Chris@16: BOOST_PROTO_DEFINE_BINARY_OPERATOR(*, boost::proto::tag::multiplies, TRAIT, DOMAIN) \ Chris@16: BOOST_PROTO_DEFINE_BINARY_OPERATOR(/, boost::proto::tag::divides, TRAIT, DOMAIN) \ Chris@16: BOOST_PROTO_DEFINE_BINARY_OPERATOR(%, boost::proto::tag::modulus, TRAIT, DOMAIN) \ Chris@16: BOOST_PROTO_DEFINE_BINARY_OPERATOR(+, boost::proto::tag::plus, TRAIT, DOMAIN) \ Chris@16: BOOST_PROTO_DEFINE_BINARY_OPERATOR(-, boost::proto::tag::minus, TRAIT, DOMAIN) \ Chris@16: BOOST_PROTO_DEFINE_BINARY_OPERATOR(<, boost::proto::tag::less, TRAIT, DOMAIN) \ Chris@16: BOOST_PROTO_DEFINE_BINARY_OPERATOR(>, boost::proto::tag::greater, TRAIT, DOMAIN) \ Chris@16: BOOST_PROTO_DEFINE_BINARY_OPERATOR(<=, boost::proto::tag::less_equal, TRAIT, DOMAIN) \ Chris@16: BOOST_PROTO_DEFINE_BINARY_OPERATOR(>=, boost::proto::tag::greater_equal, TRAIT, DOMAIN) \ Chris@16: BOOST_PROTO_DEFINE_BINARY_OPERATOR(==, boost::proto::tag::equal_to, TRAIT, DOMAIN) \ Chris@16: BOOST_PROTO_DEFINE_BINARY_OPERATOR(!=, boost::proto::tag::not_equal_to, TRAIT, DOMAIN) \ Chris@16: BOOST_PROTO_DEFINE_BINARY_OPERATOR(||, boost::proto::tag::logical_or, TRAIT, DOMAIN) \ Chris@16: BOOST_PROTO_DEFINE_BINARY_OPERATOR(&&, boost::proto::tag::logical_and, TRAIT, DOMAIN) \ Chris@16: BOOST_PROTO_DEFINE_BINARY_OPERATOR(&, boost::proto::tag::bitwise_and, TRAIT, DOMAIN) \ Chris@16: BOOST_PROTO_DEFINE_BINARY_OPERATOR(|, boost::proto::tag::bitwise_or, TRAIT, DOMAIN) \ Chris@16: BOOST_PROTO_DEFINE_BINARY_OPERATOR(^, boost::proto::tag::bitwise_xor, TRAIT, DOMAIN) \ Chris@16: BOOST_PROTO_DEFINE_BINARY_OPERATOR(BOOST_PP_COMMA(), boost::proto::tag::comma, TRAIT, DOMAIN) \ Chris@16: BOOST_PROTO_DEFINE_BINARY_OPERATOR(->*, boost::proto::tag::mem_ptr, TRAIT, DOMAIN) \ Chris@16: BOOST_PROTO_DEFINE_BINARY_OPERATOR(<<=, boost::proto::tag::shift_left_assign, TRAIT, DOMAIN) \ Chris@16: BOOST_PROTO_DEFINE_BINARY_OPERATOR(>>=, boost::proto::tag::shift_right_assign, TRAIT, DOMAIN) \ Chris@16: BOOST_PROTO_DEFINE_BINARY_OPERATOR(*=, boost::proto::tag::multiplies_assign, TRAIT, DOMAIN) \ Chris@16: BOOST_PROTO_DEFINE_BINARY_OPERATOR(/=, boost::proto::tag::divides_assign, TRAIT, DOMAIN) \ Chris@16: BOOST_PROTO_DEFINE_BINARY_OPERATOR(%=, boost::proto::tag::modulus_assign, TRAIT, DOMAIN) \ Chris@16: BOOST_PROTO_DEFINE_BINARY_OPERATOR(+=, boost::proto::tag::plus_assign, TRAIT, DOMAIN) \ Chris@16: BOOST_PROTO_DEFINE_BINARY_OPERATOR(-=, boost::proto::tag::minus_assign, TRAIT, DOMAIN) \ Chris@16: BOOST_PROTO_DEFINE_BINARY_OPERATOR(&=, boost::proto::tag::bitwise_and_assign, TRAIT, DOMAIN) \ Chris@16: BOOST_PROTO_DEFINE_BINARY_OPERATOR(|=, boost::proto::tag::bitwise_or_assign, TRAIT, DOMAIN) \ Chris@16: BOOST_PROTO_DEFINE_BINARY_OPERATOR(^=, boost::proto::tag::bitwise_xor_assign, TRAIT, DOMAIN) \ Chris@16: /**/ Chris@16: Chris@16: // Extensions are a superset of Proto expressions Chris@16: template Chris@16: struct is_extension Chris@16: : is_expr Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct is_extension Chris@16: : is_expr Chris@16: {}; Chris@16: Chris@16: #define BOOST_PROTO_APPLY_UNARY_(TRAIT, ARG) TRAIT Chris@16: #define BOOST_PROTO_APPLY_BINARY_(TRAIT, LEFT, RIGHT) boost::mpl::or_, TRAIT > Chris@16: Chris@16: namespace exprns_ Chris@16: { Chris@16: // This defines all of Proto's built-in free operator overloads Chris@16: BOOST_PROTO_DEFINE_OPERATORS(is_extension, deduce_domain) Chris@16: Chris@16: // if_else, for the non-overloadable ternary conditional operator ?: Chris@16: template Chris@16: BOOST_FORCEINLINE Chris@16: typename result_of::make_expr< Chris@16: tag::if_else_ Chris@16: , deduce_domain Chris@16: , A0 const & Chris@16: , A1 const & Chris@16: , A2 const & Chris@16: >::type const Chris@16: if_else(A0 const &a0, A1 const &a1, A2 const &a2) Chris@16: { Chris@16: return proto::detail::make_expr_< Chris@16: tag::if_else_ Chris@16: , deduce_domain Chris@16: , A0 const & Chris@16: , A1 const & Chris@16: , A2 const & Chris@16: >()(a0, a1, a2); Chris@16: } Chris@16: } Chris@16: Chris@16: using exprns_::if_else; Chris@16: Chris@16: #undef BOOST_PROTO_APPLY_UNARY_ Chris@16: #undef BOOST_PROTO_APPLY_BINARY_ Chris@16: Chris@16: // Redefine BOOST_PROTO_APPLY_UNARY_ and BOOST_PROTO_APPLY_BINARY_ so that end users Chris@16: // can use BOOST_PROTO_DEFINE_OPERATORS to define Proto operator overloads that work Chris@16: // with their own terminal types. Chris@16: Chris@16: #ifdef BOOST_NO_CXX11_RVALUE_REFERENCES Chris@16: Chris@16: #define BOOST_PROTO_APPLY_UNARY_(TRAIT, ARG) \ Chris@16: boost::mpl::and_< \ Chris@16: TRAIT \ Chris@16: , boost::mpl::not_ > \ Chris@16: > \ Chris@16: /**/ Chris@16: Chris@16: #define BOOST_PROTO_APPLY_BINARY_(TRAIT, LEFT, RIGHT) \ Chris@16: boost::mpl::and_< \ Chris@16: boost::mpl::or_, TRAIT > \ Chris@16: , boost::mpl::not_< \ Chris@16: boost::mpl::or_< \ Chris@16: boost::proto::is_extension \ Chris@16: , boost::proto::is_extension \ Chris@16: > \ Chris@16: > \ Chris@16: > \ Chris@16: /**/ Chris@16: Chris@16: #else Chris@16: Chris@16: #define BOOST_PROTO_APPLY_UNARY_(TRAIT, ARG) \ Chris@16: boost::mpl::and_< \ Chris@16: TRAIT \ Chris@16: , boost::mpl::not_ > \ Chris@16: > \ Chris@16: /**/ Chris@16: Chris@16: #define BOOST_PROTO_APPLY_BINARY_(TRAIT, LEFT, RIGHT) \ Chris@16: boost::mpl::and_< \ Chris@16: boost::mpl::or_, TRAIT > \ Chris@16: , boost::mpl::not_< \ Chris@16: boost::mpl::or_< \ Chris@16: boost::proto::is_extension \ Chris@16: , boost::proto::is_extension \ Chris@16: > \ Chris@16: > \ Chris@16: > \ Chris@16: /**/ Chris@16: Chris@16: #endif Chris@16: Chris@16: }} Chris@16: Chris@101: #if defined(_MSC_VER) Chris@16: # pragma warning(pop) Chris@16: #endif Chris@16: Chris@16: #endif