operators.hpp 22 KB

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