Line data Source code
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 :
10 : #include <type_traits>
11 :
12 : #include <boost/core/use_default.hpp>
13 :
14 : #include <boost/iterator/iterator_categories.hpp>
15 : #include <boost/iterator/iterator_facade.hpp>
16 : #include <boost/iterator/iterator_traits.hpp>
17 : #include <boost/iterator/enable_if_convertible.hpp> // for backward compatibility; remove once downstream users are updated
18 : #include <boost/iterator/detail/eval_if_default.hpp>
19 :
20 : #include <boost/iterator/detail/config_def.hpp>
21 :
22 : namespace boost {
23 : namespace iterators {
24 :
25 : // Used as a default template argument internally, merely to
26 : // indicate "use the default", this can also be passed by users
27 : // explicitly in order to specify that the default should be used.
28 : using boost::use_default;
29 :
30 : namespace detail {
31 :
32 : // A metafunction which computes an iterator_adaptor's base class,
33 : // a specialization of iterator_facade.
34 : template<
35 : typename Derived,
36 : typename Base,
37 : typename Value,
38 : typename Traversal,
39 : typename Reference,
40 : typename Difference
41 : >
42 : using iterator_adaptor_base_t = iterator_facade<
43 : Derived,
44 :
45 : #ifdef BOOST_ITERATOR_REF_CONSTNESS_KILLS_WRITABILITY
46 : detail::eval_if_default_t<
47 : Value,
48 : detail::eval_if_default<
49 : Reference,
50 : iterator_value< Base >,
51 : std::remove_reference< Reference >
52 : >
53 : >,
54 : #else
55 : detail::eval_if_default_t<
56 : Value,
57 : iterator_value< Base >
58 : >,
59 : #endif
60 :
61 : detail::eval_if_default_t<
62 : Traversal,
63 : iterator_traversal< Base >
64 : >,
65 :
66 : detail::eval_if_default_t<
67 : Reference,
68 : detail::eval_if_default<
69 : Value,
70 : iterator_reference< Base >,
71 : std::add_lvalue_reference< Value >
72 : >
73 : >,
74 :
75 : detail::eval_if_default_t<
76 : Difference,
77 : iterator_difference< Base >
78 : >
79 : >;
80 :
81 : } // namespace detail
82 :
83 : //
84 : // Iterator Adaptor
85 : //
86 : // The parameter ordering changed slightly with respect to former
87 : // versions of iterator_adaptor The idea is that when the user needs
88 : // to fiddle with the reference type it is highly likely that the
89 : // iterator category has to be adjusted as well. Any of the
90 : // following four template arguments may be omitted or explicitly
91 : // replaced by use_default.
92 : //
93 : // Value - if supplied, the value_type of the resulting iterator, unless
94 : // const. If const, a conforming compiler strips constness for the
95 : // value_type. If not supplied, iterator_traits<Base>::value_type is used
96 : //
97 : // Category - the traversal category of the resulting iterator. If not
98 : // supplied, iterator_traversal<Base>::type is used.
99 : //
100 : // Reference - the reference type of the resulting iterator, and in
101 : // particular, the result type of operator*(). If not supplied but
102 : // Value is supplied, Value& is used. Otherwise
103 : // iterator_traits<Base>::reference is used.
104 : //
105 : // Difference - the difference_type of the resulting iterator. If not
106 : // supplied, iterator_traits<Base>::difference_type is used.
107 : //
108 : template<
109 : typename Derived,
110 : typename Base,
111 : typename Value = use_default,
112 : typename Traversal = use_default,
113 : typename Reference = use_default,
114 : typename Difference = use_default
115 : >
116 : class iterator_adaptor :
117 : public detail::iterator_adaptor_base_t<
118 : Derived, Base, Value, Traversal, Reference, Difference
119 : >
120 : {
121 : friend class iterator_core_access;
122 :
123 : protected:
124 : using super_t = detail::iterator_adaptor_base_t<
125 : Derived, Base, Value, Traversal, Reference, Difference
126 : >;
127 :
128 : public:
129 : using base_type = Base;
130 :
131 : iterator_adaptor() = default;
132 :
133 42217 : explicit iterator_adaptor(Base const& iter) :
134 42217 : m_iterator(iter)
135 : {
136 42217 : }
137 :
138 43184 : base_type const& base() const { return m_iterator; }
139 :
140 : protected:
141 : // for convenience in derived classes
142 : using iterator_adaptor_ = iterator_adaptor< Derived, Base, Value, Traversal, Reference, Difference >;
143 :
144 : //
145 : // lvalue access to the Base object for Derived
146 : //
147 27799 : Base& base_reference() { return m_iterator; }
148 61040 : Base const& base_reference() const { return m_iterator; }
149 :
150 : private:
151 : //
152 : // Core iterator interface for iterator_facade. This is private
153 : // to prevent temptation for Derived classes to use it, which
154 : // will often result in an error. Derived classes should use
155 : // base_reference(), above, to get direct access to m_iterator.
156 : //
157 : typename super_t::reference dereference() const { return *m_iterator; }
158 :
159 : template< typename OtherDerived, typename OtherIterator, typename V, typename C, typename R, typename D >
160 39096 : bool equal(iterator_adaptor< OtherDerived, OtherIterator, V, C, R, D > const& x) const
161 : {
162 : // Maybe readd with same_distance
163 : // BOOST_STATIC_ASSERT(
164 : // (detail::same_category_and_difference<Derived,OtherDerived>::value)
165 : // );
166 39096 : return m_iterator == x.base();
167 : }
168 :
169 : using my_traversal = typename iterator_category_to_traversal< typename super_t::iterator_category >::type;
170 :
171 : void advance(typename super_t::difference_type n)
172 : {
173 : static_assert(detail::is_traversal_at_least< my_traversal, random_access_traversal_tag >::value,
174 : "Iterator must support random access traversal.");
175 : m_iterator += n;
176 : }
177 :
178 4088 : void increment() { ++m_iterator; }
179 :
180 : void decrement()
181 : {
182 : static_assert(detail::is_traversal_at_least< my_traversal, bidirectional_traversal_tag >::value,
183 : "Iterator must support bidirectional traversal.");
184 : --m_iterator;
185 : }
186 :
187 : template< typename OtherDerived, typename OtherIterator, typename V, typename C, typename R, typename D >
188 : typename super_t::difference_type distance_to(iterator_adaptor< OtherDerived, OtherIterator, V, C, R, D > const& y) const
189 : {
190 : static_assert(detail::is_traversal_at_least< my_traversal, random_access_traversal_tag >::value,
191 : "Super iterator must support random access traversal.");
192 : // Maybe readd with same_distance
193 : // BOOST_STATIC_ASSERT(
194 : // (detail::same_category_and_difference<Derived,OtherDerived>::value)
195 : // );
196 : return y.base() - m_iterator;
197 : }
198 :
199 : private: // data members
200 : Base m_iterator;
201 : };
202 :
203 : } // namespace iterators
204 :
205 : using iterators::iterator_adaptor;
206 :
207 : } // namespace boost
208 :
209 : #include <boost/iterator/detail/config_undef.hpp>
210 :
211 : #endif // BOOST_ITERATOR_ADAPTOR_23022003THW_HPP
|