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