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