1 ///////////////////////////////////////////////////////////////////////////////
2 /// \file operators.hpp
3 /// Contains all the overloaded operators that make it possible to build
4 /// Proto expression trees.
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)
10 #ifndef BOOST_PROTO_OPERATORS_HPP_EAN_04_01_2005
11 #define BOOST_PROTO_OPERATORS_HPP_EAN_04_01_2005
13 #include <boost/config.hpp>
14 #include <boost/preprocessor/punctuation/comma.hpp>
15 #include <boost/mpl/logical.hpp>
16 #include <boost/utility/enable_if.hpp>
17 #include <boost/proto/proto_fwd.hpp>
18 #include <boost/proto/tags.hpp>
19 #include <boost/proto/domain.hpp>
20 #include <boost/proto/matches.hpp>
21 #include <boost/proto/generate.hpp>
22 #include <boost/proto/make_expr.hpp>
25 # pragma warning(push)
26 # pragma warning(disable : 4714) // function 'xxx' marked as __forceinline not inlined
29 namespace boost { namespace proto
33 template<typename MakeExpr, typename Grammar>
35 : proto::matches<typename MakeExpr::type, Grammar>
38 template<typename Domain, typename Grammar, typename Trait, typename Tag, typename Arg>
40 : boost::lazy_enable_if_c<
43 , lazy_matches<result_of::make_expr<Tag, basic_default_domain, Arg>, Grammar>
45 , result_of::make_expr<Tag, Domain, Arg>
49 template<typename Domain, typename Trait, typename Tag, typename Arg>
50 struct enable_unary<Domain, proto::_, Trait, Tag, Arg &>
51 : boost::lazy_enable_if_c<
53 , result_of::make_expr<Tag, Domain, Arg &>
57 template<typename Trait, typename Tag, typename Arg>
58 struct enable_unary<deduce_domain, not_a_grammar, Trait, Tag, Arg &>
60 typename domain_of<Arg>::type
61 , typename domain_of<Arg>::type::proto_grammar
68 template<typename Domain, typename Grammar, typename Trait, typename Tag, typename Left, typename Right>
70 : boost::lazy_enable_if_c<
73 , lazy_matches<result_of::make_expr<Tag, basic_default_domain, Left, Right>, Grammar>
75 , result_of::make_expr<Tag, Domain, Left, Right>
79 template<typename Domain, typename Trait, typename Tag, typename Left, typename Right>
80 struct enable_binary<Domain, proto::_, Trait, Tag, Left &, Right &>
81 : boost::lazy_enable_if_c<
83 , result_of::make_expr<Tag, Domain, Left &, Right &>
87 template<typename Trait, typename Tag, typename Left, typename Right>
88 struct enable_binary<deduce_domain, not_a_grammar, Trait, Tag, Left &, Right &>
90 typename deduce_domain2<Left, Right>::type
91 , typename deduce_domain2<Left, Right>::type::proto_grammar
101 #define BOOST_PROTO_UNARY_OP_IS_POSTFIX_0
102 #define BOOST_PROTO_UNARY_OP_IS_POSTFIX_1 , int
104 #ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
106 #define BOOST_PROTO_DEFINE_UNARY_OPERATOR(OP, TAG, TRAIT, DOMAIN, POST) \
107 template<typename Arg> \
108 BOOST_PROTO_DISABLE_MSVC_C4714 BOOST_FORCEINLINE \
109 typename boost::proto::detail::enable_unary< \
111 , DOMAIN::proto_grammar \
112 , BOOST_PROTO_APPLY_UNARY_(TRAIT, Arg) \
116 operator OP(Arg &arg BOOST_PROTO_UNARY_OP_IS_POSTFIX_ ## POST) \
118 return boost::proto::detail::make_expr_<TAG, DOMAIN, Arg &>()(arg); \
121 template<typename Arg> \
122 BOOST_PROTO_DISABLE_MSVC_C4714 BOOST_FORCEINLINE \
123 typename boost::proto::detail::enable_unary< \
125 , DOMAIN::proto_grammar \
126 , BOOST_PROTO_APPLY_UNARY_(TRAIT, Arg) \
130 operator OP(Arg const &arg BOOST_PROTO_UNARY_OP_IS_POSTFIX_ ## POST) \
132 return boost::proto::detail::make_expr_<TAG, DOMAIN, Arg const &>()(arg); \
136 #define BOOST_PROTO_DEFINE_BINARY_OPERATOR(OP, TAG, TRAIT, DOMAIN) \
137 template<typename Left, typename Right> \
138 BOOST_PROTO_DISABLE_MSVC_C4714 BOOST_FORCEINLINE \
139 typename boost::proto::detail::enable_binary< \
141 , DOMAIN::proto_grammar \
142 , BOOST_PROTO_APPLY_BINARY_(TRAIT, Left, Right) \
147 operator OP(Left &left, Right &right) \
149 return boost::proto::detail::make_expr_<TAG, DOMAIN, Left &, Right &>()(left, right); \
152 template<typename Left, typename Right> \
153 BOOST_PROTO_DISABLE_MSVC_C4714 BOOST_FORCEINLINE \
154 typename boost::proto::detail::enable_binary< \
156 , DOMAIN::proto_grammar \
157 , BOOST_PROTO_APPLY_BINARY_(TRAIT, Left, Right) \
162 operator OP(Left &left, Right const &right) \
164 return boost::proto::detail::make_expr_<TAG, DOMAIN, Left &, Right const &>()(left, right); \
167 template<typename Left, typename Right> \
168 BOOST_PROTO_DISABLE_MSVC_C4714 BOOST_FORCEINLINE \
169 typename boost::proto::detail::enable_binary< \
171 , DOMAIN::proto_grammar \
172 , BOOST_PROTO_APPLY_BINARY_(TRAIT, Left, Right) \
177 operator OP(Left const &left, Right &right) \
179 return boost::proto::detail::make_expr_<TAG, DOMAIN, Left const &, Right &>()(left, right); \
182 template<typename Left, typename Right> \
183 BOOST_PROTO_DISABLE_MSVC_C4714 BOOST_FORCEINLINE \
184 typename boost::proto::detail::enable_binary< \
186 , DOMAIN::proto_grammar \
187 , BOOST_PROTO_APPLY_BINARY_(TRAIT, Left, Right) \
192 operator OP(Left const &left, Right const &right) \
194 return boost::proto::detail::make_expr_<TAG, DOMAIN, Left const &, Right const &>()(left, right);\
200 #define BOOST_PROTO_DEFINE_UNARY_OPERATOR(OP, TAG, TRAIT, DOMAIN, POST) \
201 template<typename Arg> \
202 BOOST_PROTO_DISABLE_MSVC_C4714 BOOST_FORCEINLINE \
203 typename boost::proto::detail::enable_unary< \
205 , DOMAIN::proto_grammar \
206 , BOOST_PROTO_APPLY_UNARY_(TRAIT, Arg) \
210 operator OP(Arg &&arg BOOST_PROTO_UNARY_OP_IS_POSTFIX_ ## POST) \
212 return boost::proto::detail::make_expr_<TAG, DOMAIN, Arg const &>()(arg); \
216 #define BOOST_PROTO_DEFINE_BINARY_OPERATOR(OP, TAG, TRAIT, DOMAIN) \
217 template<typename Left, typename Right> \
218 BOOST_PROTO_DISABLE_MSVC_C4714 BOOST_FORCEINLINE \
219 typename boost::proto::detail::enable_binary< \
221 , DOMAIN::proto_grammar \
222 , BOOST_PROTO_APPLY_BINARY_(TRAIT, Left, Right) \
227 operator OP(Left &&left, Right &&right) \
229 return boost::proto::detail::make_expr_<TAG, DOMAIN, Left const &, Right const &>()(left, right);\
235 #define BOOST_PROTO_DEFINE_OPERATORS(TRAIT, DOMAIN) \
236 BOOST_PROTO_DEFINE_UNARY_OPERATOR(+, boost::proto::tag::unary_plus, TRAIT, DOMAIN, 0) \
237 BOOST_PROTO_DEFINE_UNARY_OPERATOR(-, boost::proto::tag::negate, TRAIT, DOMAIN, 0) \
238 BOOST_PROTO_DEFINE_UNARY_OPERATOR(*, boost::proto::tag::dereference, TRAIT, DOMAIN, 0) \
239 BOOST_PROTO_DEFINE_UNARY_OPERATOR(~, boost::proto::tag::complement, TRAIT, DOMAIN, 0) \
240 BOOST_PROTO_DEFINE_UNARY_OPERATOR(&, boost::proto::tag::address_of, TRAIT, DOMAIN, 0) \
241 BOOST_PROTO_DEFINE_UNARY_OPERATOR(!, boost::proto::tag::logical_not, TRAIT, DOMAIN, 0) \
242 BOOST_PROTO_DEFINE_UNARY_OPERATOR(++, boost::proto::tag::pre_inc, TRAIT, DOMAIN, 0) \
243 BOOST_PROTO_DEFINE_UNARY_OPERATOR(--, boost::proto::tag::pre_dec, TRAIT, DOMAIN, 0) \
244 BOOST_PROTO_DEFINE_UNARY_OPERATOR(++, boost::proto::tag::post_inc, TRAIT, DOMAIN, 1) \
245 BOOST_PROTO_DEFINE_UNARY_OPERATOR(--, boost::proto::tag::post_dec, TRAIT, DOMAIN, 1) \
246 BOOST_PROTO_DEFINE_BINARY_OPERATOR(<<, boost::proto::tag::shift_left, TRAIT, DOMAIN) \
247 BOOST_PROTO_DEFINE_BINARY_OPERATOR(>>, boost::proto::tag::shift_right, TRAIT, DOMAIN) \
248 BOOST_PROTO_DEFINE_BINARY_OPERATOR(*, boost::proto::tag::multiplies, TRAIT, DOMAIN) \
249 BOOST_PROTO_DEFINE_BINARY_OPERATOR(/, boost::proto::tag::divides, TRAIT, DOMAIN) \
250 BOOST_PROTO_DEFINE_BINARY_OPERATOR(%, boost::proto::tag::modulus, TRAIT, DOMAIN) \
251 BOOST_PROTO_DEFINE_BINARY_OPERATOR(+, boost::proto::tag::plus, TRAIT, DOMAIN) \
252 BOOST_PROTO_DEFINE_BINARY_OPERATOR(-, boost::proto::tag::minus, TRAIT, DOMAIN) \
253 BOOST_PROTO_DEFINE_BINARY_OPERATOR(<, boost::proto::tag::less, TRAIT, DOMAIN) \
254 BOOST_PROTO_DEFINE_BINARY_OPERATOR(>, boost::proto::tag::greater, TRAIT, DOMAIN) \
255 BOOST_PROTO_DEFINE_BINARY_OPERATOR(<=, boost::proto::tag::less_equal, TRAIT, DOMAIN) \
256 BOOST_PROTO_DEFINE_BINARY_OPERATOR(>=, boost::proto::tag::greater_equal, TRAIT, DOMAIN) \
257 BOOST_PROTO_DEFINE_BINARY_OPERATOR(==, boost::proto::tag::equal_to, TRAIT, DOMAIN) \
258 BOOST_PROTO_DEFINE_BINARY_OPERATOR(!=, boost::proto::tag::not_equal_to, TRAIT, DOMAIN) \
259 BOOST_PROTO_DEFINE_BINARY_OPERATOR(||, boost::proto::tag::logical_or, TRAIT, DOMAIN) \
260 BOOST_PROTO_DEFINE_BINARY_OPERATOR(&&, boost::proto::tag::logical_and, TRAIT, DOMAIN) \
261 BOOST_PROTO_DEFINE_BINARY_OPERATOR(&, boost::proto::tag::bitwise_and, TRAIT, DOMAIN) \
262 BOOST_PROTO_DEFINE_BINARY_OPERATOR(|, boost::proto::tag::bitwise_or, TRAIT, DOMAIN) \
263 BOOST_PROTO_DEFINE_BINARY_OPERATOR(^, boost::proto::tag::bitwise_xor, TRAIT, DOMAIN) \
264 BOOST_PROTO_DEFINE_BINARY_OPERATOR(BOOST_PP_COMMA(), boost::proto::tag::comma, TRAIT, DOMAIN) \
265 BOOST_PROTO_DEFINE_BINARY_OPERATOR(->*, boost::proto::tag::mem_ptr, TRAIT, DOMAIN) \
266 BOOST_PROTO_DEFINE_BINARY_OPERATOR(<<=, boost::proto::tag::shift_left_assign, TRAIT, DOMAIN) \
267 BOOST_PROTO_DEFINE_BINARY_OPERATOR(>>=, boost::proto::tag::shift_right_assign, TRAIT, DOMAIN) \
268 BOOST_PROTO_DEFINE_BINARY_OPERATOR(*=, boost::proto::tag::multiplies_assign, TRAIT, DOMAIN) \
269 BOOST_PROTO_DEFINE_BINARY_OPERATOR(/=, boost::proto::tag::divides_assign, TRAIT, DOMAIN) \
270 BOOST_PROTO_DEFINE_BINARY_OPERATOR(%=, boost::proto::tag::modulus_assign, TRAIT, DOMAIN) \
271 BOOST_PROTO_DEFINE_BINARY_OPERATOR(+=, boost::proto::tag::plus_assign, TRAIT, DOMAIN) \
272 BOOST_PROTO_DEFINE_BINARY_OPERATOR(-=, boost::proto::tag::minus_assign, TRAIT, DOMAIN) \
273 BOOST_PROTO_DEFINE_BINARY_OPERATOR(&=, boost::proto::tag::bitwise_and_assign, TRAIT, DOMAIN) \
274 BOOST_PROTO_DEFINE_BINARY_OPERATOR(|=, boost::proto::tag::bitwise_or_assign, TRAIT, DOMAIN) \
275 BOOST_PROTO_DEFINE_BINARY_OPERATOR(^=, boost::proto::tag::bitwise_xor_assign, TRAIT, DOMAIN) \
278 // Extensions are a superset of Proto expressions
285 struct is_extension<T &>
289 #define BOOST_PROTO_APPLY_UNARY_(TRAIT, ARG) TRAIT<ARG>
290 #define BOOST_PROTO_APPLY_BINARY_(TRAIT, LEFT, RIGHT) boost::mpl::or_<TRAIT<LEFT>, TRAIT<RIGHT> >
294 // This defines all of Proto's built-in free operator overloads
295 BOOST_PROTO_DEFINE_OPERATORS(is_extension, deduce_domain)
297 // if_else, for the non-overloadable ternary conditional operator ?:
298 template<typename A0, typename A1, typename A2>
300 typename result_of::make_expr<
307 if_else(A0 const &a0, A1 const &a1, A2 const &a2)
309 return proto::detail::make_expr_<
319 using exprns_::if_else;
321 #undef BOOST_PROTO_APPLY_UNARY_
322 #undef BOOST_PROTO_APPLY_BINARY_
324 // Redefine BOOST_PROTO_APPLY_UNARY_ and BOOST_PROTO_APPLY_BINARY_ so that end users
325 // can use BOOST_PROTO_DEFINE_OPERATORS to define Proto operator overloads that work
326 // with their own terminal types.
328 #ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
330 #define BOOST_PROTO_APPLY_UNARY_(TRAIT, ARG) \
333 , boost::mpl::not_<boost::proto::is_extension<ARG> > \
337 #define BOOST_PROTO_APPLY_BINARY_(TRAIT, LEFT, RIGHT) \
339 boost::mpl::or_<TRAIT<LEFT>, TRAIT<RIGHT> > \
340 , boost::mpl::not_< \
342 boost::proto::is_extension<LEFT> \
343 , boost::proto::is_extension<RIGHT> \
351 #define BOOST_PROTO_APPLY_UNARY_(TRAIT, ARG) \
353 TRAIT<BOOST_PROTO_UNCVREF(ARG) > \
354 , boost::mpl::not_<boost::proto::is_extension<ARG> > \
358 #define BOOST_PROTO_APPLY_BINARY_(TRAIT, LEFT, RIGHT) \
360 boost::mpl::or_<TRAIT<BOOST_PROTO_UNCVREF(LEFT) >, TRAIT<BOOST_PROTO_UNCVREF(RIGHT) > > \
361 , boost::mpl::not_< \
363 boost::proto::is_extension<LEFT> \
364 , boost::proto::is_extension<RIGHT> \
374 #if defined(_MSC_VER)
375 # pragma warning(pop)