1 // (C) Copyright David Abrahams 2002.
2 // (C) Copyright Jeremy Siek 2002.
3 // (C) Copyright Thomas Witt 2002.
4 // Permission to copy, use, modify,
5 // sell and distribute this software is granted provided this
6 // copyright notice appears in all copies. This software is provided
7 // "as is" without express or implied warranty, and with no claim as
8 // to its suitability for any purpose.
9 #ifndef BOOST_ITERATOR_ADAPTOR_23022003THW_HPP
10 #define BOOST_ITERATOR_ADAPTOR_23022003THW_HPP
12 #include <boost/static_assert.hpp>
13 #include <boost/iterator.hpp>
14 #include <boost/detail/iterator.hpp>
16 #include <boost/iterator/iterator_categories.hpp>
17 #include <boost/iterator/iterator_facade.hpp>
18 #include <boost/iterator/detail/enable_if.hpp>
20 #include <boost/mpl/and.hpp>
21 #include <boost/mpl/not.hpp>
22 #include <boost/mpl/or.hpp>
24 #include <boost/python/detail/is_xxx.hpp>
26 #include <boost/type_traits/is_same.hpp>
27 #include <boost/type_traits/is_convertible.hpp>
29 #ifdef BOOST_ITERATOR_REF_CONSTNESS_KILLS_WRITABILITY
30 # include <boost/type_traits/remove_reference.hpp>
32 # include <boost/type_traits/add_reference.hpp>
35 #include <boost/iterator/detail/config_def.hpp>
37 #include <boost/iterator/iterator_traits.hpp>
41 // Used as a default template argument internally, merely to
42 // indicate "use the default", this can also be passed by users
43 // explicitly in order to specify that the default should be used.
46 # ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
47 // the incompleteness of use_default causes massive problems for
48 // is_convertible (naturally). This workaround is fortunately not
49 // needed for vc6/vc7.
51 struct is_convertible<use_default,To>
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.
70 // enable_if for use in adapted iterators constructors.
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
76 // template <class BaseIterator>
77 // class adapted_iterator :
78 // public iterator_adaptor< adapted_iterator<Iterator>, Iterator >
84 // template <class OtherIterator>
86 // OtherIterator const& it
87 // , typename enable_if_convertible<OtherIterator, Iterator>::type* = 0);
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.
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.
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.
107 # if defined(BOOST_NO_IS_CONVERTIBLE) || defined(BOOST_NO_SFINAE)
109 template <class From, class To>
110 struct enable_if_convertible
112 typedef detail::enable_type type;
115 # elif BOOST_WORKAROUND(_MSC_FULL_VER, BOOST_TESTED_AT(13102292)) && BOOST_MSVC > 1300
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<
124 , is_convertible<From, To>
126 , detail::enable_type
132 template<typename From, typename To>
133 struct enable_if_convertible
134 : iterators::enable_if<
135 is_convertible<From, To>
136 , detail::enable_type
143 // Default template argument handling for iterator_adaptor
147 // If T is use_default, return the result of invoking
148 // DefaultNullaryFn, otherwise return T.
149 template <class T, class DefaultNullaryFn>
152 is_same<T, use_default>
159 // A metafunction which computes an iterator_adaptor's base class,
160 // a specialization of iterator_facade.
169 struct iterator_adaptor_base
171 typedef iterator_facade<
174 # ifdef BOOST_ITERATOR_REF_CONSTNESS_KILLS_WRITABILITY
175 , typename detail::ia_dflt_help<
178 is_same<Reference,use_default>
179 , iterator_value<Base>
180 , remove_reference<Reference>
184 , typename detail::ia_dflt_help<
185 Value, iterator_value<Base>
189 , typename detail::ia_dflt_help<
191 , iterator_traversal<Base>
194 , typename detail::ia_dflt_help<
197 is_same<Value,use_default>
198 , iterator_reference<Base>
199 , add_reference<Value>
203 , typename detail::ia_dflt_help<
204 Difference, iterator_difference<Base>
209 template <class T> int static_assert_convertible_to(T);
215 // The parameter ordering changed slightly with respect to former
216 // versions of iterator_adaptor The idea is that when the user needs
217 // to fiddle with the reference type it is highly likely that the
218 // iterator category has to be adjusted as well. Any of the
219 // following four template arguments may be ommitted or explicitly
220 // replaced by use_default.
222 // Value - if supplied, the value_type of the resulting iterator, unless
223 // const. If const, a conforming compiler strips constness for the
224 // value_type. If not supplied, iterator_traits<Base>::value_type is used
226 // Category - the traversal category of the resulting iterator. If not
227 // supplied, iterator_traversal<Base>::type is used.
229 // Reference - the reference type of the resulting iterator, and in
230 // particular, the result type of operator*(). If not supplied but
231 // Value is supplied, Value& is used. Otherwise
232 // iterator_traits<Base>::reference is used.
234 // Difference - the difference_type of the resulting iterator. If not
235 // supplied, iterator_traits<Base>::difference_type is used.
240 , class Value = use_default
241 , class Traversal = use_default
242 , class Reference = use_default
243 , class Difference = use_default
245 class iterator_adaptor
246 : public detail::iterator_adaptor_base<
247 Derived, Base, Value, Traversal, Reference, Difference
250 friend class iterator_core_access;
252 typedef typename detail::iterator_adaptor_base<
253 Derived, Base, Value, Traversal, Reference, Difference
257 iterator_adaptor() {}
259 explicit iterator_adaptor(Base const &iter)
264 Base const& base() const
265 { return m_iterator; }
269 // lvalue access to the Base object for Derived
271 Base const& base_reference() const
272 { return m_iterator; }
274 Base& base_reference()
275 { return m_iterator; }
279 // Core iterator interface for iterator_facade. This is private
280 // to prevent temptation for Derived classes to use it, which
281 // will often result in an error. Derived classes should use
282 // base_reference(), above, to get direct access to m_iterator.
284 typename super_t::reference dereference() const
285 { return *m_iterator; }
288 class OtherDerived, class OtherIterator, class V, class C, class R, class D
290 bool equal(iterator_adaptor<OtherDerived, OtherIterator, V, C, R, D> const& x) const
292 // Maybe readd with same_distance
293 // BOOST_STATIC_ASSERT(
294 // (detail::same_category_and_difference<Derived,OtherDerived>::value)
296 return m_iterator == x.base();
299 typedef typename iterator_category_to_traversal<
300 typename super_t::iterator_category
301 >::type my_traversal;
303 # define BOOST_ITERATOR_ADAPTOR_ASSERT_TRAVERSAL(cat) \
304 typedef int assertion[sizeof(detail::static_assert_convertible_to<cat>(my_traversal()))];
305 // BOOST_STATIC_ASSERT((is_convertible<my_traversal,cat>::value));
307 void advance(typename super_t::difference_type n)
309 BOOST_ITERATOR_ADAPTOR_ASSERT_TRAVERSAL(random_access_traversal_tag)
313 void increment() { ++m_iterator; }
317 BOOST_ITERATOR_ADAPTOR_ASSERT_TRAVERSAL(bidirectional_traversal_tag)
322 class OtherDerived, class OtherIterator, class V, class C, class R, class D
324 typename super_t::difference_type distance_to(
325 iterator_adaptor<OtherDerived, OtherIterator, V, C, R, D> const& y) const
327 BOOST_ITERATOR_ADAPTOR_ASSERT_TRAVERSAL(random_access_traversal_tag)
328 // Maybe readd with same_distance
329 // BOOST_STATIC_ASSERT(
330 // (detail::same_category_and_difference<Derived,OtherDerived>::value)
332 return y.base() - m_iterator;
335 # undef BOOST_ITERATOR_ADAPTOR_ASSERT_TRAVERSAL
337 private: // data members
343 #include <boost/iterator/detail/config_undef.hpp>
345 #endif // BOOST_ITERATOR_ADAPTOR_23022003THW_HPP