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