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