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