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
10 #include <boost/static_assert.hpp>
11 #include <boost/iterator.hpp>
12 #include <boost/detail/iterator.hpp>
14 #include <boost/iterator/iterator_categories.hpp>
15 #include <boost/iterator/iterator_facade.hpp>
16 #include <boost/iterator/detail/enable_if.hpp>
18 #include <boost/mpl/and.hpp>
19 #include <boost/mpl/not.hpp>
20 #include <boost/mpl/or.hpp>
22 #include <boost/type_traits/is_same.hpp>
23 #include <boost/type_traits/is_convertible.hpp>
25 #ifdef BOOST_ITERATOR_REF_CONSTNESS_KILLS_WRITABILITY
26 # include <boost/type_traits/remove_reference.hpp>
28 # include <boost/type_traits/add_reference.hpp>
31 #include <boost/iterator/detail/config_def.hpp>
33 #include <boost/iterator/iterator_traits.hpp>
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.
42 # ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
43 // the incompleteness of use_default causes massive problems for
44 // is_convertible (naturally). This workaround is fortunately not
45 // needed for vc6/vc7.
47 struct is_convertible<use_default,To>
55 // Result type used in enable_if_convertible meta function.
56 // This can be an incomplete type, as only pointers to
57 // enable_if_convertible< ... >::type are used.
58 // We could have used void for this, but conversion to
59 // void* is just to easy.
66 // enable_if for use in adapted iterators constructors.
68 // In order to provide interoperability between adapted constant and
69 // mutable iterators, adapted iterators will usually provide templated
70 // conversion constructors of the following form
72 // template <class BaseIterator>
73 // class adapted_iterator :
74 // public iterator_adaptor< adapted_iterator<Iterator>, Iterator >
80 // template <class OtherIterator>
82 // OtherIterator const& it
83 // , typename enable_if_convertible<OtherIterator, Iterator>::type* = 0);
88 // enable_if_convertible is used to remove those overloads from the overload
89 // set that cannot be instantiated. For all practical purposes only overloads
90 // for constant/mutable interaction will remain. This has the advantage that
91 // meta functions like boost::is_convertible do not return false positives,
92 // as they can only look at the signature of the conversion constructor
93 // and not at the actual instantiation.
95 // enable_if_interoperable can be safely used in user code. It falls back to
96 // always enabled for compilers that don't support enable_if or is_convertible.
97 // There is no need for compiler specific workarounds in user code.
99 // The operators implementation relies on boost::is_convertible not returning
100 // false positives for user/library defined iterator types. See comments
101 // on operator implementation for consequences.
103 # if BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
105 template<typename From, typename To>
106 struct enable_if_convertible
108 typedef typename mpl::if_<
111 , is_convertible<From, To>
113 , detail::enable_type
118 # elif defined(BOOST_NO_IS_CONVERTIBLE) || defined(BOOST_NO_SFINAE)
120 template <class From, class To>
121 struct enable_if_convertible
123 typedef detail::enable_type type;
126 # elif BOOST_WORKAROUND(_MSC_FULL_VER, BOOST_TESTED_AT(13102292)) && BOOST_MSVC > 1300
128 // For some reason vc7.1 needs us to "cut off" instantiation
129 // of is_convertible in a few cases.
130 template<typename From, typename To>
131 struct enable_if_convertible
132 : iterators::enable_if<
135 , is_convertible<From, To>
137 , detail::enable_type
143 template<typename From, typename To>
144 struct enable_if_convertible
145 : iterators::enable_if<
146 is_convertible<From, To>
147 , detail::enable_type
154 // Default template argument handling for iterator_adaptor
158 // If T is use_default, return the result of invoking
159 // DefaultNullaryFn, otherwise return T.
160 template <class T, class DefaultNullaryFn>
163 is_same<T, use_default>
170 // A metafunction which computes an iterator_adaptor's base class,
171 // a specialization of iterator_facade.
180 struct iterator_adaptor_base
182 typedef iterator_facade<
185 # ifdef BOOST_ITERATOR_REF_CONSTNESS_KILLS_WRITABILITY
186 , typename detail::ia_dflt_help<
189 is_same<Reference,use_default>
190 , iterator_value<Base>
191 , remove_reference<Reference>
195 , typename detail::ia_dflt_help<
196 Value, iterator_value<Base>
200 , typename detail::ia_dflt_help<
202 , iterator_traversal<Base>
205 , typename detail::ia_dflt_help<
208 is_same<Value,use_default>
209 , iterator_reference<Base>
210 , add_reference<Value>
214 , typename detail::ia_dflt_help<
215 Difference, iterator_difference<Base>
221 // workaround for aC++ CR JAGaf33512
222 template <class Tr1, class Tr2>
223 inline void iterator_adaptor_assert_traversal ()
225 BOOST_STATIC_ASSERT((is_convertible<Tr1, Tr2>::value));
232 // The parameter ordering changed slightly with respect to former
233 // versions of iterator_adaptor The idea is that when the user needs
234 // to fiddle with the reference type it is highly likely that the
235 // iterator category has to be adjusted as well. Any of the
236 // following four template arguments may be ommitted or explicitly
237 // replaced by use_default.
239 // Value - if supplied, the value_type of the resulting iterator, unless
240 // const. If const, a conforming compiler strips constness for the
241 // value_type. If not supplied, iterator_traits<Base>::value_type is used
243 // Category - the traversal category of the resulting iterator. If not
244 // supplied, iterator_traversal<Base>::type is used.
246 // Reference - the reference type of the resulting iterator, and in
247 // particular, the result type of operator*(). If not supplied but
248 // Value is supplied, Value& is used. Otherwise
249 // iterator_traits<Base>::reference is used.
251 // Difference - the difference_type of the resulting iterator. If not
252 // supplied, iterator_traits<Base>::difference_type is used.
257 , class Value = use_default
258 , class Traversal = use_default
259 , class Reference = use_default
260 , class Difference = use_default
262 class iterator_adaptor
263 : public detail::iterator_adaptor_base<
264 Derived, Base, Value, Traversal, Reference, Difference
267 friend class iterator_core_access;
270 typedef typename detail::iterator_adaptor_base<
271 Derived, Base, Value, Traversal, Reference, Difference
274 iterator_adaptor() {}
276 explicit iterator_adaptor(Base const &iter)
281 typedef Base base_type;
283 Base const& base() const
284 { return m_iterator; }
287 // for convenience in derived classes
288 typedef iterator_adaptor<Derived,Base,Value,Traversal,Reference,Difference> iterator_adaptor_;
291 // lvalue access to the Base object for Derived
293 Base const& base_reference() const
294 { return m_iterator; }
296 Base& base_reference()
297 { return m_iterator; }
301 // Core iterator interface for iterator_facade. This is private
302 // to prevent temptation for Derived classes to use it, which
303 // will often result in an error. Derived classes should use
304 // base_reference(), above, to get direct access to m_iterator.
306 typename super_t::reference dereference() const
307 { return *m_iterator; }
310 class OtherDerived, class OtherIterator, class V, class C, class R, class D
312 bool equal(iterator_adaptor<OtherDerived, OtherIterator, V, C, R, D> const& x) const
314 // Maybe readd with same_distance
315 // BOOST_STATIC_ASSERT(
316 // (detail::same_category_and_difference<Derived,OtherDerived>::value)
318 return m_iterator == x.base();
321 typedef typename iterator_category_to_traversal<
322 typename super_t::iterator_category
323 >::type my_traversal;
325 # define BOOST_ITERATOR_ADAPTOR_ASSERT_TRAVERSAL(cat) \
326 detail::iterator_adaptor_assert_traversal<my_traversal, cat>();
328 void advance(typename super_t::difference_type n)
330 BOOST_ITERATOR_ADAPTOR_ASSERT_TRAVERSAL(random_access_traversal_tag)
334 void increment() { ++m_iterator; }
338 BOOST_ITERATOR_ADAPTOR_ASSERT_TRAVERSAL(bidirectional_traversal_tag)
343 class OtherDerived, class OtherIterator, class V, class C, class R, class D
345 typename super_t::difference_type distance_to(
346 iterator_adaptor<OtherDerived, OtherIterator, V, C, R, D> const& y) const
348 BOOST_ITERATOR_ADAPTOR_ASSERT_TRAVERSAL(random_access_traversal_tag)
349 // Maybe readd with same_distance
350 // BOOST_STATIC_ASSERT(
351 // (detail::same_category_and_difference<Derived,OtherDerived>::value)
353 return y.base() - m_iterator;
356 # undef BOOST_ITERATOR_ADAPTOR_ASSERT_TRAVERSAL
358 private: // data members
364 #include <boost/iterator/detail/config_undef.hpp>
366 #endif // BOOST_ITERATOR_ADAPTOR_23022003THW_HPP