iterator_interface.hpp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675
  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. struct proxy_arrow_result
  41. {
  42. constexpr proxy_arrow_result(T const & value) noexcept(
  43. noexcept(T(value))) :
  44. value_(value)
  45. {}
  46. constexpr proxy_arrow_result(T && value) noexcept(
  47. noexcept(T(std::move(value)))) :
  48. value_(std::move(value))
  49. {}
  50. constexpr T const * operator->() const noexcept { return &value_; }
  51. constexpr T * operator->() noexcept { return &value_; }
  52. private:
  53. T value_;
  54. };
  55. namespace detail {
  56. template<typename Pointer, typename T>
  57. auto make_pointer(
  58. T && value,
  59. std::enable_if_t<std::is_pointer<Pointer>::value, int> = 0)
  60. -> decltype(std::addressof(value))
  61. {
  62. return std::addressof(value);
  63. }
  64. template<typename Pointer, typename T>
  65. auto make_pointer(
  66. T && value,
  67. std::enable_if_t<!std::is_pointer<Pointer>::value, int> = 0)
  68. {
  69. return Pointer(std::forward<T>(value));
  70. }
  71. template<typename IteratorConcept>
  72. struct concept_category
  73. {
  74. using type = IteratorConcept;
  75. };
  76. template<typename IteratorConcept>
  77. using concept_category_t =
  78. typename concept_category<IteratorConcept>::type;
  79. template<typename Pointer, typename IteratorConcept>
  80. struct pointer
  81. {
  82. using type = Pointer;
  83. };
  84. template<typename Pointer>
  85. struct pointer<Pointer, std::output_iterator_tag>
  86. {
  87. using type = void;
  88. };
  89. template<typename Pointer, typename IteratorConcept>
  90. using pointer_t = typename pointer<Pointer, IteratorConcept>::type;
  91. template<typename T, typename U>
  92. using interoperable = std::integral_constant<
  93. bool,
  94. (std::is_convertible<T, U>::value ||
  95. std::is_convertible<U, T>::value)>;
  96. template<typename T, typename U>
  97. using common_t =
  98. std::conditional_t<std::is_convertible<T, U>::value, U, T>;
  99. template<typename T>
  100. using use_base = decltype(access::base(std::declval<T &>()));
  101. template<typename... T>
  102. using void_t = void;
  103. template<
  104. typename AlwaysVoid,
  105. template<class...> class Template,
  106. typename... Args>
  107. struct detector : std::false_type
  108. {
  109. };
  110. template<template<class...> class Template, typename... Args>
  111. struct detector<void_t<Template<Args...>>, Template, Args...>
  112. : std::true_type
  113. {
  114. };
  115. template<
  116. typename T,
  117. typename U,
  118. bool UseBase = detector<void, use_base, T>::value>
  119. struct common_eq
  120. {
  121. static constexpr auto call(T lhs, U rhs)
  122. {
  123. return static_cast<common_t<T, U>>(lhs).derived() ==
  124. static_cast<common_t<T, U>>(rhs).derived();
  125. }
  126. };
  127. template<typename T, typename U>
  128. struct common_eq<T, U, true>
  129. {
  130. static constexpr auto call(T lhs, U rhs)
  131. {
  132. return access::base(lhs) == access::base(rhs);
  133. }
  134. };
  135. template<typename T, typename U>
  136. constexpr auto common_diff(T lhs, U rhs) noexcept(noexcept(
  137. static_cast<common_t<T, U>>(lhs) -
  138. static_cast<common_t<T, U>>(rhs)))
  139. -> decltype(
  140. static_cast<common_t<T, U>>(lhs) -
  141. static_cast<common_t<T, U>>(rhs))
  142. {
  143. return static_cast<common_t<T, U>>(lhs) -
  144. static_cast<common_t<T, U>>(rhs);
  145. }
  146. }
  147. }}
  148. namespace boost { namespace stl_interfaces { inline namespace v1 {
  149. /** A CRTP template that one may derive from to make defining iterators
  150. easier.
  151. The template parameter `D` for `iterator_interface` may be an
  152. incomplete type. Before any member of the resulting specialization of
  153. `iterator_interface` other than special member functions is
  154. referenced, `D` shall be complete, and model
  155. `std::derived_from<iterator_interface<D>>`. */
  156. template<
  157. typename Derived,
  158. typename IteratorConcept,
  159. typename ValueType,
  160. typename Reference = ValueType &,
  161. typename Pointer = ValueType *,
  162. typename DifferenceType = std::ptrdiff_t
  163. #ifndef BOOST_STL_INTERFACES_DOXYGEN
  164. ,
  165. typename E = std::enable_if_t<
  166. std::is_class<Derived>::value &&
  167. std::is_same<Derived, std::remove_cv_t<Derived>>::value>
  168. #endif
  169. >
  170. struct iterator_interface;
  171. namespace v1_dtl {
  172. template<typename Iterator, typename = void>
  173. struct ra_iter : std::false_type
  174. {
  175. };
  176. template<typename Iterator>
  177. struct ra_iter<Iterator, void_t<typename Iterator::iterator_concept>>
  178. : std::integral_constant<
  179. bool,
  180. std::is_base_of<
  181. std::random_access_iterator_tag,
  182. typename Iterator::iterator_concept>::value>
  183. {
  184. };
  185. template<typename Iterator, typename DifferenceType, typename = void>
  186. struct plus_eq : std::false_type
  187. {
  188. };
  189. template<typename Iterator, typename DifferenceType>
  190. struct plus_eq<
  191. Iterator,
  192. DifferenceType,
  193. void_t<decltype(
  194. std::declval<Iterator &>() += std::declval<DifferenceType>())>>
  195. : std::true_type
  196. {
  197. };
  198. template<
  199. typename D,
  200. typename IteratorConcept,
  201. typename ValueType,
  202. typename Reference,
  203. typename Pointer,
  204. typename DifferenceType>
  205. void derived_iterator(iterator_interface<
  206. D,
  207. IteratorConcept,
  208. ValueType,
  209. Reference,
  210. Pointer,
  211. DifferenceType> const &);
  212. }
  213. template<
  214. typename Derived,
  215. typename IteratorConcept,
  216. typename ValueType,
  217. typename Reference,
  218. typename Pointer,
  219. typename DifferenceType
  220. #ifndef BOOST_STL_INTERFACES_DOXYGEN
  221. ,
  222. typename E
  223. #endif
  224. >
  225. struct iterator_interface
  226. {
  227. #ifndef BOOST_STL_INTERFACES_DOXYGEN
  228. private:
  229. constexpr Derived & derived() noexcept
  230. {
  231. return static_cast<Derived &>(*this);
  232. }
  233. constexpr Derived const & derived() const noexcept
  234. {
  235. return static_cast<Derived const &>(*this);
  236. }
  237. template<typename T, typename U, bool UseBase>
  238. friend struct detail::common_eq;
  239. #endif
  240. public:
  241. using iterator_concept = IteratorConcept;
  242. using iterator_category = detail::concept_category_t<iterator_concept>;
  243. using value_type = std::remove_const_t<ValueType>;
  244. using reference = Reference;
  245. using pointer = detail::pointer_t<Pointer, iterator_concept>;
  246. using difference_type = DifferenceType;
  247. template<typename D = Derived>
  248. constexpr auto operator*() const
  249. noexcept(noexcept(*access::base(std::declval<D const &>())))
  250. -> decltype(*access::base(std::declval<D const &>()))
  251. {
  252. return *access::base(derived());
  253. }
  254. template<typename D = Derived>
  255. constexpr auto operator-> () const noexcept(
  256. noexcept(detail::make_pointer<pointer>(*std::declval<D const &>())))
  257. -> decltype(
  258. detail::make_pointer<pointer>(*std::declval<D const &>()))
  259. {
  260. return detail::make_pointer<pointer>(*derived());
  261. }
  262. template<typename D = Derived>
  263. constexpr auto operator[](difference_type i) const noexcept(noexcept(
  264. D(std::declval<D const &>()),
  265. std::declval<D &>() += i,
  266. *std::declval<D &>()))
  267. -> decltype(std::declval<D &>() += i, *std::declval<D &>())
  268. {
  269. D retval = derived();
  270. retval += i;
  271. return *retval;
  272. }
  273. template<
  274. typename D = Derived,
  275. typename Enable =
  276. std::enable_if_t<!v1_dtl::plus_eq<D, difference_type>::value>>
  277. constexpr auto
  278. operator++() noexcept(noexcept(++access::base(std::declval<D &>())))
  279. -> decltype(++access::base(std::declval<D &>()))
  280. {
  281. return ++access::base(derived());
  282. }
  283. template<typename D = Derived>
  284. constexpr auto operator++() noexcept(
  285. noexcept(std::declval<D &>() += difference_type(1)))
  286. -> decltype(
  287. std::declval<D &>() += difference_type(1), std::declval<D &>())
  288. {
  289. derived() += difference_type(1);
  290. return derived();
  291. }
  292. template<typename D = Derived>
  293. constexpr auto operator++(int)noexcept(
  294. noexcept(D(std::declval<D &>()), ++std::declval<D &>()))
  295. -> std::remove_reference_t<decltype(
  296. D(std::declval<D &>()),
  297. ++std::declval<D &>(),
  298. std::declval<D &>())>
  299. {
  300. D retval = derived();
  301. ++derived();
  302. return retval;
  303. }
  304. template<typename D = Derived>
  305. constexpr auto operator+=(difference_type n) noexcept(
  306. noexcept(access::base(std::declval<D &>()) += n))
  307. -> decltype(access::base(std::declval<D &>()) += n)
  308. {
  309. return access::base(derived()) += n;
  310. }
  311. template<typename D = Derived>
  312. constexpr auto operator+(difference_type i) const
  313. noexcept(noexcept(D(std::declval<D &>()), std::declval<D &>() += i))
  314. -> std::remove_reference_t<decltype(
  315. D(std::declval<D &>()),
  316. std::declval<D &>() += i,
  317. std::declval<D &>())>
  318. {
  319. D retval = derived();
  320. retval += i;
  321. return retval;
  322. }
  323. friend BOOST_STL_INTERFACES_HIDDEN_FRIEND_CONSTEXPR Derived
  324. operator+(difference_type i, Derived it) noexcept
  325. {
  326. return it + i;
  327. }
  328. template<
  329. typename D = Derived,
  330. typename Enable =
  331. std::enable_if_t<!v1_dtl::plus_eq<D, difference_type>::value>>
  332. constexpr auto
  333. operator--() noexcept(noexcept(--access::base(std::declval<D &>())))
  334. -> decltype(--access::base(std::declval<D &>()))
  335. {
  336. return --access::base(derived());
  337. }
  338. template<typename D = Derived>
  339. constexpr auto operator--() noexcept(noexcept(
  340. D(std::declval<D &>()), std::declval<D &>() += -difference_type(1)))
  341. -> decltype(
  342. std::declval<D &>() += -difference_type(1), std::declval<D &>())
  343. {
  344. derived() += -difference_type(1);
  345. return derived();
  346. }
  347. template<typename D = Derived>
  348. constexpr auto operator--(int)noexcept(
  349. noexcept(D(std::declval<D &>()), --std::declval<D &>()))
  350. -> std::remove_reference_t<decltype(
  351. D(std::declval<D &>()),
  352. --std::declval<D &>(),
  353. std::declval<D &>())>
  354. {
  355. D retval = derived();
  356. --derived();
  357. return retval;
  358. }
  359. template<typename D = Derived>
  360. constexpr D & operator-=(difference_type i) noexcept
  361. {
  362. derived() += -i;
  363. return derived();
  364. }
  365. template<typename D = Derived>
  366. constexpr auto operator-(D other) const noexcept(noexcept(
  367. access::base(std::declval<D const &>()) - access::base(other)))
  368. -> decltype(
  369. access::base(std::declval<D const &>()) - access::base(other))
  370. {
  371. return access::base(derived()) - access::base(other);
  372. }
  373. friend BOOST_STL_INTERFACES_HIDDEN_FRIEND_CONSTEXPR Derived
  374. operator-(Derived it, difference_type i) noexcept
  375. {
  376. Derived retval = it;
  377. retval += -i;
  378. return retval;
  379. }
  380. };
  381. /** Implementation of `operator==()`, implemented in terms of the iterator
  382. underlying IteratorInterface, for all iterators derived from
  383. `iterator_interface`, except those with an iterator category derived
  384. from `std::random_access_iterator_tag`. */
  385. template<
  386. typename IteratorInterface1,
  387. typename IteratorInterface2,
  388. typename Enable =
  389. std::enable_if_t<!v1_dtl::ra_iter<IteratorInterface1>::value>>
  390. constexpr auto
  391. operator==(IteratorInterface1 lhs, IteratorInterface2 rhs) noexcept
  392. -> decltype(
  393. access::base(std::declval<IteratorInterface1 &>()) ==
  394. access::base(std::declval<IteratorInterface2 &>()))
  395. {
  396. return access::base(lhs) == access::base(rhs);
  397. }
  398. /** Implementation of `operator==()` for all iterators derived from
  399. `iterator_interface` that have an iterator category derived from
  400. `std::random_access_iterator_tag`. */
  401. template<
  402. typename IteratorInterface1,
  403. typename IteratorInterface2,
  404. typename Enable =
  405. std::enable_if_t<v1_dtl::ra_iter<IteratorInterface1>::value>>
  406. constexpr auto
  407. operator==(IteratorInterface1 lhs, IteratorInterface2 rhs) noexcept(
  408. noexcept(detail::common_diff(lhs, rhs)))
  409. -> decltype(
  410. v1_dtl::derived_iterator(lhs), detail::common_diff(lhs, rhs) == 0)
  411. {
  412. return detail::common_diff(lhs, rhs) == 0;
  413. }
  414. /** Implementation of `operator!=()` for all iterators derived from
  415. `iterator_interface`. */
  416. template<typename IteratorInterface1, typename IteratorInterface2>
  417. constexpr auto operator!=(
  418. IteratorInterface1 lhs,
  419. IteratorInterface2 rhs) noexcept(noexcept(!(lhs == rhs)))
  420. -> decltype(v1_dtl::derived_iterator(lhs), !(lhs == rhs))
  421. {
  422. return !(lhs == rhs);
  423. }
  424. /** Implementation of `operator<()` for all iterators derived from
  425. `iterator_interface` that have an iterator category derived from
  426. `std::random_access_iterator_tag`. */
  427. template<typename IteratorInterface1, typename IteratorInterface2>
  428. constexpr auto
  429. operator<(IteratorInterface1 lhs, IteratorInterface2 rhs) noexcept(
  430. noexcept(detail::common_diff(lhs, rhs)))
  431. -> decltype(
  432. v1_dtl::derived_iterator(lhs), detail::common_diff(lhs, rhs) < 0)
  433. {
  434. return detail::common_diff(lhs, rhs) < 0;
  435. }
  436. /** Implementation of `operator<=()` for all iterators derived from
  437. `iterator_interface` that have an iterator category derived from
  438. `std::random_access_iterator_tag`. */
  439. template<typename IteratorInterface1, typename IteratorInterface2>
  440. constexpr auto
  441. operator<=(IteratorInterface1 lhs, IteratorInterface2 rhs) noexcept(
  442. noexcept(detail::common_diff(lhs, rhs)))
  443. -> decltype(
  444. v1_dtl::derived_iterator(lhs), detail::common_diff(lhs, rhs) <= 0)
  445. {
  446. return detail::common_diff(lhs, rhs) <= 0;
  447. }
  448. /** Implementation of `operator>()` for all iterators derived from
  449. `iterator_interface` that have an iterator category derived from
  450. `std::random_access_iterator_tag`. */
  451. template<typename IteratorInterface1, typename IteratorInterface2>
  452. constexpr auto
  453. operator>(IteratorInterface1 lhs, IteratorInterface2 rhs) noexcept(
  454. noexcept(detail::common_diff(lhs, rhs)))
  455. -> decltype(
  456. v1_dtl::derived_iterator(lhs), detail::common_diff(lhs, rhs) > 0)
  457. {
  458. return detail::common_diff(lhs, rhs) > 0;
  459. }
  460. /** Implementation of `operator>=()` for all iterators derived from
  461. `iterator_interface` that have an iterator category derived from
  462. `std::random_access_iterator_tag`. */
  463. template<typename IteratorInterface1, typename IteratorInterface2>
  464. constexpr auto
  465. operator>=(IteratorInterface1 lhs, IteratorInterface2 rhs) noexcept(
  466. noexcept(detail::common_diff(lhs, rhs)))
  467. -> decltype(
  468. v1_dtl::derived_iterator(lhs), detail::common_diff(lhs, rhs) >= 0)
  469. {
  470. return detail::common_diff(lhs, rhs) >= 0;
  471. }
  472. /** A template alias useful for defining proxy iterators. \see
  473. `iterator_interface`. */
  474. template<
  475. typename Derived,
  476. typename IteratorConcept,
  477. typename ValueType,
  478. typename Reference = ValueType,
  479. typename DifferenceType = std::ptrdiff_t>
  480. using proxy_iterator_interface = iterator_interface<
  481. Derived,
  482. IteratorConcept,
  483. ValueType,
  484. Reference,
  485. proxy_arrow_result<Reference>,
  486. DifferenceType>;
  487. }}}
  488. #if 201703L < __cplusplus && defined(__cpp_lib_ranges)
  489. namespace boost { namespace stl_interfaces { namespace v2 { namespace detail {
  490. template<typename Iterator>
  491. struct iter_concept;
  492. template<typename Iterator>
  493. requires requires
  494. {
  495. typename std::iterator_traits<Iterator>::iterator_concept;
  496. }
  497. struct iter_concept<Iterator>
  498. {
  499. using type = typename std::iterator_traits<Iterator>::iterator_concept;
  500. };
  501. template<typename Iterator>
  502. requires(
  503. !requires {
  504. typename std::iterator_traits<Iterator>::iterator_concept;
  505. } &&
  506. requires {
  507. typename std::iterator_traits<Iterator>::iterator_category;
  508. }) struct iter_concept<Iterator>
  509. {
  510. using type = typename std::iterator_traits<Iterator>::iterator_category;
  511. };
  512. template<typename Iterator>
  513. requires(
  514. !requires {
  515. typename std::iterator_traits<Iterator>::iterator_concept;
  516. } &&
  517. !requires {
  518. typename std::iterator_traits<Iterator>::iterator_category;
  519. }) struct iter_concept<Iterator>
  520. {
  521. using type = std::random_access_iterator_tag;
  522. };
  523. template<typename Iterator>
  524. struct iter_concept
  525. {};
  526. template<typename Iterator>
  527. using iter_concept_t = typename iter_concept<Iterator>::type;
  528. }}}}
  529. #endif
  530. #ifdef BOOST_STL_INTERFACES_DOXYGEN
  531. /** `static_asserts` that type `type` models concept `concept_name`. This is
  532. useful for checking that an iterator, view, etc. that you write using one
  533. of the *`_interface` templates models the right C++ concept.
  534. For example: `BOOST_STL_INTERFACES_STATIC_ASSERT_CONCEPT(my_iter,
  535. std::input_iterator)`.
  536. \note This macro expands to nothing when `__cpp_lib_concepts` is not
  537. defined. */
  538. #define BOOST_STL_INTERFACES_STATIC_ASSERT_CONCEPT(type, concept_name)
  539. /** `static_asserts` that the types of all typedefs in
  540. `std::iterator_traits<iter>` match the remaining macro parameters. This
  541. is useful for checking that an iterator you write using
  542. `iterator_interface` has the correct iterator traits.
  543. For example: `BOOST_STL_INTERFACES_STATIC_ASSERT_ITERATOR_TRAITS(my_iter,
  544. std::input_iterator_tag, std::input_iterator_tag, int, int &, int *, std::ptrdiff_t)`.
  545. \note This macro ignores the `concept` parameter when `__cpp_lib_concepts`
  546. is not defined. */
  547. #define BOOST_STL_INTERFACES_STATIC_ASSERT_ITERATOR_TRAITS( \
  548. iter, category, concept, value_type, reference, pointer, difference_type)
  549. #else
  550. #define BOOST_STL_INTERFACES_STATIC_ASSERT_ITERATOR_CONCEPT_IMPL( \
  551. type, concept_name) \
  552. static_assert(concept_name<type>, "");
  553. #define BOOST_STL_INTERFACES_STATIC_ASSERT_CONCEPT(iter, concept_name)
  554. #define BOOST_STL_INTERFACES_STATIC_ASSERT_ITERATOR_TRAITS_IMPL( \
  555. iter, category, value_t, ref, ptr, diff_t) \
  556. static_assert( \
  557. std::is_same< \
  558. typename std::iterator_traits<iter>::iterator_category, \
  559. category>::value, \
  560. ""); \
  561. static_assert( \
  562. std::is_same< \
  563. typename std::iterator_traits<iter>::value_type, \
  564. value_t>::value, \
  565. ""); \
  566. static_assert( \
  567. std::is_same<typename std::iterator_traits<iter>::reference, ref>:: \
  568. value, \
  569. ""); \
  570. static_assert( \
  571. std::is_same<typename std::iterator_traits<iter>::pointer, ptr>:: \
  572. value, \
  573. ""); \
  574. static_assert( \
  575. std::is_same< \
  576. typename std::iterator_traits<iter>::difference_type, \
  577. diff_t>::value, \
  578. "");
  579. #if 201703L < __cplusplus && defined(__cpp_lib_ranges)
  580. #define BOOST_STL_INTERFACES_STATIC_ASSERT_ITERATOR_TRAITS( \
  581. iter, category, concept, value_type, reference, pointer, difference_type) \
  582. static_assert( \
  583. std::is_same_v< \
  584. boost::stl_interfaces::v2::detail::iter_concept_t<iter>, \
  585. concept>, \
  586. ""); \
  587. BOOST_STL_INTERFACES_STATIC_ASSERT_ITERATOR_TRAITS_IMPL( \
  588. iter, category, value_type, reference, pointer, difference_type)
  589. #else
  590. #define BOOST_STL_INTERFACES_STATIC_ASSERT_ITERATOR_TRAITS( \
  591. iter, category, concept, value_type, reference, pointer, difference_type) \
  592. BOOST_STL_INTERFACES_STATIC_ASSERT_ITERATOR_TRAITS_IMPL( \
  593. iter, category, value_type, reference, pointer, difference_type)
  594. #endif
  595. #endif
  596. #endif