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 |
361 | |