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_FACADE_23022003THW_HPP
|
Chris@16
|
8 #define BOOST_ITERATOR_FACADE_23022003THW_HPP
|
Chris@16
|
9
|
Chris@101
|
10 #include <boost/config.hpp>
|
Chris@16
|
11 #include <boost/iterator.hpp>
|
Chris@16
|
12 #include <boost/iterator/interoperable.hpp>
|
Chris@16
|
13 #include <boost/iterator/iterator_traits.hpp>
|
Chris@101
|
14 #include <boost/iterator/iterator_categories.hpp>
|
Chris@16
|
15
|
Chris@16
|
16 #include <boost/iterator/detail/facade_iterator_category.hpp>
|
Chris@16
|
17 #include <boost/iterator/detail/enable_if.hpp>
|
Chris@16
|
18
|
Chris@16
|
19 #include <boost/static_assert.hpp>
|
Chris@16
|
20 #include <boost/utility/addressof.hpp>
|
Chris@16
|
21
|
Chris@16
|
22 #include <boost/type_traits/is_same.hpp>
|
Chris@16
|
23 #include <boost/type_traits/add_const.hpp>
|
Chris@16
|
24 #include <boost/type_traits/add_pointer.hpp>
|
Chris@16
|
25 #include <boost/type_traits/remove_const.hpp>
|
Chris@16
|
26 #include <boost/type_traits/remove_reference.hpp>
|
Chris@16
|
27 #include <boost/type_traits/is_convertible.hpp>
|
Chris@16
|
28 #include <boost/type_traits/is_pod.hpp>
|
Chris@16
|
29
|
Chris@16
|
30 #include <boost/mpl/eval_if.hpp>
|
Chris@16
|
31 #include <boost/mpl/if.hpp>
|
Chris@16
|
32 #include <boost/mpl/or.hpp>
|
Chris@16
|
33 #include <boost/mpl/and.hpp>
|
Chris@16
|
34 #include <boost/mpl/not.hpp>
|
Chris@16
|
35 #include <boost/mpl/always.hpp>
|
Chris@16
|
36 #include <boost/mpl/apply.hpp>
|
Chris@16
|
37 #include <boost/mpl/identity.hpp>
|
Chris@16
|
38
|
Chris@16
|
39 #include <boost/iterator/detail/config_def.hpp> // this goes last
|
Chris@16
|
40
|
Chris@101
|
41 namespace boost {
|
Chris@101
|
42 namespace iterators {
|
Chris@101
|
43
|
Chris@16
|
44 // This forward declaration is required for the friend declaration
|
Chris@16
|
45 // in iterator_core_access
|
Chris@16
|
46 template <class I, class V, class TC, class R, class D> class iterator_facade;
|
Chris@16
|
47
|
Chris@16
|
48 namespace detail
|
Chris@16
|
49 {
|
Chris@16
|
50 // A binary metafunction class that always returns bool. VC6
|
Chris@16
|
51 // ICEs on mpl::always<bool>, probably because of the default
|
Chris@16
|
52 // parameters.
|
Chris@16
|
53 struct always_bool2
|
Chris@16
|
54 {
|
Chris@16
|
55 template <class T, class U>
|
Chris@16
|
56 struct apply
|
Chris@16
|
57 {
|
Chris@16
|
58 typedef bool type;
|
Chris@16
|
59 };
|
Chris@16
|
60 };
|
Chris@16
|
61
|
Chris@101
|
62 // The type trait checks if the category or traversal is at least as advanced as the specified required traversal
|
Chris@101
|
63 template< typename CategoryOrTraversal, typename Required >
|
Chris@101
|
64 struct is_traversal_at_least :
|
Chris@101
|
65 public boost::is_convertible< typename iterator_category_to_traversal< CategoryOrTraversal >::type, Required >
|
Chris@101
|
66 {};
|
Chris@101
|
67
|
Chris@16
|
68 //
|
Chris@16
|
69 // enable if for use in operator implementation.
|
Chris@16
|
70 //
|
Chris@16
|
71 template <
|
Chris@16
|
72 class Facade1
|
Chris@16
|
73 , class Facade2
|
Chris@16
|
74 , class Return
|
Chris@16
|
75 >
|
Chris@101
|
76 struct enable_if_interoperable :
|
Chris@101
|
77 public boost::iterators::enable_if<
|
Chris@101
|
78 is_interoperable< Facade1, Facade2 >
|
Chris@101
|
79 , Return
|
Chris@101
|
80 >
|
Chris@101
|
81 {};
|
Chris@101
|
82
|
Chris@101
|
83 //
|
Chris@101
|
84 // enable if for use in implementation of operators specific for random access traversal.
|
Chris@101
|
85 //
|
Chris@101
|
86 template <
|
Chris@101
|
87 class Facade1
|
Chris@101
|
88 , class Facade2
|
Chris@101
|
89 , class Return
|
Chris@101
|
90 >
|
Chris@101
|
91 struct enable_if_interoperable_and_random_access_traversal :
|
Chris@101
|
92 public boost::iterators::enable_if<
|
Chris@101
|
93 mpl::and_<
|
Chris@101
|
94 is_interoperable< Facade1, Facade2 >
|
Chris@101
|
95 , is_traversal_at_least< typename iterator_category< Facade1 >::type, random_access_traversal_tag >
|
Chris@101
|
96 , is_traversal_at_least< typename iterator_category< Facade2 >::type, random_access_traversal_tag >
|
Chris@16
|
97 >
|
Chris@16
|
98 , Return
|
Chris@16
|
99 >
|
Chris@16
|
100 {};
|
Chris@16
|
101
|
Chris@16
|
102 //
|
Chris@16
|
103 // Generates associated types for an iterator_facade with the
|
Chris@16
|
104 // given parameters.
|
Chris@16
|
105 //
|
Chris@16
|
106 template <
|
Chris@16
|
107 class ValueParam
|
Chris@16
|
108 , class CategoryOrTraversal
|
Chris@101
|
109 , class Reference
|
Chris@16
|
110 , class Difference
|
Chris@16
|
111 >
|
Chris@16
|
112 struct iterator_facade_types
|
Chris@16
|
113 {
|
Chris@16
|
114 typedef typename facade_iterator_category<
|
Chris@16
|
115 CategoryOrTraversal, ValueParam, Reference
|
Chris@16
|
116 >::type iterator_category;
|
Chris@101
|
117
|
Chris@16
|
118 typedef typename remove_const<ValueParam>::type value_type;
|
Chris@101
|
119
|
Chris@16
|
120 // Not the real associated pointer type
|
Chris@16
|
121 typedef typename mpl::eval_if<
|
Chris@101
|
122 boost::iterators::detail::iterator_writability_disabled<ValueParam,Reference>
|
Chris@16
|
123 , add_pointer<const value_type>
|
Chris@16
|
124 , add_pointer<value_type>
|
Chris@16
|
125 >::type pointer;
|
Chris@101
|
126
|
Chris@16
|
127 # if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \
|
Chris@16
|
128 && (BOOST_WORKAROUND(_STLPORT_VERSION, BOOST_TESTED_AT(0x452)) \
|
Chris@16
|
129 || BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, BOOST_TESTED_AT(310))) \
|
Chris@16
|
130 || BOOST_WORKAROUND(BOOST_RWSTD_VER, BOOST_TESTED_AT(0x20101)) \
|
Chris@16
|
131 || BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, <= 310)
|
Chris@16
|
132
|
Chris@16
|
133 // To interoperate with some broken library/compiler
|
Chris@16
|
134 // combinations, user-defined iterators must be derived from
|
Chris@16
|
135 // std::iterator. It is possible to implement a standard
|
Chris@16
|
136 // library for broken compilers without this limitation.
|
Chris@16
|
137 # define BOOST_ITERATOR_FACADE_NEEDS_ITERATOR_BASE 1
|
Chris@16
|
138
|
Chris@16
|
139 typedef
|
Chris@16
|
140 iterator<iterator_category, value_type, Difference, pointer, Reference>
|
Chris@16
|
141 base;
|
Chris@16
|
142 # endif
|
Chris@16
|
143 };
|
Chris@16
|
144
|
Chris@16
|
145 // iterators whose dereference operators reference the same value
|
Chris@16
|
146 // for all iterators into the same sequence (like many input
|
Chris@16
|
147 // iterators) need help with their postfix ++: the referenced
|
Chris@16
|
148 // value must be read and stored away before the increment occurs
|
Chris@16
|
149 // so that *a++ yields the originally referenced element and not
|
Chris@16
|
150 // the next one.
|
Chris@16
|
151 template <class Iterator>
|
Chris@16
|
152 class postfix_increment_proxy
|
Chris@16
|
153 {
|
Chris@16
|
154 typedef typename iterator_value<Iterator>::type value_type;
|
Chris@16
|
155 public:
|
Chris@16
|
156 explicit postfix_increment_proxy(Iterator const& x)
|
Chris@16
|
157 : stored_value(*x)
|
Chris@16
|
158 {}
|
Chris@16
|
159
|
Chris@16
|
160 // Returning a mutable reference allows nonsense like
|
Chris@16
|
161 // (*r++).mutate(), but it imposes fewer assumptions about the
|
Chris@16
|
162 // behavior of the value_type. In particular, recall that
|
Chris@16
|
163 // (*r).mutate() is legal if operator* returns by value.
|
Chris@16
|
164 value_type&
|
Chris@16
|
165 operator*() const
|
Chris@16
|
166 {
|
Chris@16
|
167 return this->stored_value;
|
Chris@16
|
168 }
|
Chris@16
|
169 private:
|
Chris@16
|
170 mutable value_type stored_value;
|
Chris@16
|
171 };
|
Chris@101
|
172
|
Chris@16
|
173 //
|
Chris@16
|
174 // In general, we can't determine that such an iterator isn't
|
Chris@16
|
175 // writable -- we also need to store a copy of the old iterator so
|
Chris@16
|
176 // that it can be written into.
|
Chris@16
|
177 template <class Iterator>
|
Chris@16
|
178 class writable_postfix_increment_proxy
|
Chris@16
|
179 {
|
Chris@16
|
180 typedef typename iterator_value<Iterator>::type value_type;
|
Chris@16
|
181 public:
|
Chris@16
|
182 explicit writable_postfix_increment_proxy(Iterator const& x)
|
Chris@16
|
183 : stored_value(*x)
|
Chris@16
|
184 , stored_iterator(x)
|
Chris@16
|
185 {}
|
Chris@16
|
186
|
Chris@16
|
187 // Dereferencing must return a proxy so that both *r++ = o and
|
Chris@16
|
188 // value_type(*r++) can work. In this case, *r is the same as
|
Chris@16
|
189 // *r++, and the conversion operator below is used to ensure
|
Chris@16
|
190 // readability.
|
Chris@16
|
191 writable_postfix_increment_proxy const&
|
Chris@16
|
192 operator*() const
|
Chris@16
|
193 {
|
Chris@16
|
194 return *this;
|
Chris@16
|
195 }
|
Chris@16
|
196
|
Chris@16
|
197 // Provides readability of *r++
|
Chris@16
|
198 operator value_type&() const
|
Chris@16
|
199 {
|
Chris@16
|
200 return stored_value;
|
Chris@16
|
201 }
|
Chris@16
|
202
|
Chris@16
|
203 // Provides writability of *r++
|
Chris@16
|
204 template <class T>
|
Chris@16
|
205 T const& operator=(T const& x) const
|
Chris@16
|
206 {
|
Chris@16
|
207 *this->stored_iterator = x;
|
Chris@16
|
208 return x;
|
Chris@16
|
209 }
|
Chris@16
|
210
|
Chris@16
|
211 // This overload just in case only non-const objects are writable
|
Chris@16
|
212 template <class T>
|
Chris@16
|
213 T& operator=(T& x) const
|
Chris@16
|
214 {
|
Chris@16
|
215 *this->stored_iterator = x;
|
Chris@16
|
216 return x;
|
Chris@16
|
217 }
|
Chris@16
|
218
|
Chris@16
|
219 // Provides X(r++)
|
Chris@16
|
220 operator Iterator const&() const
|
Chris@16
|
221 {
|
Chris@16
|
222 return stored_iterator;
|
Chris@16
|
223 }
|
Chris@101
|
224
|
Chris@16
|
225 private:
|
Chris@16
|
226 mutable value_type stored_value;
|
Chris@16
|
227 Iterator stored_iterator;
|
Chris@16
|
228 };
|
Chris@16
|
229
|
Chris@16
|
230 # ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
Chris@16
|
231
|
Chris@16
|
232 template <class Reference, class Value>
|
Chris@16
|
233 struct is_non_proxy_reference_impl
|
Chris@16
|
234 {
|
Chris@16
|
235 static Reference r;
|
Chris@101
|
236
|
Chris@16
|
237 template <class R>
|
Chris@16
|
238 static typename mpl::if_<
|
Chris@16
|
239 is_convertible<
|
Chris@16
|
240 R const volatile*
|
Chris@16
|
241 , Value const volatile*
|
Chris@16
|
242 >
|
Chris@16
|
243 , char[1]
|
Chris@16
|
244 , char[2]
|
Chris@16
|
245 >::type& helper(R const&);
|
Chris@101
|
246
|
Chris@16
|
247 BOOST_STATIC_CONSTANT(bool, value = sizeof(helper(r)) == 1);
|
Chris@16
|
248 };
|
Chris@101
|
249
|
Chris@16
|
250 template <class Reference, class Value>
|
Chris@16
|
251 struct is_non_proxy_reference
|
Chris@16
|
252 : mpl::bool_<
|
Chris@16
|
253 is_non_proxy_reference_impl<Reference, Value>::value
|
Chris@16
|
254 >
|
Chris@16
|
255 {};
|
Chris@101
|
256 # else
|
Chris@16
|
257 template <class Reference, class Value>
|
Chris@16
|
258 struct is_non_proxy_reference
|
Chris@16
|
259 : is_convertible<
|
Chris@16
|
260 typename remove_reference<Reference>::type
|
Chris@16
|
261 const volatile*
|
Chris@16
|
262 , Value const volatile*
|
Chris@16
|
263 >
|
Chris@16
|
264 {};
|
Chris@101
|
265 # endif
|
Chris@101
|
266
|
Chris@16
|
267 // A metafunction to choose the result type of postfix ++
|
Chris@16
|
268 //
|
Chris@16
|
269 // Because the C++98 input iterator requirements say that *r++ has
|
Chris@16
|
270 // type T (value_type), implementations of some standard
|
Chris@16
|
271 // algorithms like lexicographical_compare may use constructions
|
Chris@16
|
272 // like:
|
Chris@16
|
273 //
|
Chris@16
|
274 // *r++ < *s++
|
Chris@16
|
275 //
|
Chris@16
|
276 // If *r++ returns a proxy (as required if r is writable but not
|
Chris@16
|
277 // multipass), this sort of expression will fail unless the proxy
|
Chris@16
|
278 // supports the operator<. Since there are any number of such
|
Chris@16
|
279 // operations, we're not going to try to support them. Therefore,
|
Chris@16
|
280 // even if r++ returns a proxy, *r++ will only return a proxy if
|
Chris@16
|
281 // *r also returns a proxy.
|
Chris@16
|
282 template <class Iterator, class Value, class Reference, class CategoryOrTraversal>
|
Chris@16
|
283 struct postfix_increment_result
|
Chris@16
|
284 : mpl::eval_if<
|
Chris@16
|
285 mpl::and_<
|
Chris@16
|
286 // A proxy is only needed for readable iterators
|
Chris@16
|
287 is_convertible<Reference,Value const&>
|
Chris@101
|
288
|
Chris@16
|
289 // No multipass iterator can have values that disappear
|
Chris@16
|
290 // before positions can be re-visited
|
Chris@16
|
291 , mpl::not_<
|
Chris@16
|
292 is_convertible<
|
Chris@16
|
293 typename iterator_category_to_traversal<CategoryOrTraversal>::type
|
Chris@16
|
294 , forward_traversal_tag
|
Chris@16
|
295 >
|
Chris@16
|
296 >
|
Chris@16
|
297 >
|
Chris@16
|
298 , mpl::if_<
|
Chris@16
|
299 is_non_proxy_reference<Reference,Value>
|
Chris@16
|
300 , postfix_increment_proxy<Iterator>
|
Chris@16
|
301 , writable_postfix_increment_proxy<Iterator>
|
Chris@16
|
302 >
|
Chris@16
|
303 , mpl::identity<Iterator>
|
Chris@16
|
304 >
|
Chris@16
|
305 {};
|
Chris@16
|
306
|
Chris@16
|
307 // operator->() needs special support for input iterators to strictly meet the
|
Chris@16
|
308 // standard's requirements. If *i is not a reference type, we must still
|
Chris@16
|
309 // produce an lvalue to which a pointer can be formed. We do that by
|
Chris@16
|
310 // returning a proxy object containing an instance of the reference object.
|
Chris@16
|
311 template <class Reference, class Pointer>
|
Chris@16
|
312 struct operator_arrow_dispatch // proxy references
|
Chris@16
|
313 {
|
Chris@16
|
314 struct proxy
|
Chris@16
|
315 {
|
Chris@16
|
316 explicit proxy(Reference const & x) : m_ref(x) {}
|
Chris@16
|
317 Reference* operator->() { return boost::addressof(m_ref); }
|
Chris@16
|
318 // This function is needed for MWCW and BCC, which won't call
|
Chris@16
|
319 // operator-> again automatically per 13.3.1.2 para 8
|
Chris@16
|
320 operator Reference*() { return boost::addressof(m_ref); }
|
Chris@16
|
321 Reference m_ref;
|
Chris@16
|
322 };
|
Chris@16
|
323 typedef proxy result_type;
|
Chris@16
|
324 static result_type apply(Reference const & x)
|
Chris@16
|
325 {
|
Chris@16
|
326 return result_type(x);
|
Chris@16
|
327 }
|
Chris@16
|
328 };
|
Chris@16
|
329
|
Chris@16
|
330 template <class T, class Pointer>
|
Chris@16
|
331 struct operator_arrow_dispatch<T&, Pointer> // "real" references
|
Chris@16
|
332 {
|
Chris@16
|
333 typedef Pointer result_type;
|
Chris@16
|
334 static result_type apply(T& x)
|
Chris@16
|
335 {
|
Chris@16
|
336 return boost::addressof(x);
|
Chris@16
|
337 }
|
Chris@16
|
338 };
|
Chris@16
|
339
|
Chris@16
|
340 // A proxy return type for operator[], needed to deal with
|
Chris@16
|
341 // iterators that may invalidate referents upon destruction.
|
Chris@16
|
342 // Consider the temporary iterator in *(a + n)
|
Chris@16
|
343 template <class Iterator>
|
Chris@16
|
344 class operator_brackets_proxy
|
Chris@16
|
345 {
|
Chris@16
|
346 // Iterator is actually an iterator_facade, so we do not have to
|
Chris@16
|
347 // go through iterator_traits to access the traits.
|
Chris@16
|
348 typedef typename Iterator::reference reference;
|
Chris@16
|
349 typedef typename Iterator::value_type value_type;
|
Chris@16
|
350
|
Chris@16
|
351 public:
|
Chris@16
|
352 operator_brackets_proxy(Iterator const& iter)
|
Chris@16
|
353 : m_iter(iter)
|
Chris@16
|
354 {}
|
Chris@16
|
355
|
Chris@16
|
356 operator reference() const
|
Chris@16
|
357 {
|
Chris@16
|
358 return *m_iter;
|
Chris@16
|
359 }
|
Chris@16
|
360
|
Chris@16
|
361 operator_brackets_proxy& operator=(value_type const& val)
|
Chris@16
|
362 {
|
Chris@16
|
363 *m_iter = val;
|
Chris@16
|
364 return *this;
|
Chris@16
|
365 }
|
Chris@16
|
366
|
Chris@16
|
367 private:
|
Chris@16
|
368 Iterator m_iter;
|
Chris@16
|
369 };
|
Chris@16
|
370
|
Chris@16
|
371 // A metafunction that determines whether operator[] must return a
|
Chris@16
|
372 // proxy, or whether it can simply return a copy of the value_type.
|
Chris@16
|
373 template <class ValueType, class Reference>
|
Chris@16
|
374 struct use_operator_brackets_proxy
|
Chris@16
|
375 : mpl::not_<
|
Chris@16
|
376 mpl::and_<
|
Chris@16
|
377 // Really we want an is_copy_constructible trait here,
|
Chris@16
|
378 // but is_POD will have to suffice in the meantime.
|
Chris@16
|
379 boost::is_POD<ValueType>
|
Chris@16
|
380 , iterator_writability_disabled<ValueType,Reference>
|
Chris@16
|
381 >
|
Chris@16
|
382 >
|
Chris@16
|
383 {};
|
Chris@101
|
384
|
Chris@16
|
385 template <class Iterator, class Value, class Reference>
|
Chris@16
|
386 struct operator_brackets_result
|
Chris@16
|
387 {
|
Chris@16
|
388 typedef typename mpl::if_<
|
Chris@16
|
389 use_operator_brackets_proxy<Value,Reference>
|
Chris@16
|
390 , operator_brackets_proxy<Iterator>
|
Chris@16
|
391 , Value
|
Chris@16
|
392 >::type type;
|
Chris@16
|
393 };
|
Chris@16
|
394
|
Chris@16
|
395 template <class Iterator>
|
Chris@16
|
396 operator_brackets_proxy<Iterator> make_operator_brackets_result(Iterator const& iter, mpl::true_)
|
Chris@16
|
397 {
|
Chris@16
|
398 return operator_brackets_proxy<Iterator>(iter);
|
Chris@16
|
399 }
|
Chris@16
|
400
|
Chris@16
|
401 template <class Iterator>
|
Chris@16
|
402 typename Iterator::value_type make_operator_brackets_result(Iterator const& iter, mpl::false_)
|
Chris@16
|
403 {
|
Chris@16
|
404 return *iter;
|
Chris@16
|
405 }
|
Chris@16
|
406
|
Chris@16
|
407 struct choose_difference_type
|
Chris@16
|
408 {
|
Chris@16
|
409 template <class I1, class I2>
|
Chris@16
|
410 struct apply
|
Chris@16
|
411 :
|
Chris@16
|
412 # ifdef BOOST_NO_ONE_WAY_ITERATOR_INTEROP
|
Chris@16
|
413 iterator_difference<I1>
|
Chris@101
|
414 # else
|
Chris@16
|
415 mpl::eval_if<
|
Chris@16
|
416 is_convertible<I2,I1>
|
Chris@16
|
417 , iterator_difference<I1>
|
Chris@16
|
418 , iterator_difference<I2>
|
Chris@16
|
419 >
|
Chris@101
|
420 # endif
|
Chris@16
|
421 {};
|
Chris@16
|
422
|
Chris@16
|
423 };
|
Chris@101
|
424
|
Chris@101
|
425 template <
|
Chris@101
|
426 class Derived
|
Chris@101
|
427 , class Value
|
Chris@101
|
428 , class CategoryOrTraversal
|
Chris@101
|
429 , class Reference
|
Chris@101
|
430 , class Difference
|
Chris@101
|
431 , bool IsBidirectionalTraversal
|
Chris@101
|
432 , bool IsRandomAccessTraversal
|
Chris@101
|
433 >
|
Chris@101
|
434 class iterator_facade_base;
|
Chris@101
|
435
|
Chris@16
|
436 } // namespace detail
|
Chris@16
|
437
|
Chris@16
|
438
|
Chris@16
|
439 // Macros which describe the declarations of binary operators
|
Chris@16
|
440 # ifdef BOOST_NO_STRICT_ITERATOR_INTEROPERABILITY
|
Chris@101
|
441 # define BOOST_ITERATOR_FACADE_INTEROP_HEAD_IMPL(prefix, op, result_type, enabler) \
|
Chris@16
|
442 template < \
|
Chris@16
|
443 class Derived1, class V1, class TC1, class Reference1, class Difference1 \
|
Chris@16
|
444 , class Derived2, class V2, class TC2, class Reference2, class Difference2 \
|
Chris@16
|
445 > \
|
Chris@16
|
446 prefix typename mpl::apply2<result_type,Derived1,Derived2>::type \
|
Chris@16
|
447 operator op( \
|
Chris@16
|
448 iterator_facade<Derived1, V1, TC1, Reference1, Difference1> const& lhs \
|
Chris@16
|
449 , iterator_facade<Derived2, V2, TC2, Reference2, Difference2> const& rhs)
|
Chris@101
|
450 # else
|
Chris@101
|
451 # define BOOST_ITERATOR_FACADE_INTEROP_HEAD_IMPL(prefix, op, result_type, enabler) \
|
Chris@16
|
452 template < \
|
Chris@16
|
453 class Derived1, class V1, class TC1, class Reference1, class Difference1 \
|
Chris@16
|
454 , class Derived2, class V2, class TC2, class Reference2, class Difference2 \
|
Chris@16
|
455 > \
|
Chris@101
|
456 prefix typename enabler< \
|
Chris@16
|
457 Derived1, Derived2 \
|
Chris@16
|
458 , typename mpl::apply2<result_type,Derived1,Derived2>::type \
|
Chris@16
|
459 >::type \
|
Chris@16
|
460 operator op( \
|
Chris@16
|
461 iterator_facade<Derived1, V1, TC1, Reference1, Difference1> const& lhs \
|
Chris@16
|
462 , iterator_facade<Derived2, V2, TC2, Reference2, Difference2> const& rhs)
|
Chris@101
|
463 # endif
|
Chris@101
|
464
|
Chris@101
|
465 # define BOOST_ITERATOR_FACADE_INTEROP_HEAD(prefix, op, result_type) \
|
Chris@101
|
466 BOOST_ITERATOR_FACADE_INTEROP_HEAD_IMPL(prefix, op, result_type, boost::iterators::detail::enable_if_interoperable)
|
Chris@101
|
467
|
Chris@101
|
468 # define BOOST_ITERATOR_FACADE_INTEROP_RANDOM_ACCESS_HEAD(prefix, op, result_type) \
|
Chris@101
|
469 BOOST_ITERATOR_FACADE_INTEROP_HEAD_IMPL(prefix, op, result_type, boost::iterators::detail::enable_if_interoperable_and_random_access_traversal)
|
Chris@16
|
470
|
Chris@16
|
471 # define BOOST_ITERATOR_FACADE_PLUS_HEAD(prefix,args) \
|
Chris@16
|
472 template <class Derived, class V, class TC, class R, class D> \
|
Chris@101
|
473 prefix typename boost::iterators::enable_if< \
|
Chris@101
|
474 boost::iterators::detail::is_traversal_at_least< TC, boost::iterators::random_access_traversal_tag >, \
|
Chris@101
|
475 Derived \
|
Chris@101
|
476 >::type operator+ args
|
Chris@16
|
477
|
Chris@16
|
478 //
|
Chris@16
|
479 // Helper class for granting access to the iterator core interface.
|
Chris@16
|
480 //
|
Chris@16
|
481 // The simple core interface is used by iterator_facade. The core
|
Chris@16
|
482 // interface of a user/library defined iterator type should not be made public
|
Chris@16
|
483 // so that it does not clutter the public interface. Instead iterator_core_access
|
Chris@16
|
484 // should be made friend so that iterator_facade can access the core
|
Chris@16
|
485 // interface through iterator_core_access.
|
Chris@16
|
486 //
|
Chris@16
|
487 class iterator_core_access
|
Chris@16
|
488 {
|
Chris@101
|
489 # if defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
|
Chris@16
|
490 // Tasteless as this may seem, making all members public allows member templates
|
Chris@16
|
491 // to work in the absence of member template friends.
|
Chris@16
|
492 public:
|
Chris@16
|
493 # else
|
Chris@101
|
494
|
Chris@16
|
495 template <class I, class V, class TC, class R, class D> friend class iterator_facade;
|
Chris@101
|
496 template <class I, class V, class TC, class R, class D, bool IsBidirectionalTraversal, bool IsRandomAccessTraversal>
|
Chris@101
|
497 friend class detail::iterator_facade_base;
|
Chris@16
|
498
|
Chris@16
|
499 # define BOOST_ITERATOR_FACADE_RELATION(op) \
|
Chris@101
|
500 BOOST_ITERATOR_FACADE_INTEROP_HEAD(friend,op, boost::iterators::detail::always_bool2);
|
Chris@16
|
501
|
Chris@16
|
502 BOOST_ITERATOR_FACADE_RELATION(==)
|
Chris@16
|
503 BOOST_ITERATOR_FACADE_RELATION(!=)
|
Chris@16
|
504
|
Chris@16
|
505 # undef BOOST_ITERATOR_FACADE_RELATION
|
Chris@16
|
506
|
Chris@101
|
507 # define BOOST_ITERATOR_FACADE_RANDOM_ACCESS_RELATION(op) \
|
Chris@101
|
508 BOOST_ITERATOR_FACADE_INTEROP_RANDOM_ACCESS_HEAD(friend,op, boost::iterators::detail::always_bool2);
|
Chris@101
|
509
|
Chris@101
|
510 BOOST_ITERATOR_FACADE_RANDOM_ACCESS_RELATION(<)
|
Chris@101
|
511 BOOST_ITERATOR_FACADE_RANDOM_ACCESS_RELATION(>)
|
Chris@101
|
512 BOOST_ITERATOR_FACADE_RANDOM_ACCESS_RELATION(<=)
|
Chris@101
|
513 BOOST_ITERATOR_FACADE_RANDOM_ACCESS_RELATION(>=)
|
Chris@101
|
514
|
Chris@101
|
515 # undef BOOST_ITERATOR_FACADE_RANDOM_ACCESS_RELATION
|
Chris@101
|
516
|
Chris@101
|
517 BOOST_ITERATOR_FACADE_INTEROP_RANDOM_ACCESS_HEAD(
|
Chris@101
|
518 friend, -, boost::iterators::detail::choose_difference_type)
|
Chris@16
|
519 ;
|
Chris@16
|
520
|
Chris@16
|
521 BOOST_ITERATOR_FACADE_PLUS_HEAD(
|
Chris@16
|
522 friend inline
|
Chris@101
|
523 , (iterator_facade<Derived, V, TC, R, D> const&
|
Chris@101
|
524 , typename Derived::difference_type)
|
Chris@16
|
525 )
|
Chris@16
|
526 ;
|
Chris@16
|
527
|
Chris@16
|
528 BOOST_ITERATOR_FACADE_PLUS_HEAD(
|
Chris@16
|
529 friend inline
|
Chris@16
|
530 , (typename Derived::difference_type
|
Chris@101
|
531 , iterator_facade<Derived, V, TC, R, D> const&)
|
Chris@16
|
532 )
|
Chris@16
|
533 ;
|
Chris@16
|
534
|
Chris@16
|
535 # endif
|
Chris@16
|
536
|
Chris@16
|
537 template <class Facade>
|
Chris@16
|
538 static typename Facade::reference dereference(Facade const& f)
|
Chris@16
|
539 {
|
Chris@16
|
540 return f.dereference();
|
Chris@16
|
541 }
|
Chris@16
|
542
|
Chris@16
|
543 template <class Facade>
|
Chris@16
|
544 static void increment(Facade& f)
|
Chris@16
|
545 {
|
Chris@16
|
546 f.increment();
|
Chris@16
|
547 }
|
Chris@16
|
548
|
Chris@16
|
549 template <class Facade>
|
Chris@16
|
550 static void decrement(Facade& f)
|
Chris@16
|
551 {
|
Chris@16
|
552 f.decrement();
|
Chris@16
|
553 }
|
Chris@16
|
554
|
Chris@16
|
555 template <class Facade1, class Facade2>
|
Chris@16
|
556 static bool equal(Facade1 const& f1, Facade2 const& f2, mpl::true_)
|
Chris@16
|
557 {
|
Chris@16
|
558 return f1.equal(f2);
|
Chris@16
|
559 }
|
Chris@16
|
560
|
Chris@16
|
561 template <class Facade1, class Facade2>
|
Chris@16
|
562 static bool equal(Facade1 const& f1, Facade2 const& f2, mpl::false_)
|
Chris@16
|
563 {
|
Chris@16
|
564 return f2.equal(f1);
|
Chris@16
|
565 }
|
Chris@16
|
566
|
Chris@16
|
567 template <class Facade>
|
Chris@16
|
568 static void advance(Facade& f, typename Facade::difference_type n)
|
Chris@16
|
569 {
|
Chris@16
|
570 f.advance(n);
|
Chris@16
|
571 }
|
Chris@16
|
572
|
Chris@16
|
573 template <class Facade1, class Facade2>
|
Chris@16
|
574 static typename Facade1::difference_type distance_from(
|
Chris@16
|
575 Facade1 const& f1, Facade2 const& f2, mpl::true_)
|
Chris@16
|
576 {
|
Chris@16
|
577 return -f1.distance_to(f2);
|
Chris@16
|
578 }
|
Chris@16
|
579
|
Chris@16
|
580 template <class Facade1, class Facade2>
|
Chris@16
|
581 static typename Facade2::difference_type distance_from(
|
Chris@16
|
582 Facade1 const& f1, Facade2 const& f2, mpl::false_)
|
Chris@16
|
583 {
|
Chris@16
|
584 return f2.distance_to(f1);
|
Chris@16
|
585 }
|
Chris@16
|
586
|
Chris@16
|
587 //
|
Chris@16
|
588 // Curiously Recurring Template interface.
|
Chris@16
|
589 //
|
Chris@16
|
590 template <class I, class V, class TC, class R, class D>
|
Chris@16
|
591 static I& derived(iterator_facade<I,V,TC,R,D>& facade)
|
Chris@16
|
592 {
|
Chris@16
|
593 return *static_cast<I*>(&facade);
|
Chris@16
|
594 }
|
Chris@16
|
595
|
Chris@16
|
596 template <class I, class V, class TC, class R, class D>
|
Chris@16
|
597 static I const& derived(iterator_facade<I,V,TC,R,D> const& facade)
|
Chris@16
|
598 {
|
Chris@16
|
599 return *static_cast<I const*>(&facade);
|
Chris@16
|
600 }
|
Chris@16
|
601
|
Chris@16
|
602 // objects of this class are useless
|
Chris@101
|
603 BOOST_DELETED_FUNCTION(iterator_core_access())
|
Chris@16
|
604 };
|
Chris@16
|
605
|
Chris@101
|
606 namespace detail {
|
Chris@101
|
607
|
Chris@101
|
608 // Implementation for forward traversal iterators
|
Chris@101
|
609 template <
|
Chris@101
|
610 class Derived
|
Chris@101
|
611 , class Value
|
Chris@101
|
612 , class CategoryOrTraversal
|
Chris@101
|
613 , class Reference
|
Chris@101
|
614 , class Difference
|
Chris@101
|
615 >
|
Chris@101
|
616 class iterator_facade_base< Derived, Value, CategoryOrTraversal, Reference, Difference, false, false >
|
Chris@101
|
617 # ifdef BOOST_ITERATOR_FACADE_NEEDS_ITERATOR_BASE
|
Chris@101
|
618 : public boost::iterators::detail::iterator_facade_types<
|
Chris@101
|
619 Value, CategoryOrTraversal, Reference, Difference
|
Chris@101
|
620 >::base
|
Chris@101
|
621 # undef BOOST_ITERATOR_FACADE_NEEDS_ITERATOR_BASE
|
Chris@101
|
622 # endif
|
Chris@101
|
623 {
|
Chris@101
|
624 private:
|
Chris@101
|
625 typedef boost::iterators::detail::iterator_facade_types<
|
Chris@101
|
626 Value, CategoryOrTraversal, Reference, Difference
|
Chris@101
|
627 > associated_types;
|
Chris@101
|
628
|
Chris@101
|
629 typedef boost::iterators::detail::operator_arrow_dispatch<
|
Chris@101
|
630 Reference
|
Chris@101
|
631 , typename associated_types::pointer
|
Chris@101
|
632 > operator_arrow_dispatch_;
|
Chris@101
|
633
|
Chris@101
|
634 public:
|
Chris@101
|
635 typedef typename associated_types::value_type value_type;
|
Chris@101
|
636 typedef Reference reference;
|
Chris@101
|
637 typedef Difference difference_type;
|
Chris@101
|
638
|
Chris@101
|
639 typedef typename operator_arrow_dispatch_::result_type pointer;
|
Chris@101
|
640
|
Chris@101
|
641 typedef typename associated_types::iterator_category iterator_category;
|
Chris@101
|
642
|
Chris@101
|
643 public:
|
Chris@101
|
644 reference operator*() const
|
Chris@101
|
645 {
|
Chris@101
|
646 return iterator_core_access::dereference(this->derived());
|
Chris@101
|
647 }
|
Chris@101
|
648
|
Chris@101
|
649 pointer operator->() const
|
Chris@101
|
650 {
|
Chris@101
|
651 return operator_arrow_dispatch_::apply(*this->derived());
|
Chris@101
|
652 }
|
Chris@101
|
653
|
Chris@101
|
654 Derived& operator++()
|
Chris@101
|
655 {
|
Chris@101
|
656 iterator_core_access::increment(this->derived());
|
Chris@101
|
657 return this->derived();
|
Chris@101
|
658 }
|
Chris@101
|
659
|
Chris@101
|
660 protected:
|
Chris@101
|
661 //
|
Chris@101
|
662 // Curiously Recurring Template interface.
|
Chris@101
|
663 //
|
Chris@101
|
664 Derived& derived()
|
Chris@101
|
665 {
|
Chris@101
|
666 return *static_cast<Derived*>(this);
|
Chris@101
|
667 }
|
Chris@101
|
668
|
Chris@101
|
669 Derived const& derived() const
|
Chris@101
|
670 {
|
Chris@101
|
671 return *static_cast<Derived const*>(this);
|
Chris@101
|
672 }
|
Chris@101
|
673 };
|
Chris@101
|
674
|
Chris@101
|
675 // Implementation for bidirectional traversal iterators
|
Chris@101
|
676 template <
|
Chris@101
|
677 class Derived
|
Chris@101
|
678 , class Value
|
Chris@101
|
679 , class CategoryOrTraversal
|
Chris@101
|
680 , class Reference
|
Chris@101
|
681 , class Difference
|
Chris@101
|
682 >
|
Chris@101
|
683 class iterator_facade_base< Derived, Value, CategoryOrTraversal, Reference, Difference, true, false > :
|
Chris@101
|
684 public iterator_facade_base< Derived, Value, CategoryOrTraversal, Reference, Difference, false, false >
|
Chris@101
|
685 {
|
Chris@101
|
686 public:
|
Chris@101
|
687 Derived& operator--()
|
Chris@101
|
688 {
|
Chris@101
|
689 iterator_core_access::decrement(this->derived());
|
Chris@101
|
690 return this->derived();
|
Chris@101
|
691 }
|
Chris@101
|
692
|
Chris@101
|
693 Derived operator--(int)
|
Chris@101
|
694 {
|
Chris@101
|
695 Derived tmp(this->derived());
|
Chris@101
|
696 --*this;
|
Chris@101
|
697 return tmp;
|
Chris@101
|
698 }
|
Chris@101
|
699 };
|
Chris@101
|
700
|
Chris@101
|
701 // Implementation for random access traversal iterators
|
Chris@101
|
702 template <
|
Chris@101
|
703 class Derived
|
Chris@101
|
704 , class Value
|
Chris@101
|
705 , class CategoryOrTraversal
|
Chris@101
|
706 , class Reference
|
Chris@101
|
707 , class Difference
|
Chris@101
|
708 >
|
Chris@101
|
709 class iterator_facade_base< Derived, Value, CategoryOrTraversal, Reference, Difference, true, true > :
|
Chris@101
|
710 public iterator_facade_base< Derived, Value, CategoryOrTraversal, Reference, Difference, true, false >
|
Chris@101
|
711 {
|
Chris@101
|
712 private:
|
Chris@101
|
713 typedef iterator_facade_base< Derived, Value, CategoryOrTraversal, Reference, Difference, true, false > base_type;
|
Chris@101
|
714
|
Chris@101
|
715 public:
|
Chris@101
|
716 typedef typename base_type::reference reference;
|
Chris@101
|
717 typedef typename base_type::difference_type difference_type;
|
Chris@101
|
718
|
Chris@101
|
719 public:
|
Chris@101
|
720 typename boost::iterators::detail::operator_brackets_result<Derived, Value, reference>::type
|
Chris@101
|
721 operator[](difference_type n) const
|
Chris@101
|
722 {
|
Chris@101
|
723 typedef boost::iterators::detail::use_operator_brackets_proxy<Value, Reference> use_proxy;
|
Chris@101
|
724
|
Chris@101
|
725 return boost::iterators::detail::make_operator_brackets_result<Derived>(
|
Chris@101
|
726 this->derived() + n
|
Chris@101
|
727 , use_proxy()
|
Chris@101
|
728 );
|
Chris@101
|
729 }
|
Chris@101
|
730
|
Chris@101
|
731 Derived& operator+=(difference_type n)
|
Chris@101
|
732 {
|
Chris@101
|
733 iterator_core_access::advance(this->derived(), n);
|
Chris@101
|
734 return this->derived();
|
Chris@101
|
735 }
|
Chris@101
|
736
|
Chris@101
|
737 Derived& operator-=(difference_type n)
|
Chris@101
|
738 {
|
Chris@101
|
739 iterator_core_access::advance(this->derived(), -n);
|
Chris@101
|
740 return this->derived();
|
Chris@101
|
741 }
|
Chris@101
|
742
|
Chris@101
|
743 Derived operator-(difference_type x) const
|
Chris@101
|
744 {
|
Chris@101
|
745 Derived result(this->derived());
|
Chris@101
|
746 return result -= x;
|
Chris@101
|
747 }
|
Chris@101
|
748 };
|
Chris@101
|
749
|
Chris@101
|
750 } // namespace detail
|
Chris@101
|
751
|
Chris@16
|
752 //
|
Chris@16
|
753 // iterator_facade - use as a public base class for defining new
|
Chris@16
|
754 // standard-conforming iterators.
|
Chris@16
|
755 //
|
Chris@16
|
756 template <
|
Chris@16
|
757 class Derived // The derived iterator type being constructed
|
Chris@16
|
758 , class Value
|
Chris@16
|
759 , class CategoryOrTraversal
|
Chris@16
|
760 , class Reference = Value&
|
Chris@16
|
761 , class Difference = std::ptrdiff_t
|
Chris@16
|
762 >
|
Chris@101
|
763 class iterator_facade :
|
Chris@101
|
764 public detail::iterator_facade_base<
|
Chris@101
|
765 Derived,
|
Chris@101
|
766 Value,
|
Chris@101
|
767 CategoryOrTraversal,
|
Chris@101
|
768 Reference,
|
Chris@101
|
769 Difference,
|
Chris@101
|
770 detail::is_traversal_at_least< CategoryOrTraversal, bidirectional_traversal_tag >::value,
|
Chris@101
|
771 detail::is_traversal_at_least< CategoryOrTraversal, random_access_traversal_tag >::value
|
Chris@101
|
772 >
|
Chris@16
|
773 {
|
Chris@101
|
774 protected:
|
Chris@16
|
775 // For use by derived classes
|
Chris@16
|
776 typedef iterator_facade<Derived,Value,CategoryOrTraversal,Reference,Difference> iterator_facade_;
|
Chris@16
|
777 };
|
Chris@16
|
778
|
Chris@16
|
779 template <class I, class V, class TC, class R, class D>
|
Chris@101
|
780 inline typename boost::iterators::detail::postfix_increment_result<I,V,R,TC>::type
|
Chris@16
|
781 operator++(
|
Chris@16
|
782 iterator_facade<I,V,TC,R,D>& i
|
Chris@16
|
783 , int
|
Chris@16
|
784 )
|
Chris@16
|
785 {
|
Chris@101
|
786 typename boost::iterators::detail::postfix_increment_result<I,V,R,TC>::type
|
Chris@16
|
787 tmp(*static_cast<I*>(&i));
|
Chris@101
|
788
|
Chris@16
|
789 ++i;
|
Chris@101
|
790
|
Chris@16
|
791 return tmp;
|
Chris@16
|
792 }
|
Chris@16
|
793
|
Chris@101
|
794
|
Chris@16
|
795 //
|
Chris@16
|
796 // Comparison operator implementation. The library supplied operators
|
Chris@16
|
797 // enables the user to provide fully interoperable constant/mutable
|
Chris@16
|
798 // iterator types. I.e. the library provides all operators
|
Chris@16
|
799 // for all mutable/constant iterator combinations.
|
Chris@16
|
800 //
|
Chris@16
|
801 // Note though that this kind of interoperability for constant/mutable
|
Chris@16
|
802 // iterators is not required by the standard for container iterators.
|
Chris@16
|
803 // All the standard asks for is a conversion mutable -> constant.
|
Chris@16
|
804 // Most standard library implementations nowadays provide fully interoperable
|
Chris@16
|
805 // iterator implementations, but there are still heavily used implementations
|
Chris@16
|
806 // that do not provide them. (Actually it's even worse, they do not provide
|
Chris@16
|
807 // them for only a few iterators.)
|
Chris@16
|
808 //
|
Chris@16
|
809 // ?? Maybe a BOOST_ITERATOR_NO_FULL_INTEROPERABILITY macro should
|
Chris@16
|
810 // enable the user to turn off mixed type operators
|
Chris@16
|
811 //
|
Chris@16
|
812 // The library takes care to provide only the right operator overloads.
|
Chris@16
|
813 // I.e.
|
Chris@16
|
814 //
|
Chris@16
|
815 // bool operator==(Iterator, Iterator);
|
Chris@16
|
816 // bool operator==(ConstIterator, Iterator);
|
Chris@16
|
817 // bool operator==(Iterator, ConstIterator);
|
Chris@16
|
818 // bool operator==(ConstIterator, ConstIterator);
|
Chris@16
|
819 //
|
Chris@16
|
820 // ...
|
Chris@16
|
821 //
|
Chris@16
|
822 // In order to do so it uses c++ idioms that are not yet widely supported
|
Chris@16
|
823 // by current compiler releases. The library is designed to degrade gracefully
|
Chris@16
|
824 // in the face of compiler deficiencies. In general compiler
|
Chris@16
|
825 // deficiencies result in less strict error checking and more obscure
|
Chris@16
|
826 // error messages, functionality is not affected.
|
Chris@16
|
827 //
|
Chris@16
|
828 // For full operation compiler support for "Substitution Failure Is Not An Error"
|
Chris@16
|
829 // (aka. enable_if) and boost::is_convertible is required.
|
Chris@16
|
830 //
|
Chris@16
|
831 // The following problems occur if support is lacking.
|
Chris@16
|
832 //
|
Chris@16
|
833 // Pseudo code
|
Chris@16
|
834 //
|
Chris@16
|
835 // ---------------
|
Chris@16
|
836 // AdaptorA<Iterator1> a1;
|
Chris@16
|
837 // AdaptorA<Iterator2> a2;
|
Chris@16
|
838 //
|
Chris@16
|
839 // // This will result in a no such overload error in full operation
|
Chris@16
|
840 // // If enable_if or is_convertible is not supported
|
Chris@16
|
841 // // The instantiation will fail with an error hopefully indicating that
|
Chris@16
|
842 // // there is no operator== for Iterator1, Iterator2
|
Chris@16
|
843 // // The same will happen if no enable_if is used to remove
|
Chris@16
|
844 // // false overloads from the templated conversion constructor
|
Chris@16
|
845 // // of AdaptorA.
|
Chris@16
|
846 //
|
Chris@16
|
847 // a1 == a2;
|
Chris@16
|
848 // ----------------
|
Chris@16
|
849 //
|
Chris@16
|
850 // AdaptorA<Iterator> a;
|
Chris@16
|
851 // AdaptorB<Iterator> b;
|
Chris@16
|
852 //
|
Chris@16
|
853 // // This will result in a no such overload error in full operation
|
Chris@16
|
854 // // If enable_if is not supported the static assert used
|
Chris@16
|
855 // // in the operator implementation will fail.
|
Chris@16
|
856 // // This will accidently work if is_convertible is not supported.
|
Chris@16
|
857 //
|
Chris@16
|
858 // a == b;
|
Chris@16
|
859 // ----------------
|
Chris@16
|
860 //
|
Chris@16
|
861
|
Chris@16
|
862 # ifdef BOOST_NO_ONE_WAY_ITERATOR_INTEROP
|
Chris@16
|
863 # define BOOST_ITERATOR_CONVERTIBLE(a,b) mpl::true_()
|
Chris@16
|
864 # else
|
Chris@16
|
865 # define BOOST_ITERATOR_CONVERTIBLE(a,b) is_convertible<a,b>()
|
Chris@16
|
866 # endif
|
Chris@16
|
867
|
Chris@16
|
868 # define BOOST_ITERATOR_FACADE_INTEROP(op, result_type, return_prefix, base_op) \
|
Chris@16
|
869 BOOST_ITERATOR_FACADE_INTEROP_HEAD(inline, op, result_type) \
|
Chris@16
|
870 { \
|
Chris@16
|
871 /* For those compilers that do not support enable_if */ \
|
Chris@16
|
872 BOOST_STATIC_ASSERT(( \
|
Chris@16
|
873 is_interoperable< Derived1, Derived2 >::value \
|
Chris@16
|
874 )); \
|
Chris@16
|
875 return_prefix iterator_core_access::base_op( \
|
Chris@16
|
876 *static_cast<Derived1 const*>(&lhs) \
|
Chris@16
|
877 , *static_cast<Derived2 const*>(&rhs) \
|
Chris@16
|
878 , BOOST_ITERATOR_CONVERTIBLE(Derived2,Derived1) \
|
Chris@16
|
879 ); \
|
Chris@16
|
880 }
|
Chris@16
|
881
|
Chris@16
|
882 # define BOOST_ITERATOR_FACADE_RELATION(op, return_prefix, base_op) \
|
Chris@16
|
883 BOOST_ITERATOR_FACADE_INTEROP( \
|
Chris@16
|
884 op \
|
Chris@101
|
885 , boost::iterators::detail::always_bool2 \
|
Chris@16
|
886 , return_prefix \
|
Chris@16
|
887 , base_op \
|
Chris@16
|
888 )
|
Chris@16
|
889
|
Chris@16
|
890 BOOST_ITERATOR_FACADE_RELATION(==, return, equal)
|
Chris@16
|
891 BOOST_ITERATOR_FACADE_RELATION(!=, return !, equal)
|
Chris@16
|
892
|
Chris@16
|
893 # undef BOOST_ITERATOR_FACADE_RELATION
|
Chris@16
|
894
|
Chris@101
|
895
|
Chris@101
|
896 # define BOOST_ITERATOR_FACADE_INTEROP_RANDOM_ACCESS(op, result_type, return_prefix, base_op) \
|
Chris@101
|
897 BOOST_ITERATOR_FACADE_INTEROP_RANDOM_ACCESS_HEAD(inline, op, result_type) \
|
Chris@101
|
898 { \
|
Chris@101
|
899 /* For those compilers that do not support enable_if */ \
|
Chris@101
|
900 BOOST_STATIC_ASSERT(( \
|
Chris@101
|
901 is_interoperable< Derived1, Derived2 >::value && \
|
Chris@101
|
902 boost::iterators::detail::is_traversal_at_least< typename iterator_category< Derived1 >::type, random_access_traversal_tag >::value && \
|
Chris@101
|
903 boost::iterators::detail::is_traversal_at_least< typename iterator_category< Derived2 >::type, random_access_traversal_tag >::value \
|
Chris@101
|
904 )); \
|
Chris@101
|
905 return_prefix iterator_core_access::base_op( \
|
Chris@101
|
906 *static_cast<Derived1 const*>(&lhs) \
|
Chris@101
|
907 , *static_cast<Derived2 const*>(&rhs) \
|
Chris@101
|
908 , BOOST_ITERATOR_CONVERTIBLE(Derived2,Derived1) \
|
Chris@101
|
909 ); \
|
Chris@101
|
910 }
|
Chris@101
|
911
|
Chris@101
|
912 # define BOOST_ITERATOR_FACADE_RANDOM_ACCESS_RELATION(op, return_prefix, base_op) \
|
Chris@101
|
913 BOOST_ITERATOR_FACADE_INTEROP_RANDOM_ACCESS( \
|
Chris@101
|
914 op \
|
Chris@101
|
915 , boost::iterators::detail::always_bool2 \
|
Chris@101
|
916 , return_prefix \
|
Chris@101
|
917 , base_op \
|
Chris@101
|
918 )
|
Chris@101
|
919
|
Chris@101
|
920 BOOST_ITERATOR_FACADE_RANDOM_ACCESS_RELATION(<, return 0 >, distance_from)
|
Chris@101
|
921 BOOST_ITERATOR_FACADE_RANDOM_ACCESS_RELATION(>, return 0 <, distance_from)
|
Chris@101
|
922 BOOST_ITERATOR_FACADE_RANDOM_ACCESS_RELATION(<=, return 0 >=, distance_from)
|
Chris@101
|
923 BOOST_ITERATOR_FACADE_RANDOM_ACCESS_RELATION(>=, return 0 <=, distance_from)
|
Chris@101
|
924
|
Chris@101
|
925 # undef BOOST_ITERATOR_FACADE_RANDOM_ACCESS_RELATION
|
Chris@101
|
926
|
Chris@16
|
927 // operator- requires an additional part in the static assertion
|
Chris@101
|
928 BOOST_ITERATOR_FACADE_INTEROP_RANDOM_ACCESS(
|
Chris@16
|
929 -
|
Chris@101
|
930 , boost::iterators::detail::choose_difference_type
|
Chris@16
|
931 , return
|
Chris@16
|
932 , distance_from
|
Chris@16
|
933 )
|
Chris@101
|
934
|
Chris@16
|
935 # undef BOOST_ITERATOR_FACADE_INTEROP
|
Chris@101
|
936 # undef BOOST_ITERATOR_FACADE_INTEROP_RANDOM_ACCESS
|
Chris@16
|
937
|
Chris@16
|
938 # define BOOST_ITERATOR_FACADE_PLUS(args) \
|
Chris@16
|
939 BOOST_ITERATOR_FACADE_PLUS_HEAD(inline, args) \
|
Chris@16
|
940 { \
|
Chris@16
|
941 Derived tmp(static_cast<Derived const&>(i)); \
|
Chris@16
|
942 return tmp += n; \
|
Chris@16
|
943 }
|
Chris@16
|
944
|
Chris@101
|
945 BOOST_ITERATOR_FACADE_PLUS((
|
Chris@101
|
946 iterator_facade<Derived, V, TC, R, D> const& i
|
Chris@101
|
947 , typename Derived::difference_type n
|
Chris@101
|
948 ))
|
Chris@16
|
949
|
Chris@101
|
950 BOOST_ITERATOR_FACADE_PLUS((
|
Chris@101
|
951 typename Derived::difference_type n
|
Chris@16
|
952 , iterator_facade<Derived, V, TC, R, D> const& i
|
Chris@101
|
953 ))
|
Chris@101
|
954
|
Chris@16
|
955 # undef BOOST_ITERATOR_FACADE_PLUS
|
Chris@16
|
956 # undef BOOST_ITERATOR_FACADE_PLUS_HEAD
|
Chris@16
|
957
|
Chris@101
|
958 # undef BOOST_ITERATOR_FACADE_INTEROP_HEAD
|
Chris@101
|
959 # undef BOOST_ITERATOR_FACADE_INTEROP_RANDOM_ACCESS_HEAD
|
Chris@101
|
960 # undef BOOST_ITERATOR_FACADE_INTEROP_HEAD_IMPL
|
Chris@101
|
961
|
Chris@101
|
962 } // namespace iterators
|
Chris@101
|
963
|
Chris@101
|
964 using iterators::iterator_core_access;
|
Chris@101
|
965 using iterators::iterator_facade;
|
Chris@101
|
966
|
Chris@16
|
967 } // namespace boost
|
Chris@16
|
968
|
Chris@16
|
969 #include <boost/iterator/detail/config_undef.hpp>
|
Chris@16
|
970
|
Chris@16
|
971 #endif // BOOST_ITERATOR_FACADE_23022003THW_HPP
|