iterator_interface.hpp 43 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183
  1. // Copyright (C) 2019 T. Zachary Laine
  2. //
  3. // Distributed under the Boost Software License, Version 1.0. (See
  4. // accompanying file LICENSE_1_0.txt or copy at
  5. // http://www.boost.org/LICENSE_1_0.txt)
  6. #ifndef BOOST_STL_INTERFACES_ITERATOR_INTERFACE_HPP
  7. #define BOOST_STL_INTERFACES_ITERATOR_INTERFACE_HPP
  8. #include <boost/stl_interfaces/fwd.hpp>
  9. #include <utility>
  10. #include <type_traits>
  11. #if defined(__cpp_lib_three_way_comparison)
  12. #include <compare>
  13. #endif
  14. namespace boost { namespace stl_interfaces {
  15. /** A type for granting access to the private members of an iterator
  16. derived from `iterator_interface`. */
  17. struct access
  18. {
  19. #ifndef BOOST_STL_INTERFACES_DOXYGEN
  20. template<typename D>
  21. static constexpr auto base(D & d) noexcept
  22. -> decltype(d.base_reference())
  23. {
  24. return d.base_reference();
  25. }
  26. template<typename D>
  27. static constexpr auto base(D const & d) noexcept
  28. -> decltype(d.base_reference())
  29. {
  30. return d.base_reference();
  31. }
  32. #endif
  33. };
  34. /** The return type of `operator->()` in a proxy iterator.
  35. This template is used as the default `Pointer` template parameter in
  36. the `proxy_iterator_interface` template alias. Note that the use of
  37. this template implies a copy or move of the underlying object of type
  38. `T`. */
  39. template<typename T>
  40. #if defined(BOOST_STL_INTERFACES_DOXYGEN) || BOOST_STL_INTERFACES_USE_CONCEPTS
  41. // clang-format off
  42. requires std::is_object_v<T>
  43. #endif
  44. struct proxy_arrow_result
  45. // clang-format on
  46. {
  47. constexpr proxy_arrow_result(T const & value) noexcept(
  48. noexcept(T(value))) :
  49. value_(value)
  50. {}
  51. constexpr proxy_arrow_result(T && value) noexcept(
  52. noexcept(T(std::move(value)))) :
  53. value_(std::move(value))
  54. {}
  55. constexpr T const * operator->() const noexcept { return &value_; }
  56. constexpr T * operator->() noexcept { return &value_; }
  57. private:
  58. T value_;
  59. };
  60. namespace detail {
  61. template<typename Pointer, typename Reference, typename T>
  62. auto make_pointer(
  63. T && value,
  64. std::enable_if_t<
  65. std::is_pointer<Pointer>::value &&
  66. std::is_reference<Reference>::value,
  67. int> = 0) -> decltype(std::addressof(value))
  68. {
  69. return std::addressof(value);
  70. }
  71. template<typename Pointer, typename Reference, typename T>
  72. auto make_pointer(
  73. T && value,
  74. std::enable_if_t<
  75. !std::is_pointer<Pointer>::value &&
  76. !std::is_same<Pointer, void>::value &&
  77. std::is_reference<Reference>::value,
  78. int> = 0)
  79. {
  80. return Pointer(std::forward<T>(value));
  81. }
  82. template<typename Pointer, typename IteratorConcept>
  83. struct pointer
  84. {
  85. using type = Pointer;
  86. };
  87. template<typename Pointer>
  88. struct pointer<Pointer, std::output_iterator_tag>
  89. {
  90. using type = void;
  91. };
  92. template<typename Pointer, typename IteratorConcept>
  93. using pointer_t = typename pointer<Pointer, IteratorConcept>::type;
  94. template<typename T, typename U>
  95. using interoperable = std::integral_constant<
  96. bool,
  97. (std::is_convertible<T, U>::value ||
  98. std::is_convertible<U, T>::value)>;
  99. template<typename T, typename U>
  100. using common_t =
  101. std::conditional_t<std::is_convertible<T, U>::value, U, T>;
  102. template<typename T>
  103. using use_base = decltype(access::base(std::declval<T &>()));
  104. template<typename... T>
  105. using void_t = void;
  106. template<
  107. typename AlwaysVoid,
  108. template<class...> class Template,
  109. typename... Args>
  110. struct detector : std::false_type
  111. {
  112. };
  113. template<template<class...> class Template, typename... Args>
  114. struct detector<void_t<Template<Args...>>, Template, Args...>
  115. : std::true_type
  116. {
  117. };
  118. template<
  119. typename T,
  120. typename U,
  121. bool UseBase = detector<void, use_base, T>::value>
  122. struct common_eq
  123. {
  124. static constexpr auto call(T lhs, U rhs)
  125. {
  126. return static_cast<common_t<T, U>>(lhs).derived() ==
  127. static_cast<common_t<T, U>>(rhs).derived();
  128. }
  129. };
  130. template<typename T, typename U>
  131. struct common_eq<T, U, true>
  132. {
  133. static constexpr auto call(T lhs, U rhs)
  134. {
  135. return access::base(lhs) == access::base(rhs);
  136. }
  137. };
  138. template<typename T, typename U>
  139. constexpr auto common_diff(T lhs, U rhs) noexcept(noexcept(
  140. static_cast<common_t<T, U>>(lhs) -
  141. static_cast<common_t<T, U>>(rhs)))
  142. -> decltype(
  143. static_cast<common_t<T, U>>(lhs) -
  144. static_cast<common_t<T, U>>(rhs))
  145. {
  146. return static_cast<common_t<T, U>>(lhs) -
  147. static_cast<common_t<T, U>>(rhs);
  148. }
  149. }
  150. }}
  151. namespace boost { namespace stl_interfaces { BOOST_STL_INTERFACES_NAMESPACE_V1 {
  152. /** A CRTP template that one may derive from to make defining iterators
  153. easier.
  154. The template parameter `D` for `iterator_interface` may be an
  155. incomplete type. Before any member of the resulting specialization of
  156. `iterator_interface` other than special member functions is
  157. referenced, `D` shall be complete, and model
  158. `std::derived_from<iterator_interface<D>>`. */
  159. template<
  160. typename Derived,
  161. typename IteratorConcept,
  162. typename ValueType,
  163. typename Reference = ValueType &,
  164. typename Pointer = ValueType *,
  165. typename DifferenceType = std::ptrdiff_t
  166. #ifndef BOOST_STL_INTERFACES_DOXYGEN
  167. ,
  168. typename E = std::enable_if_t<
  169. std::is_class<Derived>::value &&
  170. std::is_same<Derived, std::remove_cv_t<Derived>>::value>
  171. #endif
  172. >
  173. struct iterator_interface;
  174. namespace v1_dtl {
  175. template<typename Iterator, typename = void>
  176. struct ra_iter : std::false_type
  177. {
  178. };
  179. template<typename Iterator>
  180. struct ra_iter<Iterator, void_t<typename Iterator::iterator_concept>>
  181. : std::integral_constant<
  182. bool,
  183. std::is_base_of<
  184. std::random_access_iterator_tag,
  185. typename Iterator::iterator_concept>::value>
  186. {
  187. };
  188. template<typename Iterator, typename DifferenceType, typename = void>
  189. struct plus_eq : std::false_type
  190. {
  191. };
  192. template<typename Iterator, typename DifferenceType>
  193. struct plus_eq<
  194. Iterator,
  195. DifferenceType,
  196. void_t<decltype(
  197. std::declval<Iterator &>() += std::declval<DifferenceType>())>>
  198. : std::true_type
  199. {
  200. };
  201. template<
  202. typename D,
  203. typename IteratorConcept,
  204. typename ValueType,
  205. typename Reference,
  206. typename Pointer,
  207. typename DifferenceType>
  208. void derived_iterator(iterator_interface<
  209. D,
  210. IteratorConcept,
  211. ValueType,
  212. Reference,
  213. Pointer,
  214. DifferenceType> const &);
  215. }
  216. template<
  217. typename Derived,
  218. typename IteratorConcept,
  219. typename ValueType,
  220. typename Reference,
  221. typename Pointer,
  222. typename DifferenceType
  223. #ifndef BOOST_STL_INTERFACES_DOXYGEN
  224. ,
  225. typename E
  226. #endif
  227. >
  228. struct iterator_interface
  229. {
  230. #ifndef BOOST_STL_INTERFACES_DOXYGEN
  231. private:
  232. constexpr Derived & derived() noexcept
  233. {
  234. return static_cast<Derived &>(*this);
  235. }
  236. constexpr Derived const & derived() const noexcept
  237. {
  238. return static_cast<Derived const &>(*this);
  239. }
  240. template<typename T, typename U, bool UseBase>
  241. friend struct detail::common_eq;
  242. #endif
  243. public:
  244. using iterator_concept = IteratorConcept;
  245. using iterator_category = iterator_concept;
  246. using value_type = std::remove_const_t<ValueType>;
  247. using reference = Reference;
  248. using pointer = detail::pointer_t<Pointer, iterator_concept>;
  249. using difference_type = DifferenceType;
  250. template<typename D = Derived>
  251. constexpr auto operator*()
  252. noexcept(noexcept(*access::base(std::declval<D &>())))
  253. -> decltype(*access::base(std::declval<D &>()))
  254. {
  255. return *access::base(derived());
  256. }
  257. template<typename D = Derived>
  258. constexpr auto operator*() const
  259. noexcept(noexcept(*access::base(std::declval<D const &>())))
  260. -> decltype(*access::base(std::declval<D const &>()))
  261. {
  262. return *access::base(derived());
  263. }
  264. template<typename D = Derived>
  265. constexpr auto operator->() noexcept(noexcept(
  266. detail::make_pointer<pointer, reference>(*std::declval<D &>())))
  267. -> decltype(
  268. detail::make_pointer<pointer, reference>(*std::declval<D &>()))
  269. {
  270. return detail::make_pointer<pointer, reference>(*derived());
  271. }
  272. template<typename D = Derived>
  273. constexpr auto operator->() const noexcept(noexcept(
  274. detail::make_pointer<pointer, reference>(
  275. *std::declval<D const &>())))
  276. -> decltype(
  277. detail::make_pointer<pointer, reference>(
  278. *std::declval<D const &>()))
  279. {
  280. return detail::make_pointer<pointer, reference>(*derived());
  281. }
  282. template<typename D = Derived>
  283. constexpr auto operator[](difference_type i) const noexcept(noexcept(
  284. D(std::declval<D const &>()),
  285. std::declval<D &>() += i,
  286. *std::declval<D &>()))
  287. -> decltype(std::declval<D &>() += i, *std::declval<D &>())
  288. {
  289. D retval = derived();
  290. retval += i;
  291. return *retval;
  292. }
  293. template<
  294. typename D = Derived,
  295. typename Enable =
  296. std::enable_if_t<!v1_dtl::plus_eq<D, difference_type>::value>>
  297. constexpr auto
  298. operator++() noexcept(noexcept(++access::base(std::declval<D &>())))
  299. -> decltype(
  300. ++access::base(std::declval<D &>()), std::declval<D &>())
  301. {
  302. ++access::base(derived());
  303. return derived();
  304. }
  305. template<typename D = Derived>
  306. constexpr auto operator++() noexcept(
  307. noexcept(std::declval<D &>() += difference_type(1)))
  308. -> decltype(
  309. std::declval<D &>() += difference_type(1), std::declval<D &>())
  310. {
  311. derived() += difference_type(1);
  312. return derived();
  313. }
  314. template<typename D = Derived>
  315. constexpr auto operator++(int)noexcept(
  316. noexcept(D(std::declval<D &>()), ++std::declval<D &>()))
  317. -> std::remove_reference_t<decltype(
  318. D(std::declval<D &>()),
  319. ++std::declval<D &>(),
  320. std::declval<D &>())>
  321. {
  322. D retval = derived();
  323. ++derived();
  324. return retval;
  325. }
  326. template<typename D = Derived>
  327. constexpr auto operator+=(difference_type n) noexcept(
  328. noexcept(access::base(std::declval<D &>()) += n))
  329. -> decltype(
  330. access::base(std::declval<D &>()) += n, std::declval<D &>())
  331. {
  332. access::base(derived()) += n;
  333. return derived();
  334. }
  335. template<typename D = Derived>
  336. constexpr auto operator+(difference_type i) const
  337. noexcept(noexcept(D(std::declval<D &>()), std::declval<D &>() += i))
  338. -> std::remove_reference_t<decltype(
  339. D(std::declval<D &>()),
  340. std::declval<D &>() += i,
  341. std::declval<D &>())>
  342. {
  343. D retval = derived();
  344. retval += i;
  345. return retval;
  346. }
  347. friend BOOST_STL_INTERFACES_HIDDEN_FRIEND_CONSTEXPR Derived
  348. operator+(difference_type i, Derived it) noexcept
  349. {
  350. return it + i;
  351. }
  352. template<
  353. typename D = Derived,
  354. typename Enable =
  355. std::enable_if_t<!v1_dtl::plus_eq<D, difference_type>::value>>
  356. constexpr auto
  357. operator--() noexcept(noexcept(--access::base(std::declval<D &>())))
  358. -> decltype(--access::base(std::declval<D &>()), std::declval<D &>())
  359. {
  360. --access::base(derived());
  361. return derived();
  362. }
  363. template<typename D = Derived>
  364. constexpr auto operator--() noexcept(noexcept(
  365. D(std::declval<D &>()), std::declval<D &>() += -difference_type(1)))
  366. -> decltype(
  367. std::declval<D &>() += -difference_type(1), std::declval<D &>())
  368. {
  369. derived() += -difference_type(1);
  370. return derived();
  371. }
  372. template<typename D = Derived>
  373. constexpr auto operator--(int)noexcept(
  374. noexcept(D(std::declval<D &>()), --std::declval<D &>()))
  375. -> std::remove_reference_t<decltype(
  376. D(std::declval<D &>()),
  377. --std::declval<D &>(),
  378. std::declval<D &>())>
  379. {
  380. D retval = derived();
  381. --derived();
  382. return retval;
  383. }
  384. template<typename D = Derived>
  385. constexpr D & operator-=(difference_type i) noexcept
  386. {
  387. derived() += -i;
  388. return derived();
  389. }
  390. template<typename D = Derived>
  391. constexpr auto operator-(D other) const noexcept(noexcept(
  392. access::base(std::declval<D const &>()) - access::base(other)))
  393. -> decltype(
  394. access::base(std::declval<D const &>()) - access::base(other))
  395. {
  396. return access::base(derived()) - access::base(other);
  397. }
  398. friend BOOST_STL_INTERFACES_HIDDEN_FRIEND_CONSTEXPR Derived
  399. operator-(Derived it, difference_type i) noexcept
  400. {
  401. Derived retval = it;
  402. retval += -i;
  403. return retval;
  404. }
  405. };
  406. /** Implementation of `operator==()`, implemented in terms of the iterator
  407. underlying IteratorInterface, for all iterators derived from
  408. `iterator_interface`, except those with an iterator category derived
  409. from `std::random_access_iterator_tag`. */
  410. template<
  411. typename IteratorInterface1,
  412. typename IteratorInterface2,
  413. typename Enable =
  414. std::enable_if_t<!v1_dtl::ra_iter<IteratorInterface1>::value>>
  415. constexpr auto
  416. operator==(IteratorInterface1 lhs, IteratorInterface2 rhs) noexcept
  417. -> decltype(
  418. access::base(std::declval<IteratorInterface1 &>()) ==
  419. access::base(std::declval<IteratorInterface2 &>()))
  420. {
  421. return access::base(lhs) == access::base(rhs);
  422. }
  423. /** Implementation of `operator==()` for all iterators derived from
  424. `iterator_interface` that have an iterator category derived from
  425. `std::random_access_iterator_tag`. */
  426. template<
  427. typename IteratorInterface1,
  428. typename IteratorInterface2,
  429. typename Enable =
  430. std::enable_if_t<v1_dtl::ra_iter<IteratorInterface1>::value>>
  431. constexpr auto
  432. operator==(IteratorInterface1 lhs, IteratorInterface2 rhs) noexcept(
  433. noexcept(detail::common_diff(lhs, rhs)))
  434. -> decltype(
  435. v1_dtl::derived_iterator(lhs), detail::common_diff(lhs, rhs) == 0)
  436. {
  437. return detail::common_diff(lhs, rhs) == 0;
  438. }
  439. /** Implementation of `operator!=()` for all iterators derived from
  440. `iterator_interface`. */
  441. template<typename IteratorInterface1, typename IteratorInterface2>
  442. constexpr auto operator!=(
  443. IteratorInterface1 lhs,
  444. IteratorInterface2 rhs) noexcept(noexcept(!(lhs == rhs)))
  445. -> decltype(v1_dtl::derived_iterator(lhs), !(lhs == rhs))
  446. {
  447. return !(lhs == rhs);
  448. }
  449. /** Implementation of `operator<()` for all iterators derived from
  450. `iterator_interface` that have an iterator category derived from
  451. `std::random_access_iterator_tag`. */
  452. template<typename IteratorInterface1, typename IteratorInterface2>
  453. constexpr auto
  454. operator<(IteratorInterface1 lhs, IteratorInterface2 rhs) noexcept(
  455. noexcept(detail::common_diff(lhs, rhs)))
  456. -> decltype(
  457. v1_dtl::derived_iterator(lhs), detail::common_diff(lhs, rhs) < 0)
  458. {
  459. return detail::common_diff(lhs, rhs) < 0;
  460. }
  461. /** Implementation of `operator<=()` for all iterators derived from
  462. `iterator_interface` that have an iterator category derived from
  463. `std::random_access_iterator_tag`. */
  464. template<typename IteratorInterface1, typename IteratorInterface2>
  465. constexpr auto
  466. operator<=(IteratorInterface1 lhs, IteratorInterface2 rhs) noexcept(
  467. noexcept(detail::common_diff(lhs, rhs)))
  468. -> decltype(
  469. v1_dtl::derived_iterator(lhs), detail::common_diff(lhs, rhs) <= 0)
  470. {
  471. return detail::common_diff(lhs, rhs) <= 0;
  472. }
  473. /** Implementation of `operator>()` for all iterators derived from
  474. `iterator_interface` that have an iterator category derived from
  475. `std::random_access_iterator_tag`. */
  476. template<typename IteratorInterface1, typename IteratorInterface2>
  477. constexpr auto
  478. operator>(IteratorInterface1 lhs, IteratorInterface2 rhs) noexcept(
  479. noexcept(detail::common_diff(lhs, rhs)))
  480. -> decltype(
  481. v1_dtl::derived_iterator(lhs), detail::common_diff(lhs, rhs) > 0)
  482. {
  483. return detail::common_diff(lhs, rhs) > 0;
  484. }
  485. /** Implementation of `operator>=()` for all iterators derived from
  486. `iterator_interface` that have an iterator category derived from
  487. `std::random_access_iterator_tag`. */
  488. template<typename IteratorInterface1, typename IteratorInterface2>
  489. constexpr auto
  490. operator>=(IteratorInterface1 lhs, IteratorInterface2 rhs) noexcept(
  491. noexcept(detail::common_diff(lhs, rhs)))
  492. -> decltype(
  493. v1_dtl::derived_iterator(lhs), detail::common_diff(lhs, rhs) >= 0)
  494. {
  495. return detail::common_diff(lhs, rhs) >= 0;
  496. }
  497. /** A template alias useful for defining proxy iterators. \see
  498. `iterator_interface`. */
  499. template<
  500. typename Derived,
  501. typename IteratorConcept,
  502. typename ValueType,
  503. typename Reference = ValueType,
  504. typename DifferenceType = std::ptrdiff_t>
  505. using proxy_iterator_interface = iterator_interface<
  506. Derived,
  507. IteratorConcept,
  508. ValueType,
  509. Reference,
  510. proxy_arrow_result<Reference>,
  511. DifferenceType>;
  512. }}}
  513. #if defined(BOOST_STL_INTERFACES_DOXYGEN) || BOOST_STL_INTERFACES_USE_CONCEPTS
  514. namespace boost { namespace stl_interfaces { BOOST_STL_INTERFACES_NAMESPACE_V2 {
  515. namespace v2_dtl {
  516. template<typename Iterator>
  517. struct iter_concept;
  518. template<typename Iterator>
  519. requires requires
  520. {
  521. typename std::iterator_traits<Iterator>::iterator_concept;
  522. }
  523. struct iter_concept<Iterator>
  524. {
  525. using type =
  526. typename std::iterator_traits<Iterator>::iterator_concept;
  527. };
  528. template<typename Iterator>
  529. requires(
  530. !requires {
  531. typename std::iterator_traits<Iterator>::iterator_concept;
  532. } &&
  533. requires {
  534. typename std::iterator_traits<Iterator>::iterator_category;
  535. })
  536. struct iter_concept<Iterator>
  537. {
  538. using type =
  539. typename std::iterator_traits<Iterator>::iterator_category;
  540. };
  541. template<typename Iterator>
  542. requires(
  543. !requires {
  544. typename std::iterator_traits<Iterator>::iterator_concept;
  545. } &&
  546. !requires {
  547. typename std::iterator_traits<Iterator>::iterator_category;
  548. })
  549. struct iter_concept<Iterator>
  550. {
  551. using type = std::random_access_iterator_tag;
  552. };
  553. template<typename Iterator>
  554. struct iter_concept
  555. {};
  556. template<typename Iterator>
  557. using iter_concept_t = typename iter_concept<Iterator>::type;
  558. template<typename D, typename DifferenceType>
  559. // clang-format off
  560. concept plus_eq = requires (D d) { d += DifferenceType(1); };
  561. // clang-format on
  562. template<typename D, typename D2 = D>
  563. // clang-format off
  564. concept base_3way =
  565. #if defined(__cpp_impl_three_way_comparison)
  566. requires (D d, D2 d2) { access::base(d) <=> access::base(d2); };
  567. #else
  568. false;
  569. #endif
  570. // clang-format on
  571. template<typename D1, typename D2 = D1>
  572. // clang-format off
  573. concept base_eq =
  574. requires (D1 d1, D2 d2) { access::base(d1) == access::base(d2); };
  575. // clang-format on
  576. template<typename D, typename D2 = D>
  577. // clang-format off
  578. concept iter_sub = requires (D d, D2 d2) {
  579. typename D::difference_type;
  580. {d - d2} -> std::convertible_to<typename D::difference_type>;
  581. };
  582. // clang-format on
  583. // This iterator concept -> category mapping scheme follows the one
  584. // from zip_transform_view; see
  585. // https://eel.is/c++draft/range.zip.transform.iterator#1.
  586. template<typename IteratorConcept, typename ReferenceType>
  587. constexpr auto category_tag()
  588. {
  589. if constexpr (std::is_base_of_v<
  590. std::forward_iterator_tag,
  591. IteratorConcept>) {
  592. if constexpr (!std::is_reference_v<ReferenceType>) {
  593. return std::input_iterator_tag{};
  594. } else if constexpr (std::is_base_of_v<
  595. std::random_access_iterator_tag,
  596. IteratorConcept>) {
  597. return std::random_access_iterator_tag{};
  598. } else if constexpr (std::is_base_of_v<
  599. std::bidirectional_iterator_tag,
  600. IteratorConcept>) {
  601. return std::bidirectional_iterator_tag{};
  602. } else {
  603. return std::forward_iterator_tag{};
  604. }
  605. } else {
  606. return 0; // int means "no tag"
  607. }
  608. }
  609. template<
  610. typename IteratorConcept,
  611. typename ReferenceType,
  612. typename IteratorCategory =
  613. decltype(v2_dtl::
  614. category_tag<IteratorConcept, ReferenceType>())>
  615. struct iterator_category_base
  616. {
  617. using iterator_category = IteratorCategory;
  618. };
  619. template<typename IteratorConcept, typename ReferenceType>
  620. struct iterator_category_base<IteratorConcept, ReferenceType, int>
  621. {};
  622. template<typename IteratorConcept, typename ReferenceType>
  623. constexpr bool non_input_tag()
  624. {
  625. if (std::same_as<IteratorConcept, std::input_iterator_tag>)
  626. return false;
  627. using tag_t =
  628. decltype(v2_dtl::
  629. category_tag<IteratorConcept, ReferenceType>());
  630. return !std::same_as<tag_t, std::input_iterator_tag>;
  631. }
  632. }
  633. // clang-format off
  634. /** A CRTP template that one may derive from to make defining iterators
  635. easier.
  636. The template parameter `D` for `iterator_interface` may be an
  637. incomplete type. Before any member of the resulting specialization of
  638. `iterator_interface` other than special member functions is
  639. referenced, `D` shall be complete, and model
  640. `std::derived_from<iterator_interface<D>>`. */
  641. template<
  642. typename D,
  643. typename IteratorConcept,
  644. typename ValueType,
  645. typename Reference = ValueType &,
  646. typename Pointer = ValueType *,
  647. typename DifferenceType = std::ptrdiff_t>
  648. requires std::is_class_v<D> && std::same_as<D, std::remove_cv_t<D>>
  649. struct iterator_interface
  650. : v2_dtl::iterator_category_base<IteratorConcept, Reference>
  651. {
  652. private:
  653. constexpr D& derived() noexcept {
  654. return static_cast<D&>(*this);
  655. }
  656. constexpr const D& derived() const noexcept {
  657. return static_cast<const D&>(*this);
  658. }
  659. public:
  660. using iterator_concept = IteratorConcept;
  661. using value_type = std::remove_const_t<ValueType>;
  662. using reference = Reference;
  663. using pointer = detail::pointer_t<Pointer, iterator_concept>;
  664. using difference_type = DifferenceType;
  665. constexpr decltype(auto) operator*()
  666. requires requires (D d) { *access::base(d); } {
  667. return *access::base(derived());
  668. }
  669. constexpr decltype(auto) operator*() const
  670. requires requires (D const d) { *access::base(d); } {
  671. return *access::base(derived());
  672. }
  673. constexpr auto operator->()
  674. requires (!std::same_as<pointer, void> && std::is_reference_v<reference> &&
  675. requires (D d) { *d; }) {
  676. return detail::make_pointer<pointer, reference>(*derived());
  677. }
  678. constexpr auto operator->() const
  679. requires (!std::same_as<pointer, void> && std::is_reference_v<reference> &&
  680. requires (D const d) { *d; }) {
  681. return detail::make_pointer<pointer, reference>(*derived());
  682. }
  683. constexpr decltype(auto) operator[](difference_type n) const
  684. requires requires (D const d) { d + n; } {
  685. D retval = derived();
  686. retval += n;
  687. return *retval;
  688. }
  689. constexpr decltype(auto) operator++()
  690. requires requires (D d) { ++access::base(d); } &&
  691. (!v2_dtl::plus_eq<D, difference_type>) {
  692. ++access::base(derived());
  693. return derived();
  694. }
  695. constexpr decltype(auto) operator++()
  696. requires requires (D d) { d += difference_type(1); } {
  697. return derived() += difference_type(1);
  698. }
  699. constexpr auto operator++(int) requires requires (D d) { ++d; } {
  700. if constexpr (std::is_same_v<IteratorConcept, std::input_iterator_tag>){
  701. ++derived();
  702. } else {
  703. D retval = derived();
  704. ++derived();
  705. return retval;
  706. }
  707. }
  708. constexpr decltype(auto) operator+=(difference_type n)
  709. requires requires (D d) { access::base(d) += n; } {
  710. access::base(derived()) += n;
  711. return derived();
  712. }
  713. constexpr decltype(auto) operator--()
  714. requires requires (D d) { --access::base(d); } &&
  715. (!v2_dtl::plus_eq<D, difference_type>) {
  716. --access::base(derived());
  717. return derived();
  718. }
  719. constexpr decltype(auto) operator--()
  720. requires requires (D d) { d += -difference_type(1); } {
  721. return derived() += -difference_type(1);
  722. }
  723. constexpr auto operator--(int) requires requires (D d) { --d; } {
  724. D retval = derived();
  725. --derived();
  726. return retval;
  727. }
  728. constexpr decltype(auto) operator-=(difference_type n)
  729. requires requires (D d) { d += -n; } {
  730. return derived() += -n;
  731. }
  732. };
  733. namespace v2_dtl {
  734. template<
  735. typename D,
  736. typename IteratorConcept,
  737. typename ValueType,
  738. typename Reference,
  739. typename Pointer,
  740. typename DifferenceType>
  741. void derived_iterator(v2::iterator_interface<
  742. D,
  743. IteratorConcept,
  744. ValueType,
  745. Reference,
  746. Pointer,
  747. DifferenceType> const &);
  748. template<typename D>
  749. concept derived_iter = requires (D d) { v2_dtl::derived_iterator(d); };
  750. }
  751. template<typename D>
  752. constexpr auto operator+(D it, typename D::difference_type n)
  753. requires v2_dtl::derived_iter<D> && requires { it += n; }
  754. { return it += n; }
  755. template<typename D>
  756. constexpr auto operator+(typename D::difference_type n, D it)
  757. requires v2_dtl::derived_iter<D> && requires { it += n; }
  758. { return it += n; }
  759. template<typename D1, typename D2>
  760. constexpr auto operator-(D1 lhs, D2 rhs)
  761. requires v2_dtl::derived_iter<D1> && v2_dtl::derived_iter<D2> &&
  762. requires { access::base(lhs) - access::base(rhs); }
  763. { return access::base(lhs) - access::base(rhs); }
  764. template<typename D>
  765. constexpr auto operator-(D it, typename D::difference_type n)
  766. requires v2_dtl::derived_iter<D> && requires { it += -n; }
  767. { return it += -n; }
  768. #if defined(__cpp_lib_three_way_comparison)
  769. template<typename D1, typename D2>
  770. constexpr auto operator<=>(D1 lhs, D2 rhs)
  771. requires v2_dtl::derived_iter<D1> && v2_dtl::derived_iter<D2> &&
  772. (v2_dtl::base_3way<D1, D2> || v2_dtl::iter_sub<D1, D2>) {
  773. if constexpr (v2_dtl::base_3way<D1, D2>) {
  774. return access::base(lhs) <=> access::base(rhs);
  775. } else {
  776. using diff_type = typename D1::difference_type;
  777. diff_type const diff = rhs - lhs;
  778. return diff < diff_type(0) ? std::strong_ordering::less :
  779. diff_type(0) < diff ? std::strong_ordering::greater :
  780. std::strong_ordering::equal;
  781. }
  782. }
  783. #endif
  784. template<typename D1, typename D2>
  785. constexpr bool operator<(D1 lhs, D2 rhs)
  786. requires v2_dtl::derived_iter<D1> && v2_dtl::derived_iter<D2> && v2_dtl::iter_sub<D1, D2>
  787. { return (lhs - rhs) < typename D1::difference_type(0); }
  788. template<typename D1, typename D2>
  789. constexpr bool operator<=(D1 lhs, D2 rhs)
  790. requires v2_dtl::derived_iter<D1> && v2_dtl::derived_iter<D2> && v2_dtl::iter_sub<D1, D2>
  791. { return (lhs - rhs) <= typename D1::difference_type(0); }
  792. template<typename D1, typename D2>
  793. constexpr bool operator>(D1 lhs, D2 rhs)
  794. requires v2_dtl::derived_iter<D1> && v2_dtl::derived_iter<D2> && v2_dtl::iter_sub<D1, D2>
  795. { return (lhs - rhs) > typename D1::difference_type(0); }
  796. template<typename D1, typename D2>
  797. constexpr bool operator>=(D1 lhs, D2 rhs)
  798. requires v2_dtl::derived_iter<D1> && v2_dtl::derived_iter<D2> && v2_dtl::iter_sub<D1, D2>
  799. { return (lhs - rhs) >= typename D1::difference_type(0); }
  800. template<typename D1, typename D2>
  801. constexpr bool operator==(D1 lhs, D2 rhs)
  802. requires v2_dtl::derived_iter<D1> && v2_dtl::derived_iter<D2> &&
  803. detail::interoperable<D1, D2>::value &&
  804. (v2_dtl::base_eq<D1, D2> || v2_dtl::iter_sub<D1, D2>) {
  805. if constexpr (v2_dtl::base_eq<D1, D2>) {
  806. return (access::base(lhs) == access::base(rhs));
  807. } else if constexpr (v2_dtl::iter_sub<D1, D2>) {
  808. return (lhs - rhs) == typename D1::difference_type(0);
  809. }
  810. }
  811. template<typename D1, typename D2>
  812. constexpr auto operator!=(D1 lhs, D2 rhs) -> decltype(!(lhs == rhs))
  813. requires v2_dtl::derived_iter<D1> && v2_dtl::derived_iter<D2>
  814. { return !(lhs == rhs); }
  815. // clang-format on
  816. /** A template alias useful for defining proxy iterators. \see
  817. `iterator_interface`. */
  818. template<
  819. typename Derived,
  820. typename IteratorConcept,
  821. typename ValueType,
  822. typename Reference = ValueType,
  823. typename DifferenceType = std::ptrdiff_t>
  824. using proxy_iterator_interface = iterator_interface<
  825. Derived,
  826. IteratorConcept,
  827. ValueType,
  828. Reference,
  829. proxy_arrow_result<Reference>,
  830. DifferenceType>;
  831. }}}
  832. #endif
  833. #if defined(BOOST_STL_INTERFACES_DOXYGEN) || BOOST_STL_INTERFACES_USE_DEDUCED_THIS
  834. namespace boost { namespace stl_interfaces { BOOST_STL_INTERFACES_NAMESPACE_V3 {
  835. // clang-format off
  836. /** A base template that one may derive from to make defining iterators
  837. easier. */
  838. template<
  839. typename IteratorConcept,
  840. typename ValueType,
  841. typename Reference = ValueType &,
  842. typename Pointer = ValueType *,
  843. typename DifferenceType = std::ptrdiff_t>
  844. struct iterator_interface
  845. : v2::v2_dtl::iterator_category_base<IteratorConcept, Reference>
  846. {
  847. using iterator_concept = IteratorConcept;
  848. using value_type = std::remove_const_t<ValueType>;
  849. using reference = Reference;
  850. using pointer = detail::pointer_t<Pointer, iterator_concept>;
  851. using difference_type = DifferenceType;
  852. constexpr decltype(auto) operator*(this auto&& self)
  853. requires requires { *access::base(self); } {
  854. return *access::base(self);
  855. }
  856. constexpr auto operator->(this auto&& self)
  857. requires (!std::same_as<pointer, void>) && std::is_reference_v<reference> && requires { *self; } {
  858. return detail::make_pointer<pointer, reference>(*self);
  859. }
  860. constexpr decltype(auto) operator[](this auto const& self, difference_type n)
  861. requires requires { self + n; } {
  862. auto retval = self;
  863. retval = retval + n;
  864. return *retval;
  865. }
  866. constexpr decltype(auto) operator++(this auto& self)
  867. requires requires { ++access::base(self); } && (!requires { self += difference_type(1); }) {
  868. ++access::base(self);
  869. return self;
  870. }
  871. constexpr decltype(auto) operator++(this auto& self)
  872. requires requires { self += difference_type(1); } {
  873. return self += difference_type(1);
  874. }
  875. constexpr auto operator++(this auto& self, int) requires requires { ++self; } {
  876. if constexpr (std::is_same_v<IteratorConcept, std::input_iterator_tag>){
  877. ++self;
  878. } else {
  879. auto retval = self;
  880. ++self;
  881. return retval;
  882. }
  883. }
  884. constexpr decltype(auto) operator+=(this auto& self, difference_type n)
  885. requires requires { access::base(self) += n; } {
  886. access::base(self) += n;
  887. return self;
  888. }
  889. constexpr decltype(auto) operator--(this auto& self)
  890. requires requires { --access::base(self); } && (!requires { self += difference_type(1); }) {
  891. --access::base(self);
  892. return self;
  893. }
  894. constexpr decltype(auto) operator--(this auto& self)
  895. requires requires { self += -difference_type(1); } {
  896. return self += -difference_type(1);
  897. }
  898. constexpr auto operator--(this auto& self, int) requires requires { --self; } {
  899. auto retval = self;
  900. --self;
  901. return retval;
  902. }
  903. constexpr decltype(auto) operator-=(this auto& self, difference_type n)
  904. requires requires { self += -n; } {
  905. return self += -n;
  906. }
  907. };
  908. namespace v3_dtl {
  909. template<
  910. typename IteratorConcept,
  911. typename ValueType,
  912. typename Reference,
  913. typename Pointer,
  914. typename DifferenceType>
  915. void derived_iterator(v3::iterator_interface<
  916. IteratorConcept,
  917. ValueType,
  918. Reference,
  919. Pointer,
  920. DifferenceType> const &);
  921. template<typename D>
  922. concept derived_iter = requires (D d) { v3_dtl::derived_iterator(d); };
  923. }
  924. template<typename D>
  925. constexpr auto operator+(D it, typename D::difference_type n)
  926. requires v3_dtl::derived_iter<D> && requires { it += n; }
  927. { return it += n; }
  928. template<typename D>
  929. constexpr auto operator+(typename D::difference_type n, D it)
  930. requires v3_dtl::derived_iter<D> && requires { it += n; }
  931. { return it += n; }
  932. template<typename D1, typename D2>
  933. constexpr auto operator-(D1 lhs, D2 rhs)
  934. requires v3_dtl::derived_iter<D1> && v3_dtl::derived_iter<D2> &&
  935. requires { access::base(lhs) - access::base(rhs); }
  936. { return access::base(lhs) - access::base(rhs); }
  937. template<typename D>
  938. constexpr auto operator-(D it, typename D::difference_type n)
  939. requires v3_dtl::derived_iter<D> && requires { it += -n; }
  940. { return it += -n; }
  941. #if defined(__cpp_lib_three_way_comparison)
  942. template<typename D1, typename D2>
  943. constexpr auto operator<=>(D1 lhs, D2 rhs)
  944. requires v3_dtl::derived_iter<D1> && v3_dtl::derived_iter<D2> &&
  945. (v2::v2_dtl::base_3way<D1, D2> || v2::v2_dtl::iter_sub<D1, D2>) {
  946. if constexpr (v2::v2_dtl::base_3way<D1, D2>) {
  947. return access::base(lhs) <=> access::base(rhs);
  948. } else {
  949. using diff_type = typename D1::difference_type;
  950. diff_type const diff = rhs - lhs;
  951. return diff < diff_type(0) ? std::strong_ordering::less :
  952. diff_type(0) < diff ? std::strong_ordering::greater :
  953. std::strong_ordering::equal;
  954. }
  955. }
  956. #endif
  957. template<typename D1, typename D2>
  958. constexpr bool operator<(D1 lhs, D2 rhs)
  959. requires v3_dtl::derived_iter<D1> && v3_dtl::derived_iter<D2> && v2::v2_dtl::iter_sub<D1, D2>
  960. { return (lhs - rhs) < typename D1::difference_type(0); }
  961. template<typename D1, typename D2>
  962. constexpr bool operator<=(D1 lhs, D2 rhs)
  963. requires v3_dtl::derived_iter<D1> && v3_dtl::derived_iter<D2> && v2::v2_dtl::iter_sub<D1, D2>
  964. { return (lhs - rhs) <= typename D1::difference_type(0); }
  965. template<typename D1, typename D2>
  966. constexpr bool operator>(D1 lhs, D2 rhs)
  967. requires v3_dtl::derived_iter<D1> && v3_dtl::derived_iter<D2> && v2::v2_dtl::iter_sub<D1, D2>
  968. { return (lhs - rhs) > typename D1::difference_type(0); }
  969. template<typename D1, typename D2>
  970. constexpr bool operator>=(D1 lhs, D2 rhs)
  971. requires v3_dtl::derived_iter<D1> && v3_dtl::derived_iter<D2> && v2::v2_dtl::iter_sub<D1, D2>
  972. { return (lhs - rhs) >= typename D1::difference_type(0); }
  973. template<typename D1, typename D2>
  974. constexpr bool operator==(D1 lhs, D2 rhs)
  975. requires v3_dtl::derived_iter<D1> && v3_dtl::derived_iter<D2> &&
  976. detail::interoperable<D1, D2>::value &&
  977. (v2::v2_dtl::base_eq<D1, D2> || v2::v2_dtl::iter_sub<D1, D2>) {
  978. if constexpr (v2::v2_dtl::base_eq<D1, D2>) {
  979. return (access::base(lhs) == access::base(rhs));
  980. } else if constexpr (v2::v2_dtl::iter_sub<D1, D2>) {
  981. return (lhs - rhs) == typename D1::difference_type(0);
  982. }
  983. }
  984. template<typename D1, typename D2>
  985. constexpr auto operator!=(D1 lhs, D2 rhs) -> decltype(!(lhs == rhs))
  986. requires v3_dtl::derived_iter<D1> && v3_dtl::derived_iter<D2>
  987. { return !(lhs == rhs); }
  988. // clang-format on
  989. /** A template alias useful for defining proxy iterators. \see
  990. `iterator_interface`. */
  991. template<
  992. typename IteratorConcept,
  993. typename ValueType,
  994. typename Reference = ValueType,
  995. typename DifferenceType = std::ptrdiff_t>
  996. using proxy_iterator_interface = iterator_interface<
  997. IteratorConcept,
  998. ValueType,
  999. Reference,
  1000. proxy_arrow_result<Reference>,
  1001. DifferenceType>;
  1002. }}}
  1003. #endif
  1004. #ifdef BOOST_STL_INTERFACES_DOXYGEN
  1005. /** `static_asserts` that type `type` models concept `concept_name`. This is
  1006. useful for checking that an iterator, view, etc. that you write using one
  1007. of the *`_interface` templates models the right C++ concept.
  1008. For example: `BOOST_STL_INTERFACES_STATIC_ASSERT_CONCEPT(my_iter,
  1009. std::input_iterator)`.
  1010. \note This macro expands to nothing when `__cpp_lib_concepts` is not
  1011. defined. */
  1012. #define BOOST_STL_INTERFACES_STATIC_ASSERT_CONCEPT(type, concept_name)
  1013. /** `static_asserts` that the types of all typedefs in
  1014. `std::iterator_traits<iter>` match the remaining macro parameters. This
  1015. is useful for checking that an iterator you write using
  1016. `iterator_interface` has the correct iterator traits.
  1017. For example: `BOOST_STL_INTERFACES_STATIC_ASSERT_ITERATOR_TRAITS(my_iter,
  1018. std::input_iterator_tag, std::input_iterator, int, int &, int *, std::ptrdiff_t)`.
  1019. \note This macro ignores the `concept` parameter when `__cpp_lib_concepts`
  1020. is not defined. */
  1021. #define BOOST_STL_INTERFACES_STATIC_ASSERT_ITERATOR_TRAITS( \
  1022. iter, category, concept, value_type, reference, pointer, difference_type)
  1023. #else
  1024. #define BOOST_STL_INTERFACES_STATIC_ASSERT_ITERATOR_CONCEPT_IMPL( \
  1025. type, concept_name) \
  1026. static_assert(concept_name<type>, "");
  1027. #if BOOST_STL_INTERFACES_USE_CONCEPTS
  1028. #define BOOST_STL_INTERFACES_STATIC_ASSERT_CONCEPT(iter, concept_name) \
  1029. BOOST_STL_INTERFACES_STATIC_ASSERT_ITERATOR_CONCEPT_IMPL(iter, concept_name)
  1030. #else
  1031. #define BOOST_STL_INTERFACES_STATIC_ASSERT_CONCEPT(iter, concept_name)
  1032. #endif
  1033. #define BOOST_STL_INTERFACES_STATIC_ASSERT_ITERATOR_TRAITS_IMPL( \
  1034. iter, category, value_t, ref, ptr, diff_t) \
  1035. static_assert( \
  1036. std::is_same< \
  1037. typename std::iterator_traits<iter>::value_type, \
  1038. value_t>::value, \
  1039. ""); \
  1040. static_assert( \
  1041. std::is_same<typename std::iterator_traits<iter>::reference, ref>:: \
  1042. value, \
  1043. ""); \
  1044. static_assert( \
  1045. std::is_same<typename std::iterator_traits<iter>::pointer, ptr>:: \
  1046. value, \
  1047. ""); \
  1048. static_assert( \
  1049. std::is_same< \
  1050. typename std::iterator_traits<iter>::difference_type, \
  1051. diff_t>::value, \
  1052. "");
  1053. #define BOOST_STL_INTERFACES_STATIC_ASSERT_ITERATOR_TRAITS( \
  1054. iter, category, concept, value_type, reference, pointer, difference_type) \
  1055. BOOST_STL_INTERFACES_STATIC_ASSERT_ITERATOR_TRAITS_IMPL( \
  1056. iter, category, value_type, reference, pointer, difference_type)
  1057. #endif
  1058. #endif