1///////////////////////////////////////////////////////////////////////////////
2/// \file operators.hpp
3/// Contains all the overloaded operators that make it possible to build
4/// Proto expression trees.
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_OPERATORS_HPP_EAN_04_01_2005
11#define BOOST_PROTO_OPERATORS_HPP_EAN_04_01_2005
12
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>
23
24#if defined(_MSC_VER)
25# pragma warning(push)
26# pragma warning(disable : 4714) // function 'xxx' marked as __forceinline not inlined
27#endif
28
29namespace boost { namespace proto
30{
31 namespace detail
32 {
33 template<typename MakeExpr, typename Grammar>
34 struct lazy_matches
35 : proto::matches<typename MakeExpr::type, Grammar>
36 {};
37
38 template<typename Domain, typename Grammar, typename Trait, typename Tag, typename Arg>
39 struct enable_unary
40 : boost::lazy_enable_if_c<
41 boost::mpl::and_<
42 Trait
43 , lazy_matches<result_of::make_expr<Tag, basic_default_domain, Arg>, Grammar>
44 >::value
45 , result_of::make_expr<Tag, Domain, Arg>
46 >
47 {};
48
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<
52 Trait::value
53 , result_of::make_expr<Tag, Domain, Arg &>
54 >
55 {};
56
57 template<typename Trait, typename Tag, typename Arg>
58 struct enable_unary<deduce_domain, not_a_grammar, Trait, Tag, Arg &>
59 : enable_unary<
60 typename domain_of<Arg>::type
61 , typename domain_of<Arg>::type::proto_grammar
62 , Trait
63 , Tag
64 , Arg &
65 >
66 {};
67
68 template<typename Domain, typename Grammar, typename Trait, typename Tag, typename Left, typename Right>
69 struct enable_binary
70 : boost::lazy_enable_if_c<
71 boost::mpl::and_<
72 Trait
73 , lazy_matches<result_of::make_expr<Tag, basic_default_domain, Left, Right>, Grammar>
74 >::value
75 , result_of::make_expr<Tag, Domain, Left, Right>
76 >
77 {};
78
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<
82 Trait::value
83 , result_of::make_expr<Tag, Domain, Left &, Right &>
84 >
85 {};
86
87 template<typename Trait, typename Tag, typename Left, typename Right>
88 struct enable_binary<deduce_domain, not_a_grammar, Trait, Tag, Left &, Right &>
89 : enable_binary<
90 typename deduce_domain2<Left, Right>::type
91 , typename deduce_domain2<Left, Right>::type::proto_grammar
92 , Trait
93 , Tag
94 , Left &
95 , Right &
96 >
97 {};
98
99 } // detail
100
101#define BOOST_PROTO_UNARY_OP_IS_POSTFIX_0
102#define BOOST_PROTO_UNARY_OP_IS_POSTFIX_1 , int
103
104#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
105
106#define BOOST_PROTO_DEFINE_UNARY_OPERATOR(OP, TAG, TRAIT, DOMAIN, POST) \
107 BOOST_PROTO_PUSH_WARNINGS \
108 \
109 template<typename Arg> \
110 BOOST_PROTO_DISABLE_MSVC_C4714 BOOST_FORCEINLINE \
111 typename boost::proto::detail::enable_unary< \
112 DOMAIN \
113 , DOMAIN::proto_grammar \
114 , BOOST_PROTO_APPLY_UNARY_(TRAIT, Arg) \
115 , TAG \
116 , Arg & \
117 >::type const \
118 operator OP(Arg &arg BOOST_PROTO_UNARY_OP_IS_POSTFIX_ ## POST) \
119 { \
120 return boost::proto::detail::make_expr_<TAG, DOMAIN, Arg &>()(arg); \
121 } \
122 \
123 template<typename Arg> \
124 BOOST_PROTO_DISABLE_MSVC_C4714 BOOST_FORCEINLINE \
125 typename boost::proto::detail::enable_unary< \
126 DOMAIN \
127 , DOMAIN::proto_grammar \
128 , BOOST_PROTO_APPLY_UNARY_(TRAIT, Arg) \
129 , TAG \
130 , Arg const & \
131 >::type const \
132 operator OP(Arg const &arg BOOST_PROTO_UNARY_OP_IS_POSTFIX_ ## POST) \
133 { \
134 return boost::proto::detail::make_expr_<TAG, DOMAIN, Arg const &>()(arg); \
135 } \
136 \
137 BOOST_PROTO_POP_WARNINGS \
138 /**/
139
140#define BOOST_PROTO_DEFINE_BINARY_OPERATOR(OP, TAG, TRAIT, DOMAIN) \
141 BOOST_PROTO_PUSH_WARNINGS \
142 \
143 template<typename Left, typename Right> \
144 BOOST_PROTO_DISABLE_MSVC_C4714 BOOST_FORCEINLINE \
145 typename boost::proto::detail::enable_binary< \
146 DOMAIN \
147 , DOMAIN::proto_grammar \
148 , BOOST_PROTO_APPLY_BINARY_(TRAIT, Left, Right) \
149 , TAG \
150 , Left & \
151 , Right & \
152 >::type const \
153 operator OP(Left &left, Right &right) \
154 { \
155 return boost::proto::detail::make_expr_<TAG, DOMAIN, Left &, Right &>()(left, right); \
156 } \
157 \
158 template<typename Left, typename Right> \
159 BOOST_PROTO_DISABLE_MSVC_C4714 BOOST_FORCEINLINE \
160 typename boost::proto::detail::enable_binary< \
161 DOMAIN \
162 , DOMAIN::proto_grammar \
163 , BOOST_PROTO_APPLY_BINARY_(TRAIT, Left, Right) \
164 , TAG \
165 , Left & \
166 , Right const & \
167 >::type const \
168 operator OP(Left &left, Right const &right) \
169 { \
170 return boost::proto::detail::make_expr_<TAG, DOMAIN, Left &, Right const &>()(left, right); \
171 } \
172 \
173 template<typename Left, typename Right> \
174 BOOST_PROTO_DISABLE_MSVC_C4714 BOOST_FORCEINLINE \
175 typename boost::proto::detail::enable_binary< \
176 DOMAIN \
177 , DOMAIN::proto_grammar \
178 , BOOST_PROTO_APPLY_BINARY_(TRAIT, Left, Right) \
179 , TAG \
180 , Left const & \
181 , Right & \
182 >::type const \
183 operator OP(Left const &left, Right &right) \
184 { \
185 return boost::proto::detail::make_expr_<TAG, DOMAIN, Left const &, Right &>()(left, right); \
186 } \
187 \
188 template<typename Left, typename Right> \
189 BOOST_PROTO_DISABLE_MSVC_C4714 BOOST_FORCEINLINE \
190 typename boost::proto::detail::enable_binary< \
191 DOMAIN \
192 , DOMAIN::proto_grammar \
193 , BOOST_PROTO_APPLY_BINARY_(TRAIT, Left, Right) \
194 , TAG \
195 , Left const & \
196 , Right const & \
197 >::type const \
198 operator OP(Left const &left, Right const &right) \
199 { \
200 return boost::proto::detail::make_expr_<TAG, DOMAIN, Left const &, Right const &>()(left, right);\
201 } \
202 \
203 BOOST_PROTO_POP_WARNINGS \
204 /**/
205
206#else
207
208#define BOOST_PROTO_DEFINE_UNARY_OPERATOR(OP, TAG, TRAIT, DOMAIN, POST) \
209 template<typename Arg> \
210 BOOST_PROTO_PUSH_WARNINGS \
211 BOOST_PROTO_DISABLE_MSVC_C4714 BOOST_FORCEINLINE \
212 typename boost::proto::detail::enable_unary< \
213 DOMAIN \
214 , DOMAIN::proto_grammar \
215 , BOOST_PROTO_APPLY_UNARY_(TRAIT, Arg) \
216 , TAG \
217 , Arg const & \
218 >::type const \
219 operator OP(Arg &&arg BOOST_PROTO_UNARY_OP_IS_POSTFIX_ ## POST) \
220 { \
221 return boost::proto::detail::make_expr_<TAG, DOMAIN, Arg const &>()(arg); \
222 } \
223 BOOST_PROTO_POP_WARNINGS \
224 /**/
225
226#define BOOST_PROTO_DEFINE_BINARY_OPERATOR(OP, TAG, TRAIT, DOMAIN) \
227 template<typename Left, typename Right> \
228 BOOST_PROTO_PUSH_WARNINGS \
229 BOOST_PROTO_DISABLE_MSVC_C4714 BOOST_FORCEINLINE \
230 typename boost::proto::detail::enable_binary< \
231 DOMAIN \
232 , DOMAIN::proto_grammar \
233 , BOOST_PROTO_APPLY_BINARY_(TRAIT, Left, Right) \
234 , TAG \
235 , Left const & \
236 , Right const & \
237 >::type const \
238 operator OP(Left &&left, Right &&right) \
239 { \
240 return boost::proto::detail::make_expr_<TAG, DOMAIN, Left const &, Right const &>()(left, right);\
241 } \
242 BOOST_PROTO_POP_WARNINGS \
243 /**/
244
245#endif
246
247#define BOOST_PROTO_DEFINE_OPERATORS(TRAIT, DOMAIN) \
248 BOOST_PROTO_DEFINE_UNARY_OPERATOR(+, boost::proto::tag::unary_plus, TRAIT, DOMAIN, 0) \
249 BOOST_PROTO_DEFINE_UNARY_OPERATOR(-, boost::proto::tag::negate, TRAIT, DOMAIN, 0) \
250 BOOST_PROTO_DEFINE_UNARY_OPERATOR(*, boost::proto::tag::dereference, TRAIT, DOMAIN, 0) \
251 BOOST_PROTO_DEFINE_UNARY_OPERATOR(~, boost::proto::tag::complement, TRAIT, DOMAIN, 0) \
252 BOOST_PROTO_DEFINE_UNARY_OPERATOR(&, boost::proto::tag::address_of, TRAIT, DOMAIN, 0) \
253 BOOST_PROTO_DEFINE_UNARY_OPERATOR(!, boost::proto::tag::logical_not, TRAIT, DOMAIN, 0) \
254 BOOST_PROTO_DEFINE_UNARY_OPERATOR(++, boost::proto::tag::pre_inc, TRAIT, DOMAIN, 0) \
255 BOOST_PROTO_DEFINE_UNARY_OPERATOR(--, boost::proto::tag::pre_dec, TRAIT, DOMAIN, 0) \
256 BOOST_PROTO_DEFINE_UNARY_OPERATOR(++, boost::proto::tag::post_inc, TRAIT, DOMAIN, 1) \
257 BOOST_PROTO_DEFINE_UNARY_OPERATOR(--, boost::proto::tag::post_dec, TRAIT, DOMAIN, 1) \
258 BOOST_PROTO_DEFINE_BINARY_OPERATOR(<<, boost::proto::tag::shift_left, TRAIT, DOMAIN) \
259 BOOST_PROTO_DEFINE_BINARY_OPERATOR(>>, boost::proto::tag::shift_right, TRAIT, DOMAIN) \
260 BOOST_PROTO_DEFINE_BINARY_OPERATOR(*, boost::proto::tag::multiplies, TRAIT, DOMAIN) \
261 BOOST_PROTO_DEFINE_BINARY_OPERATOR(/, boost::proto::tag::divides, TRAIT, DOMAIN) \
262 BOOST_PROTO_DEFINE_BINARY_OPERATOR(%, boost::proto::tag::modulus, TRAIT, DOMAIN) \
263 BOOST_PROTO_DEFINE_BINARY_OPERATOR(+, boost::proto::tag::plus, TRAIT, DOMAIN) \
264 BOOST_PROTO_DEFINE_BINARY_OPERATOR(-, boost::proto::tag::minus, TRAIT, DOMAIN) \
265 BOOST_PROTO_DEFINE_BINARY_OPERATOR(<, boost::proto::tag::less, TRAIT, DOMAIN) \
266 BOOST_PROTO_DEFINE_BINARY_OPERATOR(>, boost::proto::tag::greater, TRAIT, DOMAIN) \
267 BOOST_PROTO_DEFINE_BINARY_OPERATOR(<=, boost::proto::tag::less_equal, TRAIT, DOMAIN) \
268 BOOST_PROTO_DEFINE_BINARY_OPERATOR(>=, boost::proto::tag::greater_equal, TRAIT, DOMAIN) \
269 BOOST_PROTO_DEFINE_BINARY_OPERATOR(==, boost::proto::tag::equal_to, TRAIT, DOMAIN) \
270 BOOST_PROTO_DEFINE_BINARY_OPERATOR(!=, boost::proto::tag::not_equal_to, TRAIT, DOMAIN) \
271 BOOST_PROTO_DEFINE_BINARY_OPERATOR(||, boost::proto::tag::logical_or, TRAIT, DOMAIN) \
272 BOOST_PROTO_DEFINE_BINARY_OPERATOR(&&, boost::proto::tag::logical_and, TRAIT, DOMAIN) \
273 BOOST_PROTO_DEFINE_BINARY_OPERATOR(&, boost::proto::tag::bitwise_and, TRAIT, DOMAIN) \
274 BOOST_PROTO_DEFINE_BINARY_OPERATOR(|, boost::proto::tag::bitwise_or, TRAIT, DOMAIN) \
275 BOOST_PROTO_DEFINE_BINARY_OPERATOR(^, boost::proto::tag::bitwise_xor, TRAIT, DOMAIN) \
276 BOOST_PROTO_DEFINE_BINARY_OPERATOR(BOOST_PP_COMMA(), boost::proto::tag::comma, TRAIT, DOMAIN) \
277 BOOST_PROTO_DEFINE_BINARY_OPERATOR(->*, boost::proto::tag::mem_ptr, TRAIT, DOMAIN) \
278 BOOST_PROTO_DEFINE_BINARY_OPERATOR(<<=, boost::proto::tag::shift_left_assign, TRAIT, DOMAIN) \
279 BOOST_PROTO_DEFINE_BINARY_OPERATOR(>>=, boost::proto::tag::shift_right_assign, TRAIT, DOMAIN) \
280 BOOST_PROTO_DEFINE_BINARY_OPERATOR(*=, boost::proto::tag::multiplies_assign, TRAIT, DOMAIN) \
281 BOOST_PROTO_DEFINE_BINARY_OPERATOR(/=, boost::proto::tag::divides_assign, TRAIT, DOMAIN) \
282 BOOST_PROTO_DEFINE_BINARY_OPERATOR(%=, boost::proto::tag::modulus_assign, TRAIT, DOMAIN) \
283 BOOST_PROTO_DEFINE_BINARY_OPERATOR(+=, boost::proto::tag::plus_assign, TRAIT, DOMAIN) \
284 BOOST_PROTO_DEFINE_BINARY_OPERATOR(-=, boost::proto::tag::minus_assign, TRAIT, DOMAIN) \
285 BOOST_PROTO_DEFINE_BINARY_OPERATOR(&=, boost::proto::tag::bitwise_and_assign, TRAIT, DOMAIN) \
286 BOOST_PROTO_DEFINE_BINARY_OPERATOR(|=, boost::proto::tag::bitwise_or_assign, TRAIT, DOMAIN) \
287 BOOST_PROTO_DEFINE_BINARY_OPERATOR(^=, boost::proto::tag::bitwise_xor_assign, TRAIT, DOMAIN) \
288 /**/
289
290 // Extensions are a superset of Proto expressions
291 template<typename T>
292 struct is_extension
293 : is_expr<T>
294 {};
295
296 template<typename T>
297 struct is_extension<T &>
298 : is_expr<T>
299 {};
300
301 #define BOOST_PROTO_APPLY_UNARY_(TRAIT, ARG) TRAIT<ARG>
302 #define BOOST_PROTO_APPLY_BINARY_(TRAIT, LEFT, RIGHT) boost::mpl::or_<TRAIT<LEFT>, TRAIT<RIGHT> >
303
304 namespace exprns_
305 {
306 // This defines all of Proto's built-in free operator overloads
307 BOOST_PROTO_DEFINE_OPERATORS(is_extension, deduce_domain)
308
309 // if_else, for the non-overloadable ternary conditional operator ?:
310 template<typename A0, typename A1, typename A2>
311 BOOST_FORCEINLINE
312 typename result_of::make_expr<
313 tag::if_else_
314 , deduce_domain
315 , A0 const &
316 , A1 const &
317 , A2 const &
318 >::type const
319 if_else(A0 const &a0, A1 const &a1, A2 const &a2)
320 {
321 return proto::detail::make_expr_<
322 tag::if_else_
323 , deduce_domain
324 , A0 const &
325 , A1 const &
326 , A2 const &
327 >()(a0, a1, a2);
328 }
329 }
330
331 using exprns_::if_else;
332
333 #undef BOOST_PROTO_APPLY_UNARY_
334 #undef BOOST_PROTO_APPLY_BINARY_
335
336 // Redefine BOOST_PROTO_APPLY_UNARY_ and BOOST_PROTO_APPLY_BINARY_ so that end users
337 // can use BOOST_PROTO_DEFINE_OPERATORS to define Proto operator overloads that work
338 // with their own terminal types.
339
340#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
341
342 #define BOOST_PROTO_APPLY_UNARY_(TRAIT, ARG) \
343 boost::mpl::and_< \
344 TRAIT<ARG> \
345 , boost::mpl::not_<boost::proto::is_extension<ARG> > \
346 > \
347 /**/
348
349 #define BOOST_PROTO_APPLY_BINARY_(TRAIT, LEFT, RIGHT) \
350 boost::mpl::and_< \
351 boost::mpl::or_<TRAIT<LEFT>, TRAIT<RIGHT> > \
352 , boost::mpl::not_< \
353 boost::mpl::or_< \
354 boost::proto::is_extension<LEFT> \
355 , boost::proto::is_extension<RIGHT> \
356 > \
357 > \
358 > \
359 /**/
360
361#else
362
363 #define BOOST_PROTO_APPLY_UNARY_(TRAIT, ARG) \
364 boost::mpl::and_< \
365 TRAIT<BOOST_PROTO_UNCVREF(ARG) > \
366 , boost::mpl::not_<boost::proto::is_extension<ARG> > \
367 > \
368 /**/
369
370 #define BOOST_PROTO_APPLY_BINARY_(TRAIT, LEFT, RIGHT) \
371 boost::mpl::and_< \
372 boost::mpl::or_<TRAIT<BOOST_PROTO_UNCVREF(LEFT) >, TRAIT<BOOST_PROTO_UNCVREF(RIGHT) > > \
373 , boost::mpl::not_< \
374 boost::mpl::or_< \
375 boost::proto::is_extension<LEFT> \
376 , boost::proto::is_extension<RIGHT> \
377 > \
378 > \
379 > \
380 /**/
381
382#endif
383
384}}
385
386#if defined(_MSC_VER)
387# pragma warning(pop)
388#endif
389
390#endif
391

source code of boost/libs/proto/include/boost/proto/operators.hpp