]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | /*============================================================================= |
2 | Copyright (c) 2001-2011 Joel de Guzman | |
3 | Copyright (c) 2001-2011 Hartmut Kaiser | |
4 | Copyright (c) 2011 Bryce Lelbach | |
5 | ||
6 | Distributed under the Boost Software License, Version 1.0. (See accompanying | |
7 | file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
8 | =============================================================================*/ | |
9 | #if !defined(BOOST_SPIRIT_UTREE_OPERATORS) | |
10 | #define BOOST_SPIRIT_UTREE_OPERATORS | |
11 | ||
12 | #if defined(BOOST_MSVC) | |
13 | # pragma warning(push) | |
14 | # pragma warning(disable: 4804) | |
15 | # pragma warning(disable: 4805) | |
16 | #endif | |
17 | ||
18 | #include <exception> | |
19 | #if !defined(BOOST_SPIRIT_DISABLE_UTREE_IO) | |
20 | #include <ios> | |
21 | #include <boost/io/ios_state.hpp> | |
22 | #endif | |
23 | #include <boost/spirit/home/support/utree/utree.hpp> | |
24 | #include <boost/preprocessor/cat.hpp> | |
25 | #include <boost/throw_exception.hpp> | |
26 | #include <boost/type_traits/is_arithmetic.hpp> | |
27 | #include <boost/type_traits/is_integral.hpp> | |
28 | ||
29 | namespace boost { namespace spirit | |
30 | { | |
31 | // Relational operators | |
32 | bool operator==(utree const& a, utree const& b); | |
33 | bool operator<(utree const& a, utree const& b); | |
34 | bool operator!=(utree const& a, utree const& b); | |
35 | bool operator>(utree const& a, utree const& b); | |
36 | bool operator<=(utree const& a, utree const& b); | |
37 | bool operator>=(utree const& a, utree const& b); | |
38 | ||
39 | #if !defined(BOOST_SPIRIT_DISABLE_UTREE_IO) | |
40 | // output | |
41 | std::ostream& operator<<(std::ostream& out, utree const& x); | |
42 | std::ostream& operator<<(std::ostream& out, utree::invalid_type const& x); | |
43 | std::ostream& operator<<(std::ostream& out, utree::nil_type const& x); | |
44 | #endif | |
45 | ||
46 | // Logical operators | |
47 | utree operator&&(utree const& a, utree const& b); | |
48 | utree operator||(utree const& a, utree const& b); | |
49 | utree operator!(utree const& a); | |
50 | ||
51 | // Arithmetic operators | |
52 | utree operator+(utree const& a, utree const& b); | |
53 | utree operator-(utree const& a, utree const& b); | |
54 | utree operator*(utree const& a, utree const& b); | |
55 | utree operator/(utree const& a, utree const& b); | |
56 | utree operator%(utree const& a, utree const& b); | |
57 | utree operator-(utree const& a); | |
58 | ||
59 | // Bitwise operators | |
60 | utree operator&(utree const& a, utree const& b); | |
61 | utree operator|(utree const& a, utree const& b); | |
62 | utree operator^(utree const& a, utree const& b); | |
63 | utree operator<<(utree const& a, utree const& b); | |
64 | utree operator>>(utree const& a, utree const& b); | |
65 | utree operator~(utree const& a); | |
66 | ||
67 | // Implementation | |
68 | struct utree_is_equal | |
69 | { | |
70 | typedef bool result_type; | |
71 | ||
72 | template <typename A, typename B> | |
73 | bool dispatch(const A&, const B&, boost::mpl::false_) const | |
74 | { | |
75 | return false; // cannot compare different types by default | |
76 | } | |
77 | ||
78 | template <typename A, typename B> | |
79 | bool dispatch(const A& a, const B& b, boost::mpl::true_) const | |
80 | { | |
81 | return a == b; // for arithmetic types | |
82 | } | |
83 | ||
84 | template <typename A, typename B> | |
85 | bool operator()(const A& a, const B& b) const | |
86 | { | |
87 | return dispatch(a, b, | |
88 | boost::mpl::and_< | |
89 | boost::is_arithmetic<A>, | |
90 | boost::is_arithmetic<B> >()); | |
91 | } | |
92 | ||
93 | template <typename T> | |
94 | bool operator()(const T& a, const T& b) const | |
95 | { | |
96 | // This code works for lists | |
97 | return a == b; | |
98 | } | |
99 | ||
100 | template <typename Base, utree_type::info type_> | |
101 | bool operator()( | |
102 | basic_string<Base, type_> const& a, | |
103 | basic_string<Base, type_> const& b) const | |
104 | { | |
105 | return static_cast<Base const&>(a) == static_cast<Base const&>(b); | |
106 | } | |
107 | ||
108 | bool operator()(utree::invalid_type, utree::invalid_type) const | |
109 | { | |
110 | return true; | |
111 | } | |
112 | ||
113 | bool operator()(utree::nil_type, utree::nil_type) const | |
114 | { | |
115 | return true; | |
116 | } | |
117 | ||
118 | bool operator()(function_base const&, function_base const&) const | |
119 | { | |
120 | return false; // just don't allow comparison of functions | |
121 | } | |
122 | }; | |
123 | ||
124 | struct utree_is_less_than | |
125 | { | |
126 | typedef bool result_type; | |
127 | ||
128 | template <typename A, typename B> | |
129 | bool dispatch(const A&, const B&, boost::mpl::false_) const | |
130 | { | |
131 | return false; // cannot compare different types by default | |
132 | } | |
133 | ||
134 | template <typename A, typename B> | |
135 | bool dispatch(const A& a, const B& b, boost::mpl::true_) const | |
136 | { | |
137 | return a < b; // for arithmetic types | |
138 | } | |
139 | ||
140 | template <typename A, typename B> | |
141 | bool operator()(const A& a, const B& b) const | |
142 | { | |
143 | return dispatch(a, b, | |
144 | boost::mpl::and_< | |
145 | boost::is_arithmetic<A>, | |
146 | boost::is_arithmetic<B> >()); | |
147 | } | |
148 | ||
149 | template <typename T> | |
150 | bool operator()(const T& a, const T& b) const | |
151 | { | |
152 | // This code works for lists | |
153 | return a < b; | |
154 | } | |
155 | ||
156 | template <typename Base, utree_type::info type_> | |
157 | bool operator()( | |
158 | basic_string<Base, type_> const& a, | |
159 | basic_string<Base, type_> const& b) const | |
160 | { | |
161 | return static_cast<Base const&>(a) < static_cast<Base const&>(b); | |
162 | } | |
163 | ||
164 | bool operator()(utree::invalid_type, utree::invalid_type) const | |
165 | { | |
166 | BOOST_THROW_EXCEPTION(bad_type_exception | |
167 | ("no less-than comparison for this utree type", | |
168 | utree_type::invalid_type)); | |
169 | return false; // no less than comparison for nil | |
170 | } | |
171 | ||
172 | bool operator()(utree::nil_type, utree::nil_type) const | |
173 | { | |
174 | BOOST_THROW_EXCEPTION(bad_type_exception | |
175 | ("no less-than comparison for this utree type", | |
176 | utree_type::nil_type)); | |
177 | return false; // no less than comparison for nil | |
178 | } | |
179 | ||
180 | bool operator()(any_ptr const&, any_ptr const&) const | |
181 | { | |
182 | BOOST_THROW_EXCEPTION(bad_type_exception | |
183 | ("no less-than comparison for this utree type", | |
184 | utree_type::any_type)); | |
185 | return false; // no less than comparison for any_ptr | |
186 | } | |
187 | ||
188 | bool operator()(function_base const&, function_base const&) const | |
189 | { | |
190 | BOOST_THROW_EXCEPTION(bad_type_exception | |
191 | ("no less-than comparison for this utree type", | |
192 | utree_type::function_type)); | |
193 | return false; // no less than comparison of functions | |
194 | } | |
195 | }; | |
196 | ||
197 | #if !defined(BOOST_SPIRIT_DISABLE_UTREE_IO) | |
198 | struct utree_print | |
199 | { | |
200 | typedef void result_type; | |
201 | ||
202 | std::ostream& out; | |
203 | utree_print(std::ostream& out) : out(out) {} | |
204 | ||
205 | void operator()(utree::invalid_type) const | |
206 | { | |
207 | out << "<invalid> "; | |
208 | } | |
209 | ||
210 | void operator()(utree::nil_type) const | |
211 | { | |
212 | out << "<nil> "; | |
213 | } | |
214 | ||
215 | template <typename T> | |
216 | void operator()(T val) const | |
217 | { | |
218 | out << val << ' '; | |
219 | } | |
220 | ||
221 | void operator()(bool b) const | |
222 | { | |
223 | out << (b ? "true" : "false") << ' '; | |
224 | } | |
225 | ||
226 | void operator()(binary_range_type const& b) const | |
227 | { | |
228 | boost::io::ios_all_saver saver(out); | |
229 | out << "#"; | |
230 | out.width(2); | |
231 | out.fill('0'); | |
232 | ||
233 | typedef binary_range_type::const_iterator iterator; | |
234 | for (iterator i = b.begin(); i != b.end(); ++i) | |
235 | out << std::hex << int((unsigned char)*i); | |
236 | out << "# "; | |
237 | } | |
238 | ||
239 | void operator()(utf8_string_range_type const& str) const | |
240 | { | |
241 | typedef utf8_string_range_type::const_iterator iterator; | |
242 | iterator i = str.begin(); | |
243 | out << '"'; | |
244 | for (; i != str.end(); ++i) | |
245 | out << *i; | |
246 | out << "\" "; | |
247 | } | |
248 | ||
249 | void operator()(utf8_symbol_range_type const& str) const | |
250 | { | |
251 | typedef utf8_symbol_range_type::const_iterator iterator; | |
252 | iterator i = str.begin(); | |
253 | for (; i != str.end(); ++i) | |
254 | out << *i; | |
255 | out << ' '; | |
256 | } | |
257 | ||
258 | template <typename Iterator> | |
259 | void operator()(boost::iterator_range<Iterator> const& range) const | |
260 | { | |
261 | typedef typename boost::iterator_range<Iterator>::const_iterator iterator; | |
262 | (*this)('('); | |
263 | for (iterator i = range.begin(); i != range.end(); ++i) | |
264 | { | |
265 | boost::spirit::utree::visit(*i, *this); | |
266 | } | |
267 | (*this)(')'); | |
268 | } | |
269 | ||
270 | void operator()(any_ptr const&) const | |
271 | { | |
272 | return (*this)("<pointer>"); | |
273 | } | |
274 | ||
275 | void operator()(function_base const&) const | |
276 | { | |
277 | return (*this)("<function>"); | |
278 | } | |
279 | }; | |
280 | #endif | |
281 | ||
282 | template <typename Base> | |
283 | struct logical_function | |
284 | { | |
285 | typedef utree result_type; | |
286 | ||
287 | // We assume anything except false is true | |
288 | ||
289 | // binary | |
290 | template <typename A, typename B> | |
291 | utree operator()(A const& a, B const& b) const | |
292 | { | |
293 | return dispatch(a, b | |
294 | , boost::is_arithmetic<A>() | |
295 | , boost::is_arithmetic<B>()); | |
296 | } | |
297 | ||
298 | // binary | |
299 | template <typename A, typename B> | |
300 | utree dispatch(A const& a, B const& b, mpl::true_, mpl::true_) const | |
301 | { | |
302 | return Base::eval(a, b); // for arithmetic types | |
303 | } | |
304 | ||
305 | // binary | |
306 | template <typename A, typename B> | |
307 | utree dispatch(A const&, B const& b, mpl::false_, mpl::true_) const | |
308 | { | |
309 | return Base::eval(true, b); | |
310 | } | |
311 | ||
312 | // binary | |
313 | template <typename A, typename B> | |
314 | utree dispatch(A const& a, B const&, mpl::true_, mpl::false_) const | |
315 | { | |
316 | return Base::eval(a, true); | |
317 | } | |
318 | ||
319 | // binary | |
320 | template <typename A, typename B> | |
321 | utree dispatch(A const&, B const&, mpl::false_, mpl::false_) const | |
322 | { | |
323 | return Base::eval(true, true); | |
324 | } | |
325 | ||
326 | // unary | |
327 | template <typename A> | |
328 | utree operator()(A const& a) const | |
329 | { | |
330 | return dispatch(a, boost::is_arithmetic<A>()); | |
331 | } | |
332 | ||
333 | // unary | |
334 | template <typename A> | |
335 | utree dispatch(A const& a, mpl::true_) const | |
336 | { | |
337 | return Base::eval(a); | |
338 | } | |
339 | ||
340 | // unary | |
341 | template <typename A> | |
342 | utree dispatch(A const&, mpl::false_) const | |
343 | { | |
344 | return Base::eval(true); | |
345 | } | |
346 | }; | |
347 | ||
348 | template <typename Base> | |
349 | struct arithmetic_function | |
350 | { | |
351 | typedef utree result_type; | |
352 | ||
353 | template <typename A, typename B> | |
354 | utree dispatch(A const&, B const&, boost::mpl::false_) const | |
355 | { | |
356 | return utree(); // cannot apply to non-arithmetic types | |
357 | } | |
358 | ||
359 | template <typename A, typename B> | |
360 | utree dispatch(A const& a, B const& b, boost::mpl::true_) const | |
361 | { | |
362 | return Base::eval(a, b); // for arithmetic types | |
363 | } | |
364 | ||
365 | // binary | |
366 | template <typename A, typename B> | |
367 | utree operator()(A const& a, B const& b) const | |
368 | { | |
369 | return dispatch(a, b, | |
370 | boost::mpl::and_< | |
371 | boost::is_arithmetic<A>, | |
372 | boost::is_arithmetic<B> >()); | |
373 | } | |
374 | ||
375 | template <typename A> | |
376 | utree dispatch(A const&, boost::mpl::false_) const | |
377 | { | |
378 | return utree(); // cannot apply to non-arithmetic types | |
379 | } | |
380 | ||
381 | template <typename A> | |
382 | utree dispatch(A const& a, boost::mpl::true_) const | |
383 | { | |
384 | return Base::eval(a); // for arithmetic types | |
385 | } | |
386 | ||
387 | // unary | |
388 | template <typename A> | |
389 | utree operator()(A const& a) const | |
390 | { | |
391 | return dispatch(a, boost::is_arithmetic<A>()); | |
392 | } | |
393 | }; | |
394 | ||
395 | template <typename Base> | |
396 | struct integral_function | |
397 | { | |
398 | typedef utree result_type; | |
399 | ||
400 | template <typename A, typename B> | |
401 | utree dispatch(A const&, B const&, boost::mpl::false_) const | |
402 | { | |
403 | return utree(); // cannot apply to non-integral types | |
404 | } | |
405 | ||
406 | template <typename A, typename B> | |
407 | utree dispatch(A const& a, B const& b, boost::mpl::true_) const | |
408 | { | |
409 | return Base::eval(a, b); // for integral types | |
410 | } | |
411 | ||
412 | // binary | |
413 | template <typename A, typename B> | |
414 | utree operator()(A const& a, B const& b) const | |
415 | { | |
416 | return dispatch(a, b, | |
417 | boost::mpl::and_< | |
418 | boost::is_integral<A>, | |
419 | boost::is_integral<B> >()); | |
420 | } | |
421 | ||
422 | template <typename A> | |
423 | utree dispatch(A const&, boost::mpl::false_) const | |
424 | { | |
425 | return utree(); // cannot apply to non-integral types | |
426 | } | |
427 | ||
428 | template <typename A> | |
429 | utree dispatch(A const& a, boost::mpl::true_) const | |
430 | { | |
431 | return Base::eval(a); // for integral types | |
432 | } | |
433 | ||
434 | // unary | |
435 | template <typename A> | |
436 | utree operator()(A const& a) const | |
437 | { | |
438 | return dispatch(a, boost::is_integral<A>()); | |
439 | } | |
440 | }; | |
441 | ||
442 | #define BOOST_SPIRIT_UTREE_CREATE_FUNCTION(name, expr, base) \ | |
443 | struct BOOST_PP_CAT(function_impl_, name) \ | |
444 | { \ | |
445 | template <typename A, typename B> \ | |
446 | static utree eval(A const& a, B const& b) \ | |
447 | { \ | |
448 | return utree(expr); \ | |
449 | } \ | |
450 | template <typename A> \ | |
451 | static utree eval(A const& a) \ | |
452 | { \ | |
453 | static int b; \ | |
454 | (void) b; \ | |
455 | return utree(expr); \ | |
456 | } \ | |
457 | }; \ | |
458 | base<BOOST_PP_CAT(function_impl_, name)> const \ | |
459 | BOOST_PP_CAT(base, BOOST_PP_CAT(_, name)) = {}; \ | |
460 | /***/ | |
461 | ||
462 | #define BOOST_SPIRIT_UTREE_CREATE_ARITHMETIC_FUNCTION(name, expr) \ | |
463 | BOOST_SPIRIT_UTREE_CREATE_FUNCTION(name, expr, arithmetic_function) \ | |
464 | /***/ | |
465 | ||
466 | #define BOOST_SPIRIT_UTREE_CREATE_INTEGRAL_FUNCTION(name, expr) \ | |
467 | BOOST_SPIRIT_UTREE_CREATE_FUNCTION(name, expr, integral_function) \ | |
468 | /***/ | |
469 | ||
470 | #define BOOST_SPIRIT_UTREE_CREATE_LOGICAL_FUNCTION(name, expr) \ | |
471 | BOOST_SPIRIT_UTREE_CREATE_FUNCTION(name, expr, logical_function) \ | |
472 | /***/ | |
473 | ||
474 | inline bool operator==(utree const& a, utree const& b) | |
475 | { | |
476 | return utree::visit(a, b, utree_is_equal()); | |
477 | } | |
478 | ||
479 | inline bool operator<(utree const& a, utree const& b) | |
480 | { | |
481 | return utree::visit(a, b, utree_is_less_than()); | |
482 | } | |
483 | ||
484 | inline bool operator!=(utree const& a, utree const& b) | |
485 | { | |
486 | return !(a == b); | |
487 | } | |
488 | ||
489 | inline bool operator>(utree const& a, utree const& b) | |
490 | { | |
491 | return b < a; | |
492 | } | |
493 | ||
494 | inline bool operator<=(utree const& a, utree const& b) | |
495 | { | |
496 | return !(b < a); | |
497 | } | |
498 | ||
499 | inline bool operator>=(utree const& a, utree const& b) | |
500 | { | |
501 | return !(a < b); | |
502 | } | |
503 | ||
504 | #if !defined(BOOST_SPIRIT_DISABLE_UTREE_IO) | |
505 | inline std::ostream& operator<<(std::ostream& out, utree const& x) | |
506 | { | |
507 | utree::visit(x, utree_print(out)); | |
508 | return out; | |
509 | } | |
510 | ||
511 | inline std::ostream& operator<<(std::ostream& out, utree::invalid_type const&) | |
512 | { | |
513 | return out; | |
514 | } | |
515 | ||
516 | inline std::ostream& operator<<(std::ostream& out, utree::nil_type const&) | |
517 | { | |
518 | return out; | |
519 | } | |
520 | #endif | |
521 | ||
522 | BOOST_SPIRIT_UTREE_CREATE_LOGICAL_FUNCTION(and_, a&&b) | |
523 | BOOST_SPIRIT_UTREE_CREATE_LOGICAL_FUNCTION(or_, a||b) | |
524 | BOOST_SPIRIT_UTREE_CREATE_LOGICAL_FUNCTION(not_, !a) | |
525 | ||
526 | BOOST_SPIRIT_UTREE_CREATE_ARITHMETIC_FUNCTION(plus, a+b) | |
527 | BOOST_SPIRIT_UTREE_CREATE_ARITHMETIC_FUNCTION(minus, a-b) | |
528 | BOOST_SPIRIT_UTREE_CREATE_ARITHMETIC_FUNCTION(times, a*b) | |
529 | BOOST_SPIRIT_UTREE_CREATE_ARITHMETIC_FUNCTION(divides, a/b) | |
530 | BOOST_SPIRIT_UTREE_CREATE_INTEGRAL_FUNCTION(modulus, a%b) | |
531 | BOOST_SPIRIT_UTREE_CREATE_ARITHMETIC_FUNCTION(negate, -a) | |
532 | ||
533 | BOOST_SPIRIT_UTREE_CREATE_INTEGRAL_FUNCTION(bitand_, a&b) | |
534 | BOOST_SPIRIT_UTREE_CREATE_INTEGRAL_FUNCTION(bitor_, a|b) | |
535 | BOOST_SPIRIT_UTREE_CREATE_INTEGRAL_FUNCTION(bitxor_, a^b) | |
536 | BOOST_SPIRIT_UTREE_CREATE_INTEGRAL_FUNCTION(shift_left, a<<b) | |
537 | BOOST_SPIRIT_UTREE_CREATE_INTEGRAL_FUNCTION(shift_right, a>>b) | |
538 | BOOST_SPIRIT_UTREE_CREATE_INTEGRAL_FUNCTION(invert, ~a) | |
539 | ||
540 | inline utree operator&&(utree const& a, utree const& b) | |
541 | { | |
542 | return utree::visit(a, b, logical_function_and_); | |
543 | } | |
544 | ||
545 | inline utree operator||(utree const& a, utree const& b) | |
546 | { | |
547 | return utree::visit(a, b, logical_function_or_); | |
548 | } | |
549 | ||
550 | inline utree operator!(utree const& a) | |
551 | { | |
552 | return utree::visit(a, logical_function_not_); | |
553 | } | |
554 | ||
555 | inline utree operator+(utree const& a, utree const& b) | |
556 | { | |
557 | utree r = utree::visit(a, b, arithmetic_function_plus); | |
558 | if (r.which() == utree_type::invalid_type) | |
559 | { | |
560 | BOOST_THROW_EXCEPTION(bad_type_exception | |
561 | ("addition performed on non-arithmetic utree types", | |
562 | a.which(), b.which())); | |
563 | } | |
564 | return r; | |
565 | } | |
566 | ||
567 | inline utree operator-(utree const& a, utree const& b) | |
568 | { | |
569 | utree r = utree::visit(a, b, arithmetic_function_minus); | |
570 | if (r.which() == utree_type::invalid_type) | |
571 | { | |
572 | BOOST_THROW_EXCEPTION(bad_type_exception | |
573 | ("subtraction performed on non-arithmetic utree types", | |
574 | a.which(), b.which())); | |
575 | } | |
576 | return r; | |
577 | } | |
578 | ||
579 | inline utree operator*(utree const& a, utree const& b) | |
580 | { | |
581 | utree r = utree::visit(a, b, arithmetic_function_times); | |
582 | if (r.which() == utree_type::invalid_type) | |
583 | { | |
584 | BOOST_THROW_EXCEPTION(bad_type_exception | |
585 | ("multiplication performed on non-arithmetic utree types", | |
586 | a.which(), b.which())); | |
587 | } | |
588 | return r; | |
589 | } | |
590 | ||
591 | inline utree operator/(utree const& a, utree const& b) | |
592 | { | |
593 | utree r = utree::visit(a, b, arithmetic_function_divides); | |
594 | if (r.which() == utree_type::invalid_type) | |
595 | { | |
596 | BOOST_THROW_EXCEPTION(bad_type_exception | |
597 | ("division performed on non-arithmetic utree types", | |
598 | a.which(), b.which())); | |
599 | } | |
600 | return r; | |
601 | } | |
602 | ||
603 | inline utree operator%(utree const& a, utree const& b) | |
604 | { | |
605 | utree r = utree::visit(a, b, integral_function_modulus); | |
606 | if (r.which() == utree_type::invalid_type) | |
607 | { | |
608 | BOOST_THROW_EXCEPTION(bad_type_exception | |
609 | ("modulos performed on non-integral utree types", | |
610 | a.which(), b.which())); | |
611 | } | |
612 | return r; | |
613 | } | |
614 | ||
615 | inline utree operator-(utree const& a) | |
616 | { | |
617 | utree r = utree::visit(a, arithmetic_function_negate); | |
618 | if (r.which() == utree_type::invalid_type) | |
619 | { | |
620 | BOOST_THROW_EXCEPTION(bad_type_exception | |
621 | ("negation performed on non-arithmetic utree type", | |
622 | a.which())); | |
623 | } | |
624 | return r; | |
625 | } | |
626 | ||
627 | inline utree operator&(utree const& a, utree const& b) | |
628 | { | |
629 | utree r = utree::visit(a, b, integral_function_bitand_); | |
630 | if (r.which() == utree_type::invalid_type) | |
631 | { | |
632 | BOOST_THROW_EXCEPTION(bad_type_exception | |
633 | ("bitwise and performed on non-integral utree types", | |
634 | a.which(), b.which())); | |
635 | } | |
636 | return r; | |
637 | } | |
638 | ||
639 | inline utree operator|(utree const& a, utree const& b) | |
640 | { | |
641 | utree r = utree::visit(a, b, integral_function_bitor_); | |
642 | if (r.which() == utree_type::invalid_type) | |
643 | { | |
644 | BOOST_THROW_EXCEPTION(bad_type_exception | |
645 | ("bitwise or performed on non-integral utree types", | |
646 | a.which(), b.which())); | |
647 | } | |
648 | return r; | |
649 | } | |
650 | ||
651 | inline utree operator^(utree const& a, utree const& b) | |
652 | { | |
653 | utree r = utree::visit(a, b, integral_function_bitxor_); | |
654 | if (r.which() == utree_type::invalid_type) | |
655 | { | |
656 | BOOST_THROW_EXCEPTION(bad_type_exception | |
657 | ("bitwise xor performed on non-integral utree types", | |
658 | a.which(), b.which())); | |
659 | } | |
660 | return r; | |
661 | } | |
662 | ||
663 | inline utree operator<<(utree const& a, utree const& b) | |
664 | { | |
665 | utree r = utree::visit(a, b, integral_function_shift_left); | |
666 | if (r.which() == utree_type::invalid_type) | |
667 | { | |
668 | BOOST_THROW_EXCEPTION(bad_type_exception | |
669 | ("left shift performed on non-integral utree types", | |
670 | a.which(), b.which())); | |
671 | } | |
672 | return r; | |
673 | } | |
674 | ||
675 | inline utree operator>>(utree const& a, utree const& b) | |
676 | { | |
677 | utree r = utree::visit(a, b, integral_function_shift_right); | |
678 | if (r.which() == utree_type::invalid_type) | |
679 | { | |
680 | BOOST_THROW_EXCEPTION(bad_type_exception | |
681 | ("right shift performed on non-integral utree types", | |
682 | a.which(), b.which())); | |
683 | } | |
684 | return r; | |
685 | } | |
686 | ||
687 | inline utree operator~(utree const& a) | |
688 | { | |
689 | utree r = utree::visit(a, integral_function_invert); | |
690 | if (r.which() == utree_type::invalid_type) | |
691 | { | |
692 | BOOST_THROW_EXCEPTION(bad_type_exception | |
693 | ("inversion performed on non-integral utree type", | |
694 | a.which())); | |
695 | } | |
696 | return r; | |
697 | } | |
698 | }} | |
699 | ||
700 | #if defined(BOOST_MSVC) | |
701 | # pragma warning(pop) | |
702 | #endif | |
703 | ||
704 | #endif |