iterator 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. // Range v3 library
  2. //
  3. // Copyright Eric Niebler 2018-present
  4. //
  5. // Use, modification and distribution is subject to the
  6. // Boost Software License, Version 1.0. (See accompanying
  7. // file LICENSE_1_0.txt or copy at
  8. // http://www.boost.org/LICENSE_1_0.txt)
  9. //
  10. // Project home: https://github.com/ericniebler/range-v3
  11. //
  12. #ifndef RANGES_V3_STD_ITERATOR
  13. #define RANGES_V3_STD_ITERATOR
  14. #if defined(__GNUC__)
  15. #include_next <iterator>
  16. #elif defined(_MSC_VER)
  17. #include <../include/iterator> // HACKHACK
  18. #else
  19. #error "Cannot use range-v3 STL deep integration on this platform."
  20. #endif
  21. #if RANGES_DEEP_STL_INTEGRATION
  22. #include <range/v3/detail/config.hpp>
  23. #include <std/detail/associated_types.hpp>
  24. #include <range/v3/detail/prologue.hpp>
  25. namespace ranges
  26. {
  27. template<typename I>
  28. struct incrementable_traits;
  29. template<typename I>
  30. struct indirectly_readable_traits;
  31. /// \cond
  32. namespace detail
  33. {
  34. template<typename I>
  35. typename incrementable_traits<I>::difference_type cpp17_difference_type_(int);
  36. template<typename I>
  37. void cpp17_difference_type_(long);
  38. template<typename I>
  39. typename I::pointer cpp17_pointer_type_(int);
  40. template<typename I>
  41. auto cpp17_pointer_type_(long, I *pi = nullptr) -> decltype(pi->operator->());
  42. template<typename I>
  43. void cpp17_pointer_type_(...);
  44. template<typename I>
  45. typename I::reference cpp17_reference_type_(int);
  46. template<typename I>
  47. auto cpp17_reference_type_(long, I *pi = nullptr) -> decltype(**pi);
  48. template<typename I>
  49. auto cpp17_iterator_category_4_(long)
  50. {
  51. return std::bidirectional_iterator_tag{};
  52. }
  53. // Satisfies Cpp17RandomAccessIterator?
  54. template<typename I>
  55. auto cpp17_iterator_category_4_(
  56. int,
  57. I *pi = nullptr,
  58. typename incrementable_traits<I>::difference_type d = 0,
  59. always_<
  60. void,
  61. int[RANGES_IS_SAME(decltype(*pi += d), I &)],
  62. int[RANGES_IS_SAME(decltype(*pi -= d), I &)],
  63. int[RANGES_IS_SAME(decltype(*pi + d), I)],
  64. int[RANGES_IS_SAME(decltype(*pi - d), I)],
  65. int[RANGES_IS_SAME(decltype(d + *pi), I)],
  66. int[RANGES_IS_SAME(decltype(*pi - *pi), decltype(d))],
  67. int[RANGES_IS_SAME(decltype((*pi)[d]), decltype(**pi))],
  68. decltype(*pi < *pi ? true : false),
  69. decltype(*pi > *pi ? true : false),
  70. decltype(*pi <= *pi ? true : false),
  71. decltype(*pi >= *pi ? true : false)
  72. > * = nullptr)
  73. {
  74. return std::random_access_iterator_tag{};
  75. }
  76. template<typename I>
  77. auto cpp17_iterator_category_3_(long)
  78. {
  79. return std::forward_iterator_tag{};
  80. }
  81. // Satisfies Cpp17BidirectionalIterator?
  82. template<typename I>
  83. auto cpp17_iterator_category_3_(
  84. int,
  85. I *pi = nullptr,
  86. void (*fn)(I const &) = nullptr,
  87. always_<
  88. void,
  89. decltype(fn((*pi)--)), // i-- convertible to I const &
  90. int[RANGES_IS_SAME(decltype(--*pi), I &)], // --i has type I &
  91. // *i has the same type as *i--
  92. int[RANGES_IS_SAME(decltype(**pi), decltype(*(*pi)--))]
  93. > * = nullptr)
  94. {
  95. return cpp17_iterator_category_4_<I>(0);
  96. }
  97. template<typename I>
  98. auto cpp17_iterator_category_2_(long)
  99. {
  100. return std::input_iterator_tag{};
  101. }
  102. // Satisfies Cpp17ForwardIterator?
  103. template<typename I>
  104. auto cpp17_iterator_category_2_(
  105. int,
  106. I *pi = nullptr,
  107. void (*fn)(I const &) = nullptr,
  108. typename indirectly_readable_traits<I>::value_type *pv = nullptr,
  109. typename indirectly_readable_traits<I>::value_type const *pcv = nullptr,
  110. always_<
  111. void,
  112. decltype(I{}), // Default constructible
  113. decltype(fn((*pi)++)), // i++ convertible to I const &
  114. // *i has the same type as *i++
  115. int[RANGES_IS_SAME(decltype(**pi), decltype(*(*pi)++))],
  116. // *i is a real reference to value_type
  117. #ifdef RANGES_WORKAROUND_MSVC_793042
  118. enable_if_t<RANGES_IS_SAME(decltype(**pi), decltype(*pv)) ||
  119. RANGES_IS_SAME(decltype(**pi), decltype(*pcv)) ||
  120. RANGES_IS_SAME(decltype(**pi), typename indirectly_readable_traits<I>::value_type &&) ||
  121. RANGES_IS_SAME(decltype(**pi), typename indirectly_readable_traits<I>::value_type const &&)>
  122. #else // ^^^ workaround / no workaround vvv
  123. int[RANGES_IS_SAME(decltype(**pi), decltype(*pv)) ||
  124. RANGES_IS_SAME(decltype(**pi), decltype(*pcv)) ||
  125. RANGES_IS_SAME(decltype(**pi), typename indirectly_readable_traits<I>::value_type &&) ||
  126. RANGES_IS_SAME(decltype(**pi), typename indirectly_readable_traits<I>::value_type const &&)]
  127. #endif // RANGES_WORKAROUND_MSVC_793042
  128. > * = nullptr)
  129. {
  130. return cpp17_iterator_category_3_<I>(0);
  131. }
  132. template<typename I>
  133. using cpp17_readable_iterator_category_t =
  134. decltype(detail::cpp17_iterator_category_2_<I>(0));
  135. template<typename I>
  136. auto cpp17_iterator_category_(long)
  137. {
  138. return cpp17_iterator_category_2_<I>(0);
  139. }
  140. // Explicitly declares its category?
  141. template<typename I>
  142. typename I::iterator_category cpp17_iterator_category_(int)
  143. {
  144. return {};
  145. }
  146. template<typename I>
  147. auto std_iterator_traits_impl_2_(long)
  148. {
  149. return std_output_iterator_traits<
  150. decltype(detail::cpp17_difference_type_<I>(0))>{};
  151. }
  152. // Satisfies Cpp17InputIterator?
  153. template<typename I>
  154. auto std_iterator_traits_impl_2_(
  155. int,
  156. I *pi = nullptr,
  157. typename incrementable_traits<I>::difference_type d = 0,
  158. typename indirectly_readable_traits<I>::value_type const *pcv = nullptr,
  159. always_<
  160. void,
  161. int[decltype(d)(-1) < decltype(d)(0)], // signed difference type
  162. decltype(decltype(*pcv)(**pi)), // sensible reference/value type
  163. decltype(decltype(*pcv)(*(*pi)++)), // sensible post-increment result
  164. decltype(*pi == *pi ? true : false), // equality comparable
  165. decltype(*pi != *pi ? true : false) // " "
  166. > * = nullptr)
  167. {
  168. using D = typename incrementable_traits<I>::difference_type;
  169. struct yes_traits
  170. {
  171. using difference_type = D;
  172. using value_type = typename indirectly_readable_traits<I>::value_type;
  173. using reference = decltype(cpp17_reference_type_<I>(0));
  174. using pointer = decltype(cpp17_pointer_type_<I>(0));
  175. using iterator_category = decltype(cpp17_iterator_category_<I>(0));
  176. };
  177. struct no_traits
  178. {};
  179. return conditional_t<is_integral_<D>(0), yes_traits, no_traits>{};
  180. }
  181. template<typename I>
  182. nil_ std_iterator_traits_impl_(long)
  183. {
  184. return {};
  185. }
  186. // Satisfies Cpp17Iterator?
  187. template<typename I>
  188. auto std_iterator_traits_impl_(
  189. int,
  190. I *pi = nullptr,
  191. void (*nv)(...) = nullptr,
  192. always_<
  193. void,
  194. decltype(nv(**pi)),
  195. int[RANGES_IS_SAME(decltype(++*pi), I &)],
  196. decltype(nv(*(*pi)++))
  197. > * = nullptr)
  198. {
  199. return std_iterator_traits_impl_2_<I>(0);
  200. }
  201. template<typename T>
  202. constexpr bool has_iterator_typedefs_impl_(
  203. int,
  204. always_<
  205. void,
  206. typename T::difference_type,
  207. typename T::value_type,
  208. typename T::pointer,
  209. typename T::reference,
  210. typename T::iterator_category
  211. > * = nullptr)
  212. {
  213. return true;
  214. }
  215. template<typename T>
  216. constexpr bool has_iterator_typedefs_impl_(long)
  217. {
  218. return false;
  219. }
  220. }
  221. /// \endcond
  222. } // namespace ranges
  223. // Hijack the primary std::iterator_traits template from each of the 3 major
  224. // standard library implementations
  225. RANGES_BEGIN_NAMESPACE_STD
  226. RANGES_BEGIN_NAMESPACE_VERSION
  227. #if defined(__GLIBCXX__)
  228. template<typename I>
  229. struct __iterator_traits<
  230. I,
  231. ::ranges::detail::enable_if_t<!::ranges::detail::has_iterator_typedefs_impl_<I>(0)>>
  232. : decltype(::ranges::detail::std_iterator_traits_impl_<I>(0))
  233. {};
  234. #elif defined(_LIBCPP_VERSION)
  235. template<typename I>
  236. struct __iterator_traits<I, false> // doesn't have I::iterator_category
  237. : decltype(::ranges::detail::std_iterator_traits_impl_<I>(0))
  238. {};
  239. #elif defined(_MSVC_STL_VERSION)
  240. template<typename I>
  241. struct _Iterator_traits_base<
  242. I,
  243. #ifdef RANGES_WORKAROUND_MSVC_792338
  244. ::ranges::detail::enable_if_t<decltype(bool_constant<
  245. !::ranges::detail::has_iterator_typedefs_impl_<I>(0)>{})::value>>
  246. #else // ^^^ workaround / no workaround vvv
  247. ::ranges::detail::enable_if_t<!::ranges::detail::has_iterator_typedefs_impl_<I>(0)>>
  248. #endif // RANGES_WORKAROUND_MSVC_792338
  249. : decltype(::ranges::detail::std_iterator_traits_impl_<I>(0))
  250. {};
  251. #endif
  252. RANGES_END_NAMESPACE_VERSION
  253. RANGES_END_NAMESPACE_STD
  254. #include <range/v3/detail/epilogue.hpp>
  255. #endif // RANGES_DEEP_STL_INTEGRATION
  256. #endif // RANGES_V3_STD_ITERATOR