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