operators.hpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719
  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. BOOST_UNREACHABLE_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. BOOST_UNREACHABLE_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. BOOST_UNREACHABLE_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. BOOST_UNREACHABLE_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. BOOST_SPIRIT_UTREE_CREATE_INTEGRAL_FUNCTION(UNARY, invert, ~a)
  459. // avoid `'~' on an expression of type bool` warning
  460. template <> inline utree function_impl_invert::eval<bool>(bool const& a)
  461. {
  462. return utree(!a);
  463. }
  464. #undef BOOST_SPIRIT_UTREE_CREATE_FUNCTION_BINARY
  465. #undef BOOST_SPIRIT_UTREE_CREATE_FUNCTION_UNARY
  466. #undef BOOST_SPIRIT_UTREE_CREATE_FUNCTION
  467. #undef BOOST_SPIRIT_UTREE_CREATE_LOGICAL_FUNCTION
  468. #undef BOOST_SPIRIT_UTREE_CREATE_INTEGRAL_FUNCTION
  469. #undef BOOST_SPIRIT_UTREE_CREATE_ARITHMETIC_FUNCTION
  470. inline utree operator&&(utree const& a, utree const& b)
  471. {
  472. return utree::visit(a, b, logical_function_and_);
  473. }
  474. inline utree operator||(utree const& a, utree const& b)
  475. {
  476. return utree::visit(a, b, logical_function_or_);
  477. }
  478. inline utree operator!(utree const& a)
  479. {
  480. return utree::visit(a, logical_function_not_);
  481. }
  482. inline utree operator+(utree const& a, utree const& b)
  483. {
  484. utree r = utree::visit(a, b, arithmetic_function_plus);
  485. if (r.which() == utree_type::invalid_type)
  486. {
  487. BOOST_THROW_EXCEPTION(bad_type_exception
  488. ("addition performed on non-arithmetic utree types",
  489. a.which(), b.which()));
  490. }
  491. return r;
  492. }
  493. inline utree operator-(utree const& a, utree const& b)
  494. {
  495. utree r = utree::visit(a, b, arithmetic_function_minus);
  496. if (r.which() == utree_type::invalid_type)
  497. {
  498. BOOST_THROW_EXCEPTION(bad_type_exception
  499. ("subtraction performed on non-arithmetic utree types",
  500. a.which(), b.which()));
  501. }
  502. return r;
  503. }
  504. inline utree operator*(utree const& a, utree const& b)
  505. {
  506. utree r = utree::visit(a, b, arithmetic_function_times);
  507. if (r.which() == utree_type::invalid_type)
  508. {
  509. BOOST_THROW_EXCEPTION(bad_type_exception
  510. ("multiplication performed on non-arithmetic utree types",
  511. a.which(), b.which()));
  512. }
  513. return r;
  514. }
  515. inline utree operator/(utree const& a, utree const& b)
  516. {
  517. utree r = utree::visit(a, b, arithmetic_function_divides);
  518. if (r.which() == utree_type::invalid_type)
  519. {
  520. BOOST_THROW_EXCEPTION(bad_type_exception
  521. ("division performed on non-arithmetic utree types",
  522. a.which(), b.which()));
  523. }
  524. return r;
  525. }
  526. inline utree operator%(utree const& a, utree const& b)
  527. {
  528. utree r = utree::visit(a, b, integral_function_modulus);
  529. if (r.which() == utree_type::invalid_type)
  530. {
  531. BOOST_THROW_EXCEPTION(bad_type_exception
  532. ("modulos performed on non-integral utree types",
  533. a.which(), b.which()));
  534. }
  535. return r;
  536. }
  537. inline utree operator-(utree const& a)
  538. {
  539. utree r = utree::visit(a, arithmetic_function_negate);
  540. if (r.which() == utree_type::invalid_type)
  541. {
  542. BOOST_THROW_EXCEPTION(bad_type_exception
  543. ("negation performed on non-arithmetic utree type",
  544. a.which()));
  545. }
  546. return r;
  547. }
  548. inline utree operator&(utree const& a, utree const& b)
  549. {
  550. utree r = utree::visit(a, b, integral_function_bitand_);
  551. if (r.which() == utree_type::invalid_type)
  552. {
  553. BOOST_THROW_EXCEPTION(bad_type_exception
  554. ("bitwise and performed on non-integral utree types",
  555. a.which(), b.which()));
  556. }
  557. return r;
  558. }
  559. inline utree operator|(utree const& a, utree const& b)
  560. {
  561. utree r = utree::visit(a, b, integral_function_bitor_);
  562. if (r.which() == utree_type::invalid_type)
  563. {
  564. BOOST_THROW_EXCEPTION(bad_type_exception
  565. ("bitwise or performed on non-integral utree types",
  566. a.which(), b.which()));
  567. }
  568. return r;
  569. }
  570. inline utree operator^(utree const& a, utree const& b)
  571. {
  572. utree r = utree::visit(a, b, integral_function_bitxor_);
  573. if (r.which() == utree_type::invalid_type)
  574. {
  575. BOOST_THROW_EXCEPTION(bad_type_exception
  576. ("bitwise xor performed on non-integral utree types",
  577. a.which(), b.which()));
  578. }
  579. return r;
  580. }
  581. inline utree operator<<(utree const& a, utree const& b)
  582. {
  583. utree r = utree::visit(a, b, integral_function_shift_left);
  584. if (r.which() == utree_type::invalid_type)
  585. {
  586. BOOST_THROW_EXCEPTION(bad_type_exception
  587. ("left shift performed on non-integral utree types",
  588. a.which(), b.which()));
  589. }
  590. return r;
  591. }
  592. inline utree operator>>(utree const& a, utree const& b)
  593. {
  594. utree r = utree::visit(a, b, integral_function_shift_right);
  595. if (r.which() == utree_type::invalid_type)
  596. {
  597. BOOST_THROW_EXCEPTION(bad_type_exception
  598. ("right shift performed on non-integral utree types",
  599. a.which(), b.which()));
  600. }
  601. return r;
  602. }
  603. inline utree operator~(utree const& a)
  604. {
  605. utree r = utree::visit(a, integral_function_invert);
  606. if (r.which() == utree_type::invalid_type)
  607. {
  608. BOOST_THROW_EXCEPTION(bad_type_exception
  609. ("inversion performed on non-integral utree type",
  610. a.which()));
  611. }
  612. return r;
  613. }
  614. }}
  615. #if defined(BOOST_MSVC)
  616. # pragma warning(pop)
  617. #endif
  618. #endif