iter_adaptor.hpp 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. /* Copyright 2003-2013 Joaquin M Lopez Munoz.
  2. * Distributed under the Boost Software License, Version 1.0.
  3. * (See accompanying file LICENSE_1_0.txt or copy at
  4. * http://www.boost.org/LICENSE_1_0.txt)
  5. *
  6. * See http://www.boost.org/libs/multi_index for library home page.
  7. */
  8. #ifndef BOOST_MULTI_INDEX_DETAIL_ITER_ADAPTOR_HPP
  9. #define BOOST_MULTI_INDEX_DETAIL_ITER_ADAPTOR_HPP
  10. #if defined(_MSC_VER)
  11. #pragma once
  12. #endif
  13. #include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
  14. #include <boost/mpl/apply.hpp>
  15. #include <boost/operators.hpp>
  16. namespace boost{
  17. namespace multi_index{
  18. namespace detail{
  19. /* Poor man's version of boost::iterator_adaptor. Used instead of the
  20. * original as compile times for the latter are significantly higher.
  21. * The interface is not replicated exactly, only to the extent necessary
  22. * for internal consumption.
  23. */
  24. /* NB. The purpose of the (non-inclass) global operators ==, < and - defined
  25. * above is to partially alleviate a problem of MSVC++ 6.0 by * which
  26. * friend-injected operators on T are not visible if T is instantiated only
  27. * in template code where T is a dependent type.
  28. */
  29. class iter_adaptor_access
  30. {
  31. public:
  32. template<class Class>
  33. static typename Class::reference dereference(const Class& x)
  34. {
  35. return x.dereference();
  36. }
  37. template<class Class>
  38. static bool equal(const Class& x,const Class& y)
  39. {
  40. return x.equal(y);
  41. }
  42. template<class Class>
  43. static void increment(Class& x)
  44. {
  45. x.increment();
  46. }
  47. template<class Class>
  48. static void decrement(Class& x)
  49. {
  50. x.decrement();
  51. }
  52. template<class Class>
  53. static void advance(Class& x,typename Class::difference_type n)
  54. {
  55. x.advance(n);
  56. }
  57. template<class Class>
  58. static typename Class::difference_type distance_to(
  59. const Class& x,const Class& y)
  60. {
  61. return x.distance_to(y);
  62. }
  63. };
  64. template<typename Category>
  65. struct iter_adaptor_selector;
  66. template<class Derived,class Base>
  67. class forward_iter_adaptor_base:
  68. public forward_iterator_helper<
  69. Derived,
  70. typename Base::value_type,
  71. typename Base::difference_type,
  72. typename Base::pointer,
  73. typename Base::reference>
  74. {
  75. public:
  76. typedef typename Base::reference reference;
  77. reference operator*()const
  78. {
  79. return iter_adaptor_access::dereference(final());
  80. }
  81. friend bool operator==(const Derived& x,const Derived& y)
  82. {
  83. return iter_adaptor_access::equal(x,y);
  84. }
  85. Derived& operator++()
  86. {
  87. iter_adaptor_access::increment(final());
  88. return final();
  89. }
  90. private:
  91. Derived& final(){return *static_cast<Derived*>(this);}
  92. const Derived& final()const{return *static_cast<const Derived*>(this);}
  93. };
  94. template<class Derived,class Base>
  95. bool operator==(
  96. const forward_iter_adaptor_base<Derived,Base>& x,
  97. const forward_iter_adaptor_base<Derived,Base>& y)
  98. {
  99. return iter_adaptor_access::equal(
  100. static_cast<const Derived&>(x),static_cast<const Derived&>(y));
  101. }
  102. template<>
  103. struct iter_adaptor_selector<std::forward_iterator_tag>
  104. {
  105. template<class Derived,class Base>
  106. struct apply
  107. {
  108. typedef forward_iter_adaptor_base<Derived,Base> type;
  109. };
  110. };
  111. template<class Derived,class Base>
  112. class bidirectional_iter_adaptor_base:
  113. public bidirectional_iterator_helper<
  114. Derived,
  115. typename Base::value_type,
  116. typename Base::difference_type,
  117. typename Base::pointer,
  118. typename Base::reference>
  119. {
  120. public:
  121. typedef typename Base::reference reference;
  122. reference operator*()const
  123. {
  124. return iter_adaptor_access::dereference(final());
  125. }
  126. friend bool operator==(const Derived& x,const Derived& y)
  127. {
  128. return iter_adaptor_access::equal(x,y);
  129. }
  130. Derived& operator++()
  131. {
  132. iter_adaptor_access::increment(final());
  133. return final();
  134. }
  135. Derived& operator--()
  136. {
  137. iter_adaptor_access::decrement(final());
  138. return final();
  139. }
  140. private:
  141. Derived& final(){return *static_cast<Derived*>(this);}
  142. const Derived& final()const{return *static_cast<const Derived*>(this);}
  143. };
  144. template<class Derived,class Base>
  145. bool operator==(
  146. const bidirectional_iter_adaptor_base<Derived,Base>& x,
  147. const bidirectional_iter_adaptor_base<Derived,Base>& y)
  148. {
  149. return iter_adaptor_access::equal(
  150. static_cast<const Derived&>(x),static_cast<const Derived&>(y));
  151. }
  152. template<>
  153. struct iter_adaptor_selector<std::bidirectional_iterator_tag>
  154. {
  155. template<class Derived,class Base>
  156. struct apply
  157. {
  158. typedef bidirectional_iter_adaptor_base<Derived,Base> type;
  159. };
  160. };
  161. template<class Derived,class Base>
  162. class random_access_iter_adaptor_base:
  163. public random_access_iterator_helper<
  164. Derived,
  165. typename Base::value_type,
  166. typename Base::difference_type,
  167. typename Base::pointer,
  168. typename Base::reference>
  169. {
  170. public:
  171. typedef typename Base::reference reference;
  172. typedef typename Base::difference_type difference_type;
  173. reference operator*()const
  174. {
  175. return iter_adaptor_access::dereference(final());
  176. }
  177. friend bool operator==(const Derived& x,const Derived& y)
  178. {
  179. return iter_adaptor_access::equal(x,y);
  180. }
  181. friend bool operator<(const Derived& x,const Derived& y)
  182. {
  183. return iter_adaptor_access::distance_to(x,y)>0;
  184. }
  185. Derived& operator++()
  186. {
  187. iter_adaptor_access::increment(final());
  188. return final();
  189. }
  190. Derived& operator--()
  191. {
  192. iter_adaptor_access::decrement(final());
  193. return final();
  194. }
  195. Derived& operator+=(difference_type n)
  196. {
  197. iter_adaptor_access::advance(final(),n);
  198. return final();
  199. }
  200. Derived& operator-=(difference_type n)
  201. {
  202. iter_adaptor_access::advance(final(),-n);
  203. return final();
  204. }
  205. friend difference_type operator-(const Derived& x,const Derived& y)
  206. {
  207. return iter_adaptor_access::distance_to(y,x);
  208. }
  209. private:
  210. Derived& final(){return *static_cast<Derived*>(this);}
  211. const Derived& final()const{return *static_cast<const Derived*>(this);}
  212. };
  213. template<class Derived,class Base>
  214. bool operator==(
  215. const random_access_iter_adaptor_base<Derived,Base>& x,
  216. const random_access_iter_adaptor_base<Derived,Base>& y)
  217. {
  218. return iter_adaptor_access::equal(
  219. static_cast<const Derived&>(x),static_cast<const Derived&>(y));
  220. }
  221. template<class Derived,class Base>
  222. bool operator<(
  223. const random_access_iter_adaptor_base<Derived,Base>& x,
  224. const random_access_iter_adaptor_base<Derived,Base>& y)
  225. {
  226. return iter_adaptor_access::distance_to(
  227. static_cast<const Derived&>(x),static_cast<const Derived&>(y))>0;
  228. }
  229. template<class Derived,class Base>
  230. typename random_access_iter_adaptor_base<Derived,Base>::difference_type
  231. operator-(
  232. const random_access_iter_adaptor_base<Derived,Base>& x,
  233. const random_access_iter_adaptor_base<Derived,Base>& y)
  234. {
  235. return iter_adaptor_access::distance_to(
  236. static_cast<const Derived&>(y),static_cast<const Derived&>(x));
  237. }
  238. template<>
  239. struct iter_adaptor_selector<std::random_access_iterator_tag>
  240. {
  241. template<class Derived,class Base>
  242. struct apply
  243. {
  244. typedef random_access_iter_adaptor_base<Derived,Base> type;
  245. };
  246. };
  247. template<class Derived,class Base>
  248. struct iter_adaptor_base
  249. {
  250. typedef iter_adaptor_selector<
  251. typename Base::iterator_category> selector;
  252. typedef typename mpl::apply2<
  253. selector,Derived,Base>::type type;
  254. };
  255. template<class Derived,class Base>
  256. class iter_adaptor:public iter_adaptor_base<Derived,Base>::type
  257. {
  258. protected:
  259. iter_adaptor(){}
  260. explicit iter_adaptor(const Base& b_):b(b_){}
  261. const Base& base_reference()const{return b;}
  262. Base& base_reference(){return b;}
  263. private:
  264. Base b;
  265. };
  266. } /* namespace multi_index::detail */
  267. } /* namespace multi_index */
  268. } /* namespace boost */
  269. #endif