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