operators.hpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544
  1. // Boost.TypeErasure library
  2. //
  3. // Copyright 2011 Steven Watanabe
  4. //
  5. // Distributed under the Boost Software License Version 1.0. (See
  6. // accompanying file LICENSE_1_0.txt or copy at
  7. // http://www.boost.org/LICENSE_1_0.txt)
  8. //
  9. // $Id$
  10. #ifndef BOOST_TYPE_ERASURE_OPERATORS_HPP_INCLUDED
  11. #define BOOST_TYPE_ERASURE_OPERATORS_HPP_INCLUDED
  12. #include <iosfwd>
  13. #include <boost/utility/enable_if.hpp>
  14. #include <boost/type_erasure/detail/const.hpp>
  15. #include <boost/type_erasure/call.hpp>
  16. #include <boost/type_erasure/concept_interface.hpp>
  17. #include <boost/type_erasure/placeholder.hpp>
  18. #include <boost/type_erasure/concept_of.hpp>
  19. #include <boost/type_erasure/derived.hpp>
  20. #include <boost/type_erasure/rebind_any.hpp>
  21. #include <boost/type_erasure/param.hpp>
  22. #include <boost/type_erasure/check_match.hpp>
  23. #include <boost/type_erasure/relaxed.hpp>
  24. #include <boost/type_erasure/typeid_of.hpp>
  25. namespace boost {
  26. namespace type_erasure {
  27. /** INTERNAL ONLY */
  28. #define BOOST_TYPE_ERASURE_UNARY_INPLACE_OPERATOR(name, op) \
  29. template<class T = _self> \
  30. struct name \
  31. { \
  32. static void apply(T& arg) { op arg; } \
  33. }; \
  34. \
  35. template<class T, class Base> \
  36. struct concept_interface<name<T>, Base, T, \
  37. typename ::boost::enable_if< \
  38. detail::should_be_non_const<T, Base> \
  39. >::type \
  40. > : Base \
  41. { \
  42. typedef typename ::boost::type_erasure::derived<Base>::type _derived; \
  43. _derived& operator op() \
  44. { \
  45. ::boost::type_erasure::call(name<T>(), *this); \
  46. return static_cast<_derived&>(*this); \
  47. } \
  48. typename ::boost::type_erasure::rebind_any<Base, T>::type operator op(int) \
  49. { \
  50. typename ::boost::type_erasure::rebind_any<Base, T>::type result( \
  51. static_cast<_derived&>(*this)); \
  52. ::boost::type_erasure::call(name<T>(), *this); \
  53. return result; \
  54. } \
  55. }; \
  56. \
  57. template<class T, class Base> \
  58. struct concept_interface<name<T>, Base, T, \
  59. typename ::boost::enable_if< \
  60. detail::should_be_const<T, Base> \
  61. >::type \
  62. > : Base \
  63. { \
  64. typedef typename ::boost::type_erasure::derived<Base>::type _derived; \
  65. const _derived& operator op() const \
  66. { \
  67. ::boost::type_erasure::call(name<T>(), *this); \
  68. return static_cast<const _derived&>(*this); \
  69. } \
  70. typename ::boost::type_erasure::rebind_any<Base, T>::type operator op(int) const \
  71. { \
  72. typename ::boost::type_erasure::rebind_any<Base, T>::type result( \
  73. static_cast<const _derived&>(*this)); \
  74. ::boost::type_erasure::call(name<T>(), *this); \
  75. return result; \
  76. } \
  77. };
  78. /**
  79. * The @ref incrementable concept allow pre and
  80. * post increment on an @ref any. The contained
  81. * type must provide a pre-increment operator.
  82. */
  83. BOOST_TYPE_ERASURE_UNARY_INPLACE_OPERATOR(incrementable, ++)
  84. /**
  85. * The @ref decrementable concept allow pre and
  86. * post decrement on an @ref any. The contained
  87. * type must provide a pre-decrement operator.
  88. */
  89. BOOST_TYPE_ERASURE_UNARY_INPLACE_OPERATOR(decrementable, --)
  90. #undef BOOST_TYPE_ERASURE_UNARY_INPLACE_OPERATOR
  91. /** INTERNAL ONLY */
  92. #define BOOST_TYPE_ERASURE_UNARY_OPERATOR(name, op) \
  93. template<class T = _self, class R = T> \
  94. struct name \
  95. { \
  96. static R apply(const T& arg) { return op arg; } \
  97. }; \
  98. \
  99. template<class T, class R, class Base> \
  100. struct concept_interface<name<T, R>, Base, T> : Base \
  101. { \
  102. typename ::boost::type_erasure::rebind_any<Base, R>::type operator op() const \
  103. { \
  104. return ::boost::type_erasure::call(name<T, R>(), *this); \
  105. } \
  106. };
  107. /**
  108. * The @ref complementable concept allow use of the bitwise
  109. * complement operator on an @ref any.
  110. */
  111. BOOST_TYPE_ERASURE_UNARY_OPERATOR(complementable, ~)
  112. /**
  113. * The @ref negatable concept allow use of the unary
  114. * minus operator on an @ref any.
  115. */
  116. BOOST_TYPE_ERASURE_UNARY_OPERATOR(negatable, -)
  117. #undef BOOST_TYPE_ERASURE_UNARY_OPERATOR
  118. template<class R, class T = _self>
  119. struct dereferenceable
  120. {
  121. static R apply(const T& arg) { return *arg; }
  122. };
  123. /// \cond show_operators
  124. template<class R, class T, class Base>
  125. struct concept_interface<dereferenceable<R, T>, Base, T> : Base
  126. {
  127. typename ::boost::type_erasure::rebind_any<Base, R>::type operator*() const
  128. {
  129. return ::boost::type_erasure::call(dereferenceable<R, T>(), *this);
  130. }
  131. };
  132. /// \endcond
  133. /** INTERNAL ONLY */
  134. #define BOOST_TYPE_ERASURE_BINARY_OPERATOR(name, op) \
  135. template<class T = _self, class U = T, class R = T> \
  136. struct name \
  137. { \
  138. static R apply(const T& lhs, const U& rhs) { return lhs op rhs; } \
  139. }; \
  140. \
  141. template<class T, class U, class R, class Base> \
  142. struct concept_interface<name<T, U, R>, Base, T> : Base \
  143. { \
  144. friend typename rebind_any<Base, R>::type \
  145. operator op(const typename derived<Base>::type& lhs, \
  146. typename as_param<Base, const U&>::type rhs) \
  147. { \
  148. return ::boost::type_erasure::call(name<T, U, R>(), lhs, rhs); \
  149. } \
  150. }; \
  151. \
  152. template<class T, class U, class R, class Base> \
  153. struct concept_interface< \
  154. name<T, U, R>, \
  155. Base, \
  156. U, \
  157. typename ::boost::disable_if< \
  158. ::boost::type_erasure::is_placeholder<T> >::type \
  159. > : Base \
  160. { \
  161. friend typename rebind_any<Base, R>::type \
  162. operator op(const T& lhs, \
  163. const typename derived<Base>::type& rhs) \
  164. { \
  165. return ::boost::type_erasure::call(name<T, U, R>(), lhs, rhs); \
  166. } \
  167. };
  168. BOOST_TYPE_ERASURE_BINARY_OPERATOR(addable, +)
  169. BOOST_TYPE_ERASURE_BINARY_OPERATOR(subtractable, -)
  170. BOOST_TYPE_ERASURE_BINARY_OPERATOR(multipliable, *)
  171. BOOST_TYPE_ERASURE_BINARY_OPERATOR(dividable, /)
  172. BOOST_TYPE_ERASURE_BINARY_OPERATOR(modable, %)
  173. BOOST_TYPE_ERASURE_BINARY_OPERATOR(left_shiftable, <<)
  174. BOOST_TYPE_ERASURE_BINARY_OPERATOR(right_shiftable, >>)
  175. BOOST_TYPE_ERASURE_BINARY_OPERATOR(bitandable, &)
  176. BOOST_TYPE_ERASURE_BINARY_OPERATOR(bitorable, |)
  177. BOOST_TYPE_ERASURE_BINARY_OPERATOR(bitxorable, ^)
  178. #undef BOOST_TYPE_ERASURE_BINARY_OPERATOR
  179. /** INTERNAL ONLY */
  180. #define BOOST_TYPE_ERASURE_ASSIGNMENT_OPERATOR(name, op) \
  181. template<class T = _self, class U = T> \
  182. struct name \
  183. { \
  184. static void apply(T& lhs, const U& rhs) { lhs op rhs; } \
  185. }; \
  186. \
  187. template<class T, class U, class Base> \
  188. struct concept_interface<name<T, U>, Base, T, \
  189. typename ::boost::disable_if< \
  190. ::boost::is_same< \
  191. typename ::boost::type_erasure::placeholder_of<Base>::type, \
  192. const T& \
  193. > \
  194. >::type \
  195. > : Base \
  196. { \
  197. friend typename detail::non_const_this_param<Base>::type& \
  198. operator op(typename detail::non_const_this_param<Base>::type& lhs, \
  199. typename as_param<Base, const U&>::type rhs) \
  200. { \
  201. ::boost::type_erasure::call(name<T, U>(),lhs, rhs); \
  202. return lhs; \
  203. } \
  204. }; \
  205. \
  206. template<class T, class U, class Base> \
  207. struct concept_interface< \
  208. name<T, U>, \
  209. Base, \
  210. U, \
  211. typename ::boost::disable_if< \
  212. ::boost::type_erasure::is_placeholder<T> >::type \
  213. > : Base \
  214. { \
  215. friend T& \
  216. operator op(T& lhs, const typename derived<Base>::type& rhs) \
  217. { \
  218. ::boost::type_erasure::call(name<T, U>(),lhs, rhs); \
  219. return lhs; \
  220. } \
  221. };
  222. BOOST_TYPE_ERASURE_ASSIGNMENT_OPERATOR(add_assignable, +=)
  223. BOOST_TYPE_ERASURE_ASSIGNMENT_OPERATOR(subtract_assignable, -=)
  224. BOOST_TYPE_ERASURE_ASSIGNMENT_OPERATOR(multiply_assignable, *=)
  225. BOOST_TYPE_ERASURE_ASSIGNMENT_OPERATOR(divide_assignable, /=)
  226. BOOST_TYPE_ERASURE_ASSIGNMENT_OPERATOR(mod_assignable, %=)
  227. BOOST_TYPE_ERASURE_ASSIGNMENT_OPERATOR(left_shift_assignable, <<=)
  228. BOOST_TYPE_ERASURE_ASSIGNMENT_OPERATOR(right_shift_assignable, >>=)
  229. BOOST_TYPE_ERASURE_ASSIGNMENT_OPERATOR(bitand_assignable, &=)
  230. BOOST_TYPE_ERASURE_ASSIGNMENT_OPERATOR(bitor_assignable, |=)
  231. BOOST_TYPE_ERASURE_ASSIGNMENT_OPERATOR(bitxor_assignable, ^=)
  232. #undef BOOST_TYPE_ERASURE_ASSIGNMENT_OPERATOR
  233. template<class T = _self, class U = T>
  234. struct equality_comparable
  235. {
  236. static bool apply(const T& lhs, const U& rhs) { return lhs == rhs; }
  237. };
  238. /// \cond show_operators
  239. template<class T, class U, class Base>
  240. struct concept_interface<equality_comparable<T, U>, Base, T> : Base
  241. {
  242. friend bool operator==(const typename derived<Base>::type& lhs,
  243. typename as_param<Base, const U&>::type rhs)
  244. {
  245. if(::boost::type_erasure::check_match(equality_comparable<T, U>(), lhs, rhs)) {
  246. return ::boost::type_erasure::unchecked_call(equality_comparable<T, U>(), lhs, rhs);
  247. } else {
  248. return false;
  249. }
  250. }
  251. friend bool operator!=(const typename derived<Base>::type& lhs,
  252. typename as_param<Base, const U&>::type rhs)
  253. {
  254. return !(lhs == rhs);
  255. }
  256. };
  257. template<class T, class U, class Base>
  258. struct concept_interface<
  259. equality_comparable<T, U>,
  260. Base,
  261. U,
  262. typename ::boost::disable_if< ::boost::type_erasure::is_placeholder<T> >::type
  263. > : Base
  264. {
  265. friend bool operator==(const T& lhs, const typename derived<Base>::type& rhs)
  266. {
  267. return ::boost::type_erasure::call(equality_comparable<T, U>(), lhs, rhs);
  268. }
  269. friend bool operator!=(const T& lhs, const typename derived<Base>::type& rhs)
  270. {
  271. return !(lhs == rhs);
  272. }
  273. };
  274. /// \endcond
  275. template<class T = _self, class U = T>
  276. struct less_than_comparable
  277. {
  278. static bool apply(const T& lhs, const U& rhs) { return lhs < rhs; }
  279. };
  280. namespace detail {
  281. template<class F, class T, class U>
  282. bool less_impl(const F& f, const T& lhs, const U& rhs, ::boost::mpl::true_)
  283. {
  284. if(::boost::type_erasure::check_match(f, lhs, rhs)) {
  285. return ::boost::type_erasure::unchecked_call(f, lhs, rhs);
  286. } else {
  287. return ::boost::type_erasure::typeid_of(
  288. static_cast<const typename derived<T>::type&>(lhs)
  289. ).before(
  290. ::boost::type_erasure::typeid_of(
  291. static_cast<const typename derived<U>::type&>(rhs)
  292. )
  293. ) != false;
  294. }
  295. }
  296. template<class F, class T, class U>
  297. bool less_impl(const F& f, const T& lhs, const U& rhs, ::boost::mpl::false_)
  298. {
  299. return ::boost::type_erasure::call(f, lhs, rhs);
  300. }
  301. }
  302. /// \cond show_operators
  303. template<class T, class Base>
  304. struct concept_interface<less_than_comparable<T, T>, Base, T> : Base
  305. {
  306. friend bool operator<(const typename derived<Base>::type& lhs,
  307. typename as_param<Base, const T&>::type rhs)
  308. {
  309. return ::boost::type_erasure::detail::less_impl(
  310. less_than_comparable<T, T>(),
  311. lhs, rhs,
  312. ::boost::type_erasure::is_relaxed<
  313. typename ::boost::type_erasure::concept_of<Base>::type>());
  314. }
  315. friend bool operator>=(const typename derived<Base>::type& lhs,
  316. typename as_param<Base, const T&>::type rhs)
  317. {
  318. return !(lhs < rhs);
  319. }
  320. friend bool operator>(typename as_param<Base, const T&>::type lhs,
  321. const typename derived<Base>::type& rhs)
  322. {
  323. return rhs < lhs;
  324. }
  325. friend bool operator<=(typename as_param<Base, const T&>::type lhs,
  326. const typename derived<Base>::type& rhs)
  327. {
  328. return !(rhs < lhs);
  329. }
  330. };
  331. template<class T, class U, class Base>
  332. struct concept_interface<less_than_comparable<T, U>, Base, T> : Base
  333. {
  334. friend bool operator<(const typename derived<Base>::type& lhs,
  335. typename as_param<Base, const U&>::type rhs)
  336. {
  337. return ::boost::type_erasure::call(less_than_comparable<T, U>(), lhs, rhs);
  338. }
  339. friend bool operator>=(const typename derived<Base>::type& lhs,
  340. typename as_param<Base, const U&>::type rhs)
  341. {
  342. return !(lhs < rhs);
  343. }
  344. friend bool operator>(typename as_param<Base, const U&>::type lhs,
  345. const typename derived<Base>::type& rhs)
  346. {
  347. return rhs < lhs;
  348. }
  349. friend bool operator<=(typename as_param<Base, const U&>::type lhs,
  350. const typename derived<Base>::type& rhs)
  351. {
  352. return !(rhs < lhs);
  353. }
  354. };
  355. template<class T, class U, class Base>
  356. struct concept_interface<
  357. less_than_comparable<T, U>,
  358. Base,
  359. U,
  360. typename ::boost::disable_if< ::boost::type_erasure::is_placeholder<T> >::type
  361. > : Base
  362. {
  363. friend bool operator<(const T& lhs, const typename derived<Base>::type& rhs)
  364. {
  365. return ::boost::type_erasure::call(less_than_comparable<T, U>(), lhs, rhs);
  366. }
  367. friend bool operator>=(const T& lhs, const typename derived<Base>::type& rhs)
  368. {
  369. return !(lhs < rhs);
  370. }
  371. friend bool operator>(const typename derived<Base>::type& lhs, const T& rhs)
  372. {
  373. return rhs < lhs;
  374. }
  375. friend bool operator<=(const typename derived<Base>::type& lhs, const T& rhs)
  376. {
  377. return !(rhs < lhs);
  378. }
  379. };
  380. /// \endcond
  381. template<class R, class T = _self, class N = std::ptrdiff_t>
  382. struct subscriptable
  383. {
  384. static R apply(T& arg, const N& index) { return arg[index]; }
  385. };
  386. /// \cond show_operators
  387. template<class R, class T, class N, class Base>
  388. struct concept_interface<subscriptable<R, T, N>, Base, typename ::boost::remove_const<T>::type,
  389. typename ::boost::enable_if<
  390. ::boost::type_erasure::detail::should_be_non_const<T, Base>
  391. >::type
  392. > : Base
  393. {
  394. typename ::boost::type_erasure::rebind_any<Base, R>::type operator[](
  395. typename ::boost::type_erasure::as_param<Base, const N&>::type index)
  396. {
  397. return ::boost::type_erasure::call(subscriptable<R, T, N>(), *this, index);
  398. }
  399. };
  400. template<class R, class T, class N, class Base>
  401. struct concept_interface<subscriptable<R, T, N>, Base, typename ::boost::remove_const<T>::type,
  402. typename ::boost::enable_if<
  403. ::boost::type_erasure::detail::should_be_const<T, Base>
  404. >::type
  405. > : Base
  406. {
  407. typename ::boost::type_erasure::rebind_any<Base, R>::type operator[](
  408. typename ::boost::type_erasure::as_param<Base, const N&>::type index) const
  409. {
  410. return ::boost::type_erasure::call(subscriptable<R, const T, N>(), *this, index);
  411. }
  412. };
  413. /// \endcond
  414. /**
  415. * The @ref ostreamable concept allows an @ref any to be
  416. * written to a @c std::ostream.
  417. */
  418. template<class Os = std::ostream, class T = _self>
  419. struct ostreamable
  420. {
  421. static void apply(Os& out, const T& arg) { out << arg; }
  422. };
  423. /// \cond show_operators
  424. template<class Base, class Os, class T>
  425. struct concept_interface<ostreamable<Os, T>, Base, Os> : Base
  426. {
  427. friend typename detail::non_const_this_param<Base>::type&
  428. operator<<(typename detail::non_const_this_param<Base>::type& lhs,
  429. typename ::boost::type_erasure::as_param<Base, const T&>::type rhs)
  430. {
  431. ::boost::type_erasure::call(ostreamable<Os, T>(), lhs, rhs);
  432. return lhs;
  433. }
  434. };
  435. template<class Base, class Os, class T>
  436. struct concept_interface<
  437. ostreamable<Os, T>,
  438. Base,
  439. T,
  440. typename ::boost::disable_if< ::boost::type_erasure::is_placeholder<Os> >::type
  441. > : Base
  442. {
  443. friend Os&
  444. operator<<(Os& lhs,
  445. const typename ::boost::type_erasure::derived<Base>::type& rhs)
  446. {
  447. ::boost::type_erasure::call(ostreamable<Os, T>(), lhs, rhs);
  448. return lhs;
  449. }
  450. };
  451. /// \endcond
  452. /**
  453. * The @ref istreamable concept allows an @ref any to be
  454. * read from a @c std::istream.
  455. */
  456. template<class Is = std::istream, class T = _self>
  457. struct istreamable
  458. {
  459. static void apply(Is& out, T& arg) { out >> arg; }
  460. };
  461. /// \cond show_operators
  462. template<class Base, class Is, class T>
  463. struct concept_interface<istreamable<Is, T>, Base, Is> : Base
  464. {
  465. friend typename detail::non_const_this_param<Base>::type&
  466. operator>>(typename detail::non_const_this_param<Base>::type& lhs,
  467. typename ::boost::type_erasure::as_param<Base, T&>::type rhs)
  468. {
  469. ::boost::type_erasure::call(istreamable<Is, T>(), lhs, rhs);
  470. return lhs;
  471. }
  472. };
  473. template<class Base, class Is, class T>
  474. struct concept_interface<
  475. istreamable<Is, T>,
  476. Base,
  477. T,
  478. typename ::boost::disable_if< ::boost::type_erasure::is_placeholder<Is> >::type
  479. > : Base
  480. {
  481. friend Is&
  482. operator>>(Is& lhs,
  483. typename ::boost::type_erasure::derived<Base>::type& rhs)
  484. {
  485. ::boost::type_erasure::call(istreamable<Is, T>(), lhs, rhs);
  486. return lhs;
  487. }
  488. };
  489. /// \endcond
  490. }
  491. }
  492. #endif