xiterator_base.hpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422
  1. /***************************************************************************
  2. * Copyright (c) Johan Mabille, Sylvain Corlay and Wolf Vollprecht *
  3. * Copyright (c) QuantStack *
  4. * *
  5. * Distributed under the terms of the BSD 3-Clause License. *
  6. * *
  7. * The full license is in the file LICENSE, distributed with this software. *
  8. ****************************************************************************/
  9. #ifndef XTL_XITERATOR_BASE_HPP
  10. #define XTL_XITERATOR_BASE_HPP
  11. #include <cstddef>
  12. #include <iterator>
  13. namespace xtl
  14. {
  15. /**************************************
  16. * class xbidirectional_iterator_base *
  17. **************************************/
  18. template <class I, class T, class D = std::ptrdiff_t, class P = T*, class R = T&>
  19. class xbidirectional_iterator_base
  20. {
  21. public:
  22. using derived_type = I;
  23. using value_type = T;
  24. using reference = R;
  25. using pointer = P;
  26. using difference_type = D;
  27. using iterator_category = std::bidirectional_iterator_tag;
  28. inline friend derived_type operator++(derived_type& d, int)
  29. {
  30. derived_type tmp(d);
  31. ++d;
  32. return tmp;
  33. }
  34. inline friend derived_type operator--(derived_type& d, int)
  35. {
  36. derived_type tmp(d);
  37. --d;
  38. return tmp;
  39. }
  40. inline friend bool operator!=(const derived_type& lhs, const derived_type& rhs)
  41. {
  42. return !(lhs == rhs);
  43. }
  44. };
  45. template <class T>
  46. using xbidirectional_iterator_base2 = xbidirectional_iterator_base<typename T::iterator_type,
  47. typename T::value_type,
  48. typename T::difference_type,
  49. typename T::pointer,
  50. typename T::reference>;
  51. template <class I, class T>
  52. using xbidirectional_iterator_base3 = xbidirectional_iterator_base<I,
  53. typename T::value_type,
  54. typename T::difference_type,
  55. typename T::pointer,
  56. typename T::reference>;
  57. /********************************
  58. * xrandom_access_iterator_base *
  59. ********************************/
  60. template <class I, class T, class D = std::ptrdiff_t, class P = T*, class R = T&>
  61. class xrandom_access_iterator_base : public xbidirectional_iterator_base<I, T, D, P, R>
  62. {
  63. public:
  64. using derived_type = I;
  65. using value_type = T;
  66. using reference = R;
  67. using pointer = P;
  68. using difference_type = D;
  69. using iterator_category = std::random_access_iterator_tag;
  70. inline reference operator[](difference_type n) const
  71. {
  72. return *(*static_cast<const derived_type*>(this) + n);
  73. }
  74. inline friend derived_type operator+(const derived_type& it, difference_type n)
  75. {
  76. derived_type tmp(it);
  77. return tmp += n;
  78. }
  79. inline friend derived_type operator+(difference_type n, const derived_type& it)
  80. {
  81. derived_type tmp(it);
  82. return tmp += n;
  83. }
  84. inline friend derived_type operator-(const derived_type& it, difference_type n)
  85. {
  86. derived_type tmp(it);
  87. return tmp -= n;
  88. }
  89. inline friend bool operator<=(const derived_type& lhs, const derived_type& rhs)
  90. {
  91. return !(rhs < lhs);
  92. }
  93. inline friend bool operator>=(const derived_type& lhs, const derived_type& rhs)
  94. {
  95. return !(lhs < rhs);
  96. }
  97. inline friend bool operator>(const derived_type& lhs, const derived_type& rhs)
  98. {
  99. return rhs < lhs;
  100. }
  101. };
  102. template <class T>
  103. using xrandom_access_iterator_base2 = xrandom_access_iterator_base<typename T::iterator_type,
  104. typename T::value_type,
  105. typename T::difference_type,
  106. typename T::pointer,
  107. typename T::reference>;
  108. template <class I, class T>
  109. using xrandom_access_iterator_base3 = xrandom_access_iterator_base<I,
  110. typename T::value_type,
  111. typename T::difference_type,
  112. typename T::pointer,
  113. typename T::reference>;
  114. /*******************************
  115. * xrandom_access_iterator_ext *
  116. *******************************/
  117. // Extension for random access iterators defining operator[] and operator+ overloads
  118. // accepting size_t arguments.
  119. template <class I, class R>
  120. class xrandom_access_iterator_ext
  121. {
  122. public:
  123. using derived_type = I;
  124. using reference = R;
  125. using size_type = std::size_t;
  126. inline reference operator[](size_type n) const
  127. {
  128. return *(*static_cast<const derived_type*>(this) + n);
  129. }
  130. inline friend derived_type operator+(const derived_type& it, size_type n)
  131. {
  132. derived_type tmp(it);
  133. return tmp += n;
  134. }
  135. inline friend derived_type operator+(size_type n, const derived_type& it)
  136. {
  137. derived_type tmp(it);
  138. return tmp += n;
  139. }
  140. inline friend derived_type operator-(const derived_type& it, size_type n)
  141. {
  142. derived_type tmp(it);
  143. return tmp -= n;
  144. }
  145. };
  146. /*****************
  147. * xkey_iterator *
  148. *****************/
  149. template <class M>
  150. class xkey_iterator : public xbidirectional_iterator_base<xkey_iterator<M>, const typename M::key_type>
  151. {
  152. public:
  153. using self_type = xkey_iterator;
  154. using base_type = xbidirectional_iterator_base<self_type, const typename M::key_type>;
  155. using value_type = typename base_type::value_type;
  156. using reference = typename base_type::reference;
  157. using pointer = typename base_type::pointer;
  158. using difference_type = typename base_type::difference_type;
  159. using iterator_category = typename base_type::iterator_category;
  160. using subiterator = typename M::const_iterator;
  161. inline xkey_iterator(subiterator it) noexcept
  162. : m_it(it)
  163. {
  164. }
  165. inline self_type& operator++()
  166. {
  167. ++m_it;
  168. return *this;
  169. }
  170. inline self_type& operator--()
  171. {
  172. --m_it;
  173. return *this;
  174. }
  175. inline reference operator*() const
  176. {
  177. return m_it->first;
  178. }
  179. inline pointer operator->() const
  180. {
  181. return&(m_it->first);
  182. }
  183. inline bool operator==(const self_type& rhs) const
  184. {
  185. return m_it == rhs.m_it;
  186. }
  187. private:
  188. subiterator m_it;
  189. };
  190. /*******************
  191. * xvalue_iterator *
  192. *******************/
  193. namespace detail
  194. {
  195. template <class M>
  196. struct xvalue_iterator_types
  197. {
  198. using subiterator = typename M::iterator;
  199. using value_type = typename M::mapped_type;
  200. using reference = value_type&;
  201. using pointer = value_type*;
  202. using difference_type = typename subiterator::difference_type;
  203. };
  204. template <class M>
  205. struct xvalue_iterator_types<const M>
  206. {
  207. using subiterator = typename M::const_iterator;
  208. using value_type = typename M::mapped_type;
  209. using reference = const value_type&;
  210. using pointer = const value_type*;
  211. using difference_type = typename subiterator::difference_type;
  212. };
  213. }
  214. template <class M>
  215. class xvalue_iterator : xbidirectional_iterator_base3<xvalue_iterator<M>,
  216. detail::xvalue_iterator_types<M>>
  217. {
  218. public:
  219. using self_type = xvalue_iterator<M>;
  220. using base_type = xbidirectional_iterator_base3<self_type, detail::xvalue_iterator_types<M>>;
  221. using value_type = typename base_type::value_type;
  222. using reference = typename base_type::reference;
  223. using pointer = typename base_type::pointer;
  224. using difference_type = typename base_type::difference_type;
  225. using subiterator = typename detail::xvalue_iterator_types<M>::subiterator;
  226. inline xvalue_iterator(subiterator it) noexcept
  227. : m_it(it)
  228. {
  229. }
  230. inline self_type& operator++()
  231. {
  232. ++m_it;
  233. return *this;
  234. }
  235. inline self_type& operator--()
  236. {
  237. --m_it;
  238. return *this;
  239. }
  240. inline reference operator*() const
  241. {
  242. return m_it->second;
  243. }
  244. inline pointer operator->() const
  245. {
  246. return&(m_it->second);
  247. }
  248. inline bool operator==(const self_type& rhs) const
  249. {
  250. return m_it == rhs.m_it;
  251. }
  252. private:
  253. subiterator m_it;
  254. };
  255. /**********************
  256. * xstepping_iterator *
  257. **********************/
  258. template <class It>
  259. class xstepping_iterator : public xrandom_access_iterator_base3<xstepping_iterator<It>,
  260. std::iterator_traits<It>>
  261. {
  262. public:
  263. using self_type = xstepping_iterator;
  264. using base_type = xrandom_access_iterator_base3<self_type, std::iterator_traits<It>>;
  265. using value_type = typename base_type::value_type;
  266. using reference = typename base_type::reference;
  267. using pointer = typename base_type::pointer;
  268. using difference_type = typename base_type::difference_type;
  269. using iterator_category = typename base_type::iterator_category;
  270. using subiterator = It;
  271. xstepping_iterator() = default;
  272. inline xstepping_iterator(subiterator it, difference_type step) noexcept
  273. : m_it(it), m_step(step)
  274. {
  275. }
  276. inline self_type& operator++()
  277. {
  278. std::advance(m_it, m_step);
  279. return *this;
  280. }
  281. inline self_type& operator--()
  282. {
  283. std::advance(m_it, -m_step);
  284. return *this;
  285. }
  286. inline self_type& operator+=(difference_type n)
  287. {
  288. std::advance(m_it, n*m_step);
  289. return *this;
  290. }
  291. inline self_type& operator-=(difference_type n)
  292. {
  293. std::advance(m_it, -n*m_step);
  294. return *this;
  295. }
  296. inline difference_type operator-(const self_type& rhs) const
  297. {
  298. return std::distance(rhs.m_it, m_it) / m_step;
  299. }
  300. inline reference operator*() const
  301. {
  302. return *m_it;
  303. }
  304. inline pointer operator->() const
  305. {
  306. return m_it;
  307. }
  308. inline bool equal(const self_type& rhs) const
  309. {
  310. return m_it == rhs.m_it && m_step == rhs.m_step;
  311. }
  312. inline bool less_than(const self_type& rhs) const
  313. {
  314. return m_it < rhs.m_it && m_step == rhs.m_step;
  315. }
  316. private:
  317. subiterator m_it;
  318. difference_type m_step;
  319. };
  320. template <class It>
  321. inline bool operator==(const xstepping_iterator<It>& lhs, const xstepping_iterator<It>& rhs)
  322. {
  323. return lhs.equal(rhs);
  324. }
  325. template <class It>
  326. inline bool operator<(const xstepping_iterator<It>& lhs, const xstepping_iterator<It>& rhs)
  327. {
  328. return lhs.less_than(rhs);
  329. }
  330. template <class It>
  331. inline xstepping_iterator<It> make_stepping_iterator(It it, typename std::iterator_traits<It>::difference_type step)
  332. {
  333. return xstepping_iterator<It>(it, step);
  334. }
  335. /***********************
  336. * common_iterator_tag *
  337. ***********************/
  338. template <class... Its>
  339. struct common_iterator_tag : std::common_type<typename std::iterator_traits<Its>::iterator_category...>
  340. {
  341. };
  342. template <class... Its>
  343. using common_iterator_tag_t = typename common_iterator_tag<Its...>::type;
  344. }
  345. #endif