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>
dispatchboost::spirit::utree_is_equal73         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>
dispatchboost::spirit::utree_is_equal79         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>
operator ()boost::spirit::utree_is_equal85         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>
operator ()boost::spirit::utree_is_equal94         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_>
operator ()boost::spirit::utree_is_equal101         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 
operator ()boost::spirit::utree_is_equal108         bool operator()(utree::invalid_type, utree::invalid_type) const
109         {
110             return true;
111         }
112 
operator ()boost::spirit::utree_is_equal113         bool operator()(utree::nil_type, utree::nil_type) const
114         {
115             return true;
116         }
117 
operator ()boost::spirit::utree_is_equal118         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>
dispatchboost::spirit::utree_is_less_than129         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>
dispatchboost::spirit::utree_is_less_than135         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>
operator ()boost::spirit::utree_is_less_than141         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>
operator ()boost::spirit::utree_is_less_than150         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_>
operator ()boost::spirit::utree_is_less_than157         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 
operator ()boost::spirit::utree_is_less_than164         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 
operator ()boost::spirit::utree_is_less_than172         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 
operator ()boost::spirit::utree_is_less_than180         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 
operator ()boost::spirit::utree_is_less_than188         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;
utree_printboost::spirit::utree_print203         utree_print(std::ostream& out) : out(out) {}
204 
operator ()boost::spirit::utree_print205         void operator()(utree::invalid_type) const
206         {
207             out << "<invalid> ";
208         }
209 
operator ()boost::spirit::utree_print210         void operator()(utree::nil_type) const
211         {
212             out << "<nil> ";
213         }
214 
215         template <typename T>
operator ()boost::spirit::utree_print216         void operator()(T val) const
217         {
218             out << val << ' ';
219         }
220 
operator ()boost::spirit::utree_print221         void operator()(bool b) const
222         {
223             out << (b ? "true" : "false") << ' ';
224         }
225 
operator ()boost::spirit::utree_print226         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 
operator ()boost::spirit::utree_print239         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 
operator ()boost::spirit::utree_print249         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>
operator ()boost::spirit::utree_print259         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 
operator ()boost::spirit::utree_print270         void operator()(any_ptr const&) const
271         {
272             return (*this)("<pointer>");
273         }
274 
operator ()boost::spirit::utree_print275         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>
operator ()boost::spirit::logical_function291         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>
dispatchboost::spirit::logical_function300         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>
dispatchboost::spirit::logical_function307         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>
dispatchboost::spirit::logical_function314         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>
dispatchboost::spirit::logical_function321         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>
operator ()boost::spirit::logical_function328         utree operator()(A const& a) const
329         {
330             return dispatch(a, boost::is_arithmetic<A>());
331         }
332 
333         // unary
334         template <typename A>
dispatchboost::spirit::logical_function335         utree dispatch(A const& a, mpl::true_) const
336         {
337             return Base::eval(a);
338         }
339 
340         // unary
341         template <typename A>
dispatchboost::spirit::logical_function342         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>
dispatchboost::spirit::arithmetic_function354         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>
dispatchboost::spirit::arithmetic_function360         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>
operator ()boost::spirit::arithmetic_function367         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>
dispatchboost::spirit::arithmetic_function376         utree dispatch(A const&, boost::mpl::false_) const
377         {
378             return utree(); // cannot apply to non-arithmetic types
379         }
380 
381         template <typename A>
dispatchboost::spirit::arithmetic_function382         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>
operator ()boost::spirit::arithmetic_function389         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>
dispatchboost::spirit::integral_function401         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>
dispatchboost::spirit::integral_function407         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>
operator ()boost::spirit::integral_function414         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>
dispatchboost::spirit::integral_function423         utree dispatch(A const&, boost::mpl::false_) const
424         {
425             return utree(); // cannot apply to non-integral types
426         }
427 
428         template <typename A>
dispatchboost::spirit::integral_function429         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>
operator ()boost::spirit::integral_function436         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 
operator ==(utree const & a,utree const & b)474     inline bool operator==(utree const& a, utree const& b)
475     {
476         return utree::visit(a, b, utree_is_equal());
477     }
478 
operator <(utree const & a,utree const & b)479     inline bool operator<(utree const& a, utree const& b)
480     {
481         return utree::visit(a, b, utree_is_less_than());
482     }
483 
operator !=(utree const & a,utree const & b)484     inline bool operator!=(utree const& a, utree const& b)
485     {
486         return !(a == b);
487     }
488 
operator >(utree const & a,utree const & b)489     inline bool operator>(utree const& a, utree const& b)
490     {
491         return b < a;
492     }
493 
operator <=(utree const & a,utree const & b)494     inline bool operator<=(utree const& a, utree const& b)
495     {
496         return !(b < a);
497     }
498 
operator >=(utree const & a,utree const & b)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)
operator <<(std::ostream & out,utree const & x)505     inline std::ostream& operator<<(std::ostream& out, utree const& x)
506     {
507         utree::visit(x, utree_print(out));
508         return out;
509     }
510 
operator <<(std::ostream & out,utree::invalid_type const &)511     inline std::ostream& operator<<(std::ostream& out, utree::invalid_type const&)
512     {
513         return out;
514     }
515 
operator <<(std::ostream & out,utree::nil_type const &)516     inline std::ostream& operator<<(std::ostream& out, utree::nil_type const&)
517     {
518         return out;
519     }
520 #endif
521 
BOOST_SPIRIT_UTREE_CREATE_LOGICAL_FUNCTION(and_,a && b)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 #if defined(__GNUC__) && (__GNUC__ >= 7)
539 # pragma GCC diagnostic push
540 # pragma GCC diagnostic ignored "-Wbool-operation" // '~' on an expression of type bool
541 #endif
542     BOOST_SPIRIT_UTREE_CREATE_INTEGRAL_FUNCTION(invert, ~a)
543 #if defined(__GNUC__) && (__GNUC__ >= 7)
544 # pragma GCC diagnostic pop
545 #endif
546 
547     inline utree operator&&(utree const& a, utree const& b)
548     {
549           return utree::visit(a, b, logical_function_and_);
550     }
551 
operator ||(utree const & a,utree const & b)552     inline utree operator||(utree const& a, utree const& b)
553     {
554         return utree::visit(a, b, logical_function_or_);
555     }
556 
operator !(utree const & a)557     inline utree operator!(utree const& a)
558     {
559         return utree::visit(a, logical_function_not_);
560     }
561 
operator +(utree const & a,utree const & b)562     inline utree operator+(utree const& a, utree const& b)
563     {
564         utree r = utree::visit(a, b, arithmetic_function_plus);
565         if (r.which() == utree_type::invalid_type)
566         {
567             BOOST_THROW_EXCEPTION(bad_type_exception
568               ("addition performed on non-arithmetic utree types",
569                a.which(), b.which()));
570         }
571         return r;
572     }
573 
operator -(utree const & a,utree const & b)574     inline utree operator-(utree const& a, utree const& b)
575     {
576         utree r = utree::visit(a, b, arithmetic_function_minus);
577         if (r.which() == utree_type::invalid_type)
578         {
579             BOOST_THROW_EXCEPTION(bad_type_exception
580               ("subtraction performed on non-arithmetic utree types",
581                a.which(), b.which()));
582         }
583         return r;
584     }
585 
operator *(utree const & a,utree const & b)586     inline utree operator*(utree const& a, utree const& b)
587     {
588         utree r = utree::visit(a, b, arithmetic_function_times);
589         if (r.which() == utree_type::invalid_type)
590         {
591             BOOST_THROW_EXCEPTION(bad_type_exception
592               ("multiplication performed on non-arithmetic utree types",
593                a.which(), b.which()));
594         }
595         return r;
596     }
597 
operator /(utree const & a,utree const & b)598     inline utree operator/(utree const& a, utree const& b)
599     {
600         utree r = utree::visit(a, b, arithmetic_function_divides);
601         if (r.which() == utree_type::invalid_type)
602         {
603             BOOST_THROW_EXCEPTION(bad_type_exception
604               ("division performed on non-arithmetic utree types",
605                a.which(), b.which()));
606         }
607         return r;
608     }
609 
operator %(utree const & a,utree const & b)610     inline utree operator%(utree const& a, utree const& b)
611     {
612         utree r = utree::visit(a, b, integral_function_modulus);
613         if (r.which() == utree_type::invalid_type)
614         {
615             BOOST_THROW_EXCEPTION(bad_type_exception
616               ("modulos performed on non-integral utree types",
617                a.which(), b.which()));
618         }
619         return r;
620     }
621 
operator -(utree const & a)622     inline utree operator-(utree const& a)
623     {
624         utree r = utree::visit(a, arithmetic_function_negate);
625         if (r.which() == utree_type::invalid_type)
626         {
627             BOOST_THROW_EXCEPTION(bad_type_exception
628               ("negation performed on non-arithmetic utree type",
629                a.which()));
630         }
631         return r;
632     }
633 
operator &(utree const & a,utree const & b)634     inline utree operator&(utree const& a, utree const& b)
635     {
636         utree r = utree::visit(a, b, integral_function_bitand_);
637         if (r.which() == utree_type::invalid_type)
638         {
639             BOOST_THROW_EXCEPTION(bad_type_exception
640               ("bitwise and performed on non-integral utree types",
641                a.which(), b.which()));
642         }
643         return r;
644     }
645 
operator |(utree const & a,utree const & b)646     inline utree operator|(utree const& a, utree const& b)
647     {
648         utree r = utree::visit(a, b, integral_function_bitor_);
649         if (r.which() == utree_type::invalid_type)
650         {
651             BOOST_THROW_EXCEPTION(bad_type_exception
652               ("bitwise or performed on non-integral utree types",
653                a.which(), b.which()));
654         }
655         return r;
656     }
657 
operator ^(utree const & a,utree const & b)658     inline utree operator^(utree const& a, utree const& b)
659     {
660         utree r = utree::visit(a, b, integral_function_bitxor_);
661         if (r.which() == utree_type::invalid_type)
662         {
663             BOOST_THROW_EXCEPTION(bad_type_exception
664               ("bitwise xor performed on non-integral utree types",
665                a.which(), b.which()));
666         }
667         return r;
668     }
669 
operator <<(utree const & a,utree const & b)670     inline utree operator<<(utree const& a, utree const& b)
671     {
672         utree r = utree::visit(a, b, integral_function_shift_left);
673         if (r.which() == utree_type::invalid_type)
674         {
675             BOOST_THROW_EXCEPTION(bad_type_exception
676               ("left shift performed on non-integral utree types",
677                a.which(), b.which()));
678         }
679         return r;
680     }
681 
operator >>(utree const & a,utree const & b)682     inline utree operator>>(utree const& a, utree const& b)
683     {
684         utree r = utree::visit(a, b, integral_function_shift_right);
685         if (r.which() == utree_type::invalid_type)
686         {
687             BOOST_THROW_EXCEPTION(bad_type_exception
688               ("right shift performed on non-integral utree types",
689                a.which(), b.which()));
690         }
691         return r;
692     }
693 
operator ~(utree const & a)694     inline utree operator~(utree const& a)
695     {
696         utree r = utree::visit(a, integral_function_invert);
697         if (r.which() == utree_type::invalid_type)
698         {
699             BOOST_THROW_EXCEPTION(bad_type_exception
700               ("inversion performed on non-integral utree type",
701                a.which()));
702         }
703         return r;
704     }
705 }}
706 
707 #if defined(BOOST_MSVC)
708 # pragma warning(pop)
709 #endif
710 
711 #endif
712