iterator_adaptor.hpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359
  1. // (C) Copyright David Abrahams 2002.
  2. // (C) Copyright Jeremy Siek 2002.
  3. // (C) Copyright Thomas Witt 2002.
  4. // Distributed under the Boost Software License, Version 1.0. (See
  5. // accompanying file LICENSE_1_0.txt or copy at
  6. // http://www.boost.org/LICENSE_1_0.txt)
  7. #ifndef BOOST_ITERATOR_ADAPTOR_23022003THW_HPP
  8. #define BOOST_ITERATOR_ADAPTOR_23022003THW_HPP
  9. #include <boost/static_assert.hpp>
  10. #include <boost/core/use_default.hpp>
  11. #include <boost/iterator/iterator_categories.hpp>
  12. #include <boost/iterator/iterator_facade.hpp>
  13. #include <boost/iterator/detail/enable_if.hpp>
  14. #include <boost/mpl/and.hpp>
  15. #include <boost/mpl/not.hpp>
  16. #include <boost/mpl/or.hpp>
  17. #include <boost/type_traits/is_same.hpp>
  18. #include <boost/type_traits/is_convertible.hpp>
  19. #ifdef BOOST_ITERATOR_REF_CONSTNESS_KILLS_WRITABILITY
  20. # include <boost/type_traits/remove_reference.hpp>
  21. #endif
  22. #include <boost/type_traits/add_reference.hpp>
  23. #include <boost/iterator/detail/config_def.hpp>
  24. #include <boost/iterator/iterator_traits.hpp>
  25. namespace boost {
  26. namespace iterators {
  27. // Used as a default template argument internally, merely to
  28. // indicate "use the default", this can also be passed by users
  29. // explicitly in order to specify that the default should be used.
  30. using boost::use_default;
  31. } // namespace iterators
  32. // the incompleteness of use_default causes massive problems for
  33. // is_convertible (naturally). This workaround is fortunately not
  34. // needed for vc6/vc7.
  35. template<class To>
  36. struct is_convertible<use_default,To>
  37. : mpl::false_ {};
  38. namespace iterators {
  39. namespace detail
  40. {
  41. //
  42. // Result type used in enable_if_convertible meta function.
  43. // This can be an incomplete type, as only pointers to
  44. // enable_if_convertible< ... >::type are used.
  45. // We could have used void for this, but conversion to
  46. // void* is just to easy.
  47. //
  48. struct enable_type;
  49. }
  50. //
  51. // enable_if for use in adapted iterators constructors.
  52. //
  53. // In order to provide interoperability between adapted constant and
  54. // mutable iterators, adapted iterators will usually provide templated
  55. // conversion constructors of the following form
  56. //
  57. // template <class BaseIterator>
  58. // class adapted_iterator :
  59. // public iterator_adaptor< adapted_iterator<Iterator>, Iterator >
  60. // {
  61. // public:
  62. //
  63. // ...
  64. //
  65. // template <class OtherIterator>
  66. // adapted_iterator(
  67. // OtherIterator const& it
  68. // , typename enable_if_convertible<OtherIterator, Iterator>::type* = 0);
  69. //
  70. // ...
  71. // };
  72. //
  73. // enable_if_convertible is used to remove those overloads from the overload
  74. // set that cannot be instantiated. For all practical purposes only overloads
  75. // for constant/mutable interaction will remain. This has the advantage that
  76. // meta functions like boost::is_convertible do not return false positives,
  77. // as they can only look at the signature of the conversion constructor
  78. // and not at the actual instantiation.
  79. //
  80. // enable_if_interoperable can be safely used in user code. It falls back to
  81. // always enabled for compilers that don't support enable_if or is_convertible.
  82. // There is no need for compiler specific workarounds in user code.
  83. //
  84. // The operators implementation relies on boost::is_convertible not returning
  85. // false positives for user/library defined iterator types. See comments
  86. // on operator implementation for consequences.
  87. //
  88. # if defined(BOOST_NO_IS_CONVERTIBLE) || defined(BOOST_NO_SFINAE)
  89. template <class From, class To>
  90. struct enable_if_convertible
  91. {
  92. typedef boost::iterators::detail::enable_type type;
  93. };
  94. # elif BOOST_WORKAROUND(_MSC_FULL_VER, BOOST_TESTED_AT(13102292))
  95. // For some reason vc7.1 needs us to "cut off" instantiation
  96. // of is_convertible in a few cases.
  97. template<typename From, typename To>
  98. struct enable_if_convertible
  99. : iterators::enable_if<
  100. mpl::or_<
  101. is_same<From,To>
  102. , is_convertible<From, To>
  103. >
  104. , boost::iterators::detail::enable_type
  105. >
  106. {};
  107. # else
  108. template<typename From, typename To>
  109. struct enable_if_convertible
  110. : iterators::enable_if<
  111. is_convertible<From, To>
  112. , boost::iterators::detail::enable_type
  113. >
  114. {};
  115. # endif
  116. //
  117. // Default template argument handling for iterator_adaptor
  118. //
  119. namespace detail
  120. {
  121. // If T is use_default, return the result of invoking
  122. // DefaultNullaryFn, otherwise return T.
  123. template <class T, class DefaultNullaryFn>
  124. struct ia_dflt_help
  125. : mpl::eval_if<
  126. is_same<T, use_default>
  127. , DefaultNullaryFn
  128. , mpl::identity<T>
  129. >
  130. {
  131. };
  132. // A metafunction which computes an iterator_adaptor's base class,
  133. // a specialization of iterator_facade.
  134. template <
  135. class Derived
  136. , class Base
  137. , class Value
  138. , class Traversal
  139. , class Reference
  140. , class Difference
  141. >
  142. struct iterator_adaptor_base
  143. {
  144. typedef iterator_facade<
  145. Derived
  146. # ifdef BOOST_ITERATOR_REF_CONSTNESS_KILLS_WRITABILITY
  147. , typename boost::iterators::detail::ia_dflt_help<
  148. Value
  149. , mpl::eval_if<
  150. is_same<Reference,use_default>
  151. , iterator_value<Base>
  152. , remove_reference<Reference>
  153. >
  154. >::type
  155. # else
  156. , typename boost::iterators::detail::ia_dflt_help<
  157. Value, iterator_value<Base>
  158. >::type
  159. # endif
  160. , typename boost::iterators::detail::ia_dflt_help<
  161. Traversal
  162. , iterator_traversal<Base>
  163. >::type
  164. , typename boost::iterators::detail::ia_dflt_help<
  165. Reference
  166. , mpl::eval_if<
  167. is_same<Value,use_default>
  168. , iterator_reference<Base>
  169. , add_reference<Value>
  170. >
  171. >::type
  172. , typename boost::iterators::detail::ia_dflt_help<
  173. Difference, iterator_difference<Base>
  174. >::type
  175. >
  176. type;
  177. };
  178. // workaround for aC++ CR JAGaf33512
  179. template <class Tr1, class Tr2>
  180. inline void iterator_adaptor_assert_traversal ()
  181. {
  182. BOOST_STATIC_ASSERT((is_convertible<Tr1, Tr2>::value));
  183. }
  184. }
  185. //
  186. // Iterator Adaptor
  187. //
  188. // The parameter ordering changed slightly with respect to former
  189. // versions of iterator_adaptor The idea is that when the user needs
  190. // to fiddle with the reference type it is highly likely that the
  191. // iterator category has to be adjusted as well. Any of the
  192. // following four template arguments may be ommitted or explicitly
  193. // replaced by use_default.
  194. //
  195. // Value - if supplied, the value_type of the resulting iterator, unless
  196. // const. If const, a conforming compiler strips constness for the
  197. // value_type. If not supplied, iterator_traits<Base>::value_type is used
  198. //
  199. // Category - the traversal category of the resulting iterator. If not
  200. // supplied, iterator_traversal<Base>::type is used.
  201. //
  202. // Reference - the reference type of the resulting iterator, and in
  203. // particular, the result type of operator*(). If not supplied but
  204. // Value is supplied, Value& is used. Otherwise
  205. // iterator_traits<Base>::reference is used.
  206. //
  207. // Difference - the difference_type of the resulting iterator. If not
  208. // supplied, iterator_traits<Base>::difference_type is used.
  209. //
  210. template <
  211. class Derived
  212. , class Base
  213. , class Value = use_default
  214. , class Traversal = use_default
  215. , class Reference = use_default
  216. , class Difference = use_default
  217. >
  218. class iterator_adaptor
  219. : public boost::iterators::detail::iterator_adaptor_base<
  220. Derived, Base, Value, Traversal, Reference, Difference
  221. >::type
  222. {
  223. friend class iterator_core_access;
  224. protected:
  225. typedef typename boost::iterators::detail::iterator_adaptor_base<
  226. Derived, Base, Value, Traversal, Reference, Difference
  227. >::type super_t;
  228. public:
  229. iterator_adaptor() {}
  230. explicit iterator_adaptor(Base const &iter)
  231. : m_iterator(iter)
  232. {
  233. }
  234. typedef Base base_type;
  235. Base const& base() const
  236. { return m_iterator; }
  237. protected:
  238. // for convenience in derived classes
  239. typedef iterator_adaptor<Derived,Base,Value,Traversal,Reference,Difference> iterator_adaptor_;
  240. //
  241. // lvalue access to the Base object for Derived
  242. //
  243. Base const& base_reference() const
  244. { return m_iterator; }
  245. Base& base_reference()
  246. { return m_iterator; }
  247. private:
  248. //
  249. // Core iterator interface for iterator_facade. This is private
  250. // to prevent temptation for Derived classes to use it, which
  251. // will often result in an error. Derived classes should use
  252. // base_reference(), above, to get direct access to m_iterator.
  253. //
  254. typename super_t::reference dereference() const
  255. { return *m_iterator; }
  256. template <
  257. class OtherDerived, class OtherIterator, class V, class C, class R, class D
  258. >
  259. bool equal(iterator_adaptor<OtherDerived, OtherIterator, V, C, R, D> const& x) const
  260. {
  261. // Maybe readd with same_distance
  262. // BOOST_STATIC_ASSERT(
  263. // (detail::same_category_and_difference<Derived,OtherDerived>::value)
  264. // );
  265. return m_iterator == x.base();
  266. }
  267. typedef typename iterator_category_to_traversal<
  268. typename super_t::iterator_category
  269. >::type my_traversal;
  270. # define BOOST_ITERATOR_ADAPTOR_ASSERT_TRAVERSAL(cat) \
  271. boost::iterators::detail::iterator_adaptor_assert_traversal<my_traversal, cat>();
  272. void advance(typename super_t::difference_type n)
  273. {
  274. BOOST_ITERATOR_ADAPTOR_ASSERT_TRAVERSAL(random_access_traversal_tag)
  275. m_iterator += n;
  276. }
  277. void increment() { ++m_iterator; }
  278. void decrement()
  279. {
  280. BOOST_ITERATOR_ADAPTOR_ASSERT_TRAVERSAL(bidirectional_traversal_tag)
  281. --m_iterator;
  282. }
  283. template <
  284. class OtherDerived, class OtherIterator, class V, class C, class R, class D
  285. >
  286. typename super_t::difference_type distance_to(
  287. iterator_adaptor<OtherDerived, OtherIterator, V, C, R, D> const& y) const
  288. {
  289. BOOST_ITERATOR_ADAPTOR_ASSERT_TRAVERSAL(random_access_traversal_tag)
  290. // Maybe readd with same_distance
  291. // BOOST_STATIC_ASSERT(
  292. // (detail::same_category_and_difference<Derived,OtherDerived>::value)
  293. // );
  294. return y.base() - m_iterator;
  295. }
  296. # undef BOOST_ITERATOR_ADAPTOR_ASSERT_TRAVERSAL
  297. private: // data members
  298. Base m_iterator;
  299. };
  300. } // namespace iterators
  301. using iterators::iterator_adaptor;
  302. using iterators::enable_if_convertible;
  303. } // namespace boost
  304. #include <boost/iterator/detail/config_undef.hpp>
  305. #endif // BOOST_ITERATOR_ADAPTOR_23022003THW_HPP