Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

236 rader
7.5 KiB

  1. #pragma once
  2. namespace utl
  3. {
  4. namespace __impl
  5. {
  6. template<class It, class Tag, class T = void>
  7. using mp_enable_if_has_iterator_tag = typename std::enable_if<std::is_same<typename It::iterator_category, Tag>::value, T>::type;
  8. }
  9. template<class It, class Transform, class Enable = void>
  10. struct transform_iterator;
  11. template<class It, class Transform>
  12. struct transform_iterator<It, Transform, __impl::mp_enable_if_has_iterator_tag<It, std::forward_iterator_tag>>
  13. {
  14. public:
  15. using iterator_type = transform_iterator;
  16. using iterator_category = std::input_iterator_tag;
  17. using difference_type = typename It::difference_type;
  18. using return_type = decltype(std::declval<Transform>()(std::declval<typename It::reference>()));
  19. using value_type = typename std::remove_reference<return_type>::type;
  20. using reference = value_type&;
  21. using pointer = value_type*;
  22. private:
  23. It _it;
  24. Transform _transform;
  25. public:
  26. transform_iterator()
  27. { }
  28. transform_iterator(It it, Transform transform) :
  29. _it (it),
  30. _transform (transform)
  31. { }
  32. inline iterator_type& operator=(const iterator_type& other)
  33. {
  34. _it = other._it;
  35. return *this;
  36. }
  37. inline iterator_type& operator++()
  38. {
  39. ++_it;
  40. return *this;
  41. }
  42. inline iterator_type operator++(int)
  43. { return iterator_type(_it++, _transform); }
  44. inline bool operator==(const iterator_type& other) const
  45. { return (_it == other._it) && (_transform == other._transform); }
  46. inline bool operator!= (const iterator_type& other) const
  47. { return (_it != other._it) || (_transform != other._transform); }
  48. inline return_type operator*()
  49. { return _transform(*_it); }
  50. inline pointer operator->()
  51. { return &_transform(*_it); }
  52. };
  53. template<class It, class Transform>
  54. struct transform_iterator<It, Transform, __impl::mp_enable_if_has_iterator_tag<It, std::bidirectional_iterator_tag>>
  55. {
  56. public:
  57. using iterator_type = transform_iterator;
  58. using iterator_category = std::input_iterator_tag;
  59. using difference_type = typename It::difference_type;
  60. using return_type = decltype(std::declval<Transform>()(std::declval<typename It::reference>()));
  61. using value_type = typename std::remove_reference<return_type>::type;
  62. using reference = value_type&;
  63. using pointer = value_type*;
  64. private:
  65. It _it;
  66. Transform _transform;
  67. public:
  68. transform_iterator()
  69. { }
  70. transform_iterator(It it, Transform transform) :
  71. _it (it),
  72. _transform (transform)
  73. { }
  74. inline iterator_type& operator=(const iterator_type& other)
  75. {
  76. _it = other._it;
  77. return *this;
  78. }
  79. inline iterator_type& operator++()
  80. {
  81. ++_it;
  82. return *this;
  83. }
  84. inline iterator_type operator++(int)
  85. { return iterator_type(_it++, _transform); }
  86. inline iterator_type& operator--()
  87. {
  88. --_it;
  89. return *this;
  90. }
  91. inline iterator_type operator--(int)
  92. { return iterator_type(_it--, _transform); }
  93. inline bool operator==(const iterator_type& other) const
  94. { return (_it == other._it) && (_transform == other._transform); }
  95. inline bool operator!= (const iterator_type& other) const
  96. { return (_it != other._it) || (_transform != other._transform); }
  97. inline return_type operator*()
  98. { return _transform(*_it); }
  99. inline pointer operator->()
  100. { return &_transform(*_it); }
  101. };
  102. template<class It, class Transform>
  103. struct transform_iterator<It, Transform, __impl::mp_enable_if_has_iterator_tag<It, std::random_access_iterator_tag>>
  104. {
  105. public:
  106. using iterator_type = transform_iterator;
  107. using iterator_category = std::input_iterator_tag;
  108. using difference_type = typename It::difference_type;
  109. using return_type = decltype(std::declval<Transform>()(std::declval<typename It::reference>()));
  110. using value_type = typename std::remove_reference<return_type>::type;
  111. using reference = value_type&;
  112. using pointer = value_type*;
  113. private:
  114. It _it;
  115. Transform _transform;
  116. public:
  117. transform_iterator()
  118. { }
  119. transform_iterator(It it, Transform transform) :
  120. _it (it),
  121. _transform (transform)
  122. { }
  123. inline iterator_type& operator=(const iterator_type& other)
  124. {
  125. _it = other._it;
  126. return *this;
  127. }
  128. inline iterator_type& operator++()
  129. {
  130. ++_it;
  131. return *this;
  132. }
  133. inline iterator_type operator++(int)
  134. { return iterator_type(_it++, _transform); }
  135. inline iterator_type& operator+=(difference_type n)
  136. {
  137. _it += n;
  138. return *this;
  139. }
  140. inline iterator_type operator+(difference_type n) const
  141. { return iterator_type(_it + n, _transform); }
  142. inline iterator_type& operator--()
  143. {
  144. --_it;
  145. return *this;
  146. }
  147. inline iterator_type operator--(int)
  148. { return iterator_type(_it--, _transform); }
  149. inline iterator_type& operator-=(difference_type n)
  150. {
  151. _it -= n;
  152. return *this;
  153. }
  154. inline iterator_type operator-(difference_type n) const
  155. { return iterator_type(_it - n); }
  156. inline difference_type operator-(const iterator_type& other) const
  157. { return _it - other._it; }
  158. inline bool operator==(const iterator_type& other) const
  159. { return (_it == other._it) && (_transform == other._transform); }
  160. inline bool operator!=(const iterator_type& other) const
  161. { return (_it != other._it) || (_transform != other._transform); }
  162. inline bool operator>(const iterator_type& other) const
  163. { return _it > other._it; }
  164. inline bool operator<(const iterator_type& other) const
  165. { return _it < other._it; }
  166. inline bool operator>=(const iterator_type& other) const
  167. { return _it >= other._it; }
  168. inline bool operator<=(const iterator_type& other) const
  169. { return _it <= other._it; }
  170. inline return_type operator*() const
  171. { return _transform(*_it); }
  172. inline pointer operator->() const
  173. { return &_transform(*_it); }
  174. inline return_type operator[](difference_type n) const
  175. { return *(*this + n); }
  176. };
  177. template<class It, class Transform>
  178. transform_iterator<It, Transform> make_transform_iterator(const It& it, const Transform& transform)
  179. { return transform_iterator<It, Transform>(it, transform); }
  180. template<class It, class Transform, __impl::mp_enable_if_has_iterator_tag<It, std::random_access_iterator_tag, int> = 0>
  181. inline transform_iterator<It, Transform>
  182. operator+(const typename transform_iterator<It, Transform>::difference_type& n, const transform_iterator<It, Transform>& it)
  183. { return it + n; }
  184. }