]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 | ||
29 | namespace 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) \ | |
20effc67 TL |
107 | BOOST_PROTO_PUSH_WARNINGS \ |
108 | \ | |
7c673cae FG |
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 | } \ | |
20effc67 TL |
136 | \ |
137 | BOOST_PROTO_POP_WARNINGS \ | |
7c673cae FG |
138 | /**/ |
139 | ||
140 | #define BOOST_PROTO_DEFINE_BINARY_OPERATOR(OP, TAG, TRAIT, DOMAIN) \ | |
20effc67 TL |
141 | BOOST_PROTO_PUSH_WARNINGS \ |
142 | \ | |
7c673cae FG |
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 | } \ | |
20effc67 TL |
202 | \ |
203 | BOOST_PROTO_POP_WARNINGS \ | |
7c673cae FG |
204 | /**/ |
205 | ||
206 | #else | |
207 | ||
208 | #define BOOST_PROTO_DEFINE_UNARY_OPERATOR(OP, TAG, TRAIT, DOMAIN, POST) \ | |
209 | template<typename Arg> \ | |
20effc67 | 210 | BOOST_PROTO_PUSH_WARNINGS \ |
7c673cae FG |
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 | } \ | |
20effc67 | 223 | BOOST_PROTO_POP_WARNINGS \ |
7c673cae FG |
224 | /**/ |
225 | ||
226 | #define BOOST_PROTO_DEFINE_BINARY_OPERATOR(OP, TAG, TRAIT, DOMAIN) \ | |
227 | template<typename Left, typename Right> \ | |
20effc67 | 228 | BOOST_PROTO_PUSH_WARNINGS \ |
7c673cae FG |
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 | } \ | |
20effc67 | 242 | BOOST_PROTO_POP_WARNINGS \ |
7c673cae FG |
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 |