1 // (C) Copyright David Abrahams 2002.
\r
2 // (C) Copyright Jeremy Siek 2002.
\r
3 // (C) Copyright Thomas Witt 2002.
\r
4 // Distributed under the Boost Software License, Version 1.0. (See
\r
5 // accompanying file LICENSE_1_0.txt or copy at
\r
6 // http://www.boost.org/LICENSE_1_0.txt)
\r
7 #ifndef BOOST_ITERATOR_ADAPTOR_23022003THW_HPP
\r
8 #define BOOST_ITERATOR_ADAPTOR_23022003THW_HPP
\r
10 #include <boost/static_assert.hpp>
\r
11 #include <boost/iterator.hpp>
\r
12 #include <boost/detail/iterator.hpp>
\r
14 #include <boost/iterator/iterator_categories.hpp>
\r
15 #include <boost/iterator/iterator_facade.hpp>
\r
16 #include <boost/iterator/detail/enable_if.hpp>
\r
18 #include <boost/mpl/and.hpp>
\r
19 #include <boost/mpl/not.hpp>
\r
20 #include <boost/mpl/or.hpp>
\r
22 #include <boost/type_traits/is_same.hpp>
\r
23 #include <boost/type_traits/is_convertible.hpp>
\r
25 #ifdef BOOST_ITERATOR_REF_CONSTNESS_KILLS_WRITABILITY
\r
26 # include <boost/type_traits/remove_reference.hpp>
\r
28 # if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x610))
\r
29 # include <boost/type_traits/add_reference.hpp>
\r
33 # include <boost/type_traits/add_reference.hpp>
\r
36 #include <boost/iterator/detail/config_def.hpp>
\r
38 #include <boost/iterator/iterator_traits.hpp>
\r
42 // Used as a default template argument internally, merely to
\r
43 // indicate "use the default", this can also be passed by users
\r
44 // explicitly in order to specify that the default should be used.
\r
47 # ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
\r
48 // the incompleteness of use_default causes massive problems for
\r
49 // is_convertible (naturally). This workaround is fortunately not
\r
50 // needed for vc6/vc7.
\r
52 struct is_convertible<use_default,To>
\r
60 // Result type used in enable_if_convertible meta function.
\r
61 // This can be an incomplete type, as only pointers to
\r
62 // enable_if_convertible< ... >::type are used.
\r
63 // We could have used void for this, but conversion to
\r
64 // void* is just to easy.
\r
71 // enable_if for use in adapted iterators constructors.
\r
73 // In order to provide interoperability between adapted constant and
\r
74 // mutable iterators, adapted iterators will usually provide templated
\r
75 // conversion constructors of the following form
\r
77 // template <class BaseIterator>
\r
78 // class adapted_iterator :
\r
79 // public iterator_adaptor< adapted_iterator<Iterator>, Iterator >
\r
85 // template <class OtherIterator>
\r
86 // adapted_iterator(
\r
87 // OtherIterator const& it
\r
88 // , typename enable_if_convertible<OtherIterator, Iterator>::type* = 0);
\r
93 // enable_if_convertible is used to remove those overloads from the overload
\r
94 // set that cannot be instantiated. For all practical purposes only overloads
\r
95 // for constant/mutable interaction will remain. This has the advantage that
\r
96 // meta functions like boost::is_convertible do not return false positives,
\r
97 // as they can only look at the signature of the conversion constructor
\r
98 // and not at the actual instantiation.
\r
100 // enable_if_interoperable can be safely used in user code. It falls back to
\r
101 // always enabled for compilers that don't support enable_if or is_convertible.
\r
102 // There is no need for compiler specific workarounds in user code.
\r
104 // The operators implementation relies on boost::is_convertible not returning
\r
105 // false positives for user/library defined iterator types. See comments
\r
106 // on operator implementation for consequences.
\r
108 # if BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
\r
110 template<typename From, typename To>
\r
111 struct enable_if_convertible
\r
113 typedef typename mpl::if_<
\r
116 , is_convertible<From, To>
\r
118 , boost::detail::enable_type
\r
123 # elif defined(BOOST_NO_IS_CONVERTIBLE) || defined(BOOST_NO_SFINAE)
\r
125 template <class From, class To>
\r
126 struct enable_if_convertible
\r
128 typedef boost::detail::enable_type type;
\r
131 # elif BOOST_WORKAROUND(_MSC_FULL_VER, BOOST_TESTED_AT(13102292)) && BOOST_MSVC > 1300
\r
133 // For some reason vc7.1 needs us to "cut off" instantiation
\r
134 // of is_convertible in a few cases.
\r
135 template<typename From, typename To>
\r
136 struct enable_if_convertible
\r
137 : iterators::enable_if<
\r
140 , is_convertible<From, To>
\r
142 , boost::detail::enable_type
\r
148 template<typename From, typename To>
\r
149 struct enable_if_convertible
\r
150 : iterators::enable_if<
\r
151 is_convertible<From, To>
\r
152 , boost::detail::enable_type
\r
159 // Default template argument handling for iterator_adaptor
\r
163 // If T is use_default, return the result of invoking
\r
164 // DefaultNullaryFn, otherwise return T.
\r
165 template <class T, class DefaultNullaryFn>
\r
166 struct ia_dflt_help
\r
168 is_same<T, use_default>
\r
175 // A metafunction which computes an iterator_adaptor's base class,
\r
176 // a specialization of iterator_facade.
\r
185 struct iterator_adaptor_base
\r
187 typedef iterator_facade<
\r
190 # ifdef BOOST_ITERATOR_REF_CONSTNESS_KILLS_WRITABILITY
\r
191 , typename boost::detail::ia_dflt_help<
\r
194 is_same<Reference,use_default>
\r
195 , iterator_value<Base>
\r
196 , remove_reference<Reference>
\r
200 , typename boost::detail::ia_dflt_help<
\r
201 Value, iterator_value<Base>
\r
205 , typename boost::detail::ia_dflt_help<
\r
207 , iterator_traversal<Base>
\r
210 , typename boost::detail::ia_dflt_help<
\r
213 is_same<Value,use_default>
\r
214 , iterator_reference<Base>
\r
215 , add_reference<Value>
\r
219 , typename boost::detail::ia_dflt_help<
\r
220 Difference, iterator_difference<Base>
\r
226 // workaround for aC++ CR JAGaf33512
\r
227 template <class Tr1, class Tr2>
\r
228 inline void iterator_adaptor_assert_traversal ()
\r
230 BOOST_STATIC_ASSERT((is_convertible<Tr1, Tr2>::value));
\r
235 // Iterator Adaptor
\r
237 // The parameter ordering changed slightly with respect to former
\r
238 // versions of iterator_adaptor The idea is that when the user needs
\r
239 // to fiddle with the reference type it is highly likely that the
\r
240 // iterator category has to be adjusted as well. Any of the
\r
241 // following four template arguments may be ommitted or explicitly
\r
242 // replaced by use_default.
\r
244 // Value - if supplied, the value_type of the resulting iterator, unless
\r
245 // const. If const, a conforming compiler strips constness for the
\r
246 // value_type. If not supplied, iterator_traits<Base>::value_type is used
\r
248 // Category - the traversal category of the resulting iterator. If not
\r
249 // supplied, iterator_traversal<Base>::type is used.
\r
251 // Reference - the reference type of the resulting iterator, and in
\r
252 // particular, the result type of operator*(). If not supplied but
\r
253 // Value is supplied, Value& is used. Otherwise
\r
254 // iterator_traits<Base>::reference is used.
\r
256 // Difference - the difference_type of the resulting iterator. If not
\r
257 // supplied, iterator_traits<Base>::difference_type is used.
\r
262 , class Value = use_default
\r
263 , class Traversal = use_default
\r
264 , class Reference = use_default
\r
265 , class Difference = use_default
\r
267 class iterator_adaptor
\r
268 : public boost::detail::iterator_adaptor_base<
\r
269 Derived, Base, Value, Traversal, Reference, Difference
\r
272 friend class iterator_core_access;
\r
275 typedef typename boost::detail::iterator_adaptor_base<
\r
276 Derived, Base, Value, Traversal, Reference, Difference
\r
279 iterator_adaptor() {}
\r
281 explicit iterator_adaptor(Base const &iter)
\r
286 typedef Base base_type;
\r
288 Base const& base() const
\r
289 { return m_iterator; }
\r
292 // for convenience in derived classes
\r
293 typedef iterator_adaptor<Derived,Base,Value,Traversal,Reference,Difference> iterator_adaptor_;
\r
296 // lvalue access to the Base object for Derived
\r
298 Base const& base_reference() const
\r
299 { return m_iterator; }
\r
301 Base& base_reference()
\r
302 { return m_iterator; }
\r
306 // Core iterator interface for iterator_facade. This is private
\r
307 // to prevent temptation for Derived classes to use it, which
\r
308 // will often result in an error. Derived classes should use
\r
309 // base_reference(), above, to get direct access to m_iterator.
\r
311 typename super_t::reference dereference() const
\r
312 { return *m_iterator; }
\r
315 class OtherDerived, class OtherIterator, class V, class C, class R, class D
\r
317 bool equal(iterator_adaptor<OtherDerived, OtherIterator, V, C, R, D> const& x) const
\r
319 // Maybe readd with same_distance
\r
320 // BOOST_STATIC_ASSERT(
\r
321 // (detail::same_category_and_difference<Derived,OtherDerived>::value)
\r
323 return m_iterator == x.base();
\r
326 typedef typename iterator_category_to_traversal<
\r
327 typename super_t::iterator_category
\r
328 >::type my_traversal;
\r
330 # define BOOST_ITERATOR_ADAPTOR_ASSERT_TRAVERSAL(cat) \
\r
331 boost::detail::iterator_adaptor_assert_traversal<my_traversal, cat>();
\r
333 void advance(typename super_t::difference_type n)
\r
335 BOOST_ITERATOR_ADAPTOR_ASSERT_TRAVERSAL(random_access_traversal_tag)
\r
339 void increment() { ++m_iterator; }
\r
343 BOOST_ITERATOR_ADAPTOR_ASSERT_TRAVERSAL(bidirectional_traversal_tag)
\r
348 class OtherDerived, class OtherIterator, class V, class C, class R, class D
\r
350 typename super_t::difference_type distance_to(
\r
351 iterator_adaptor<OtherDerived, OtherIterator, V, C, R, D> const& y) const
\r
353 BOOST_ITERATOR_ADAPTOR_ASSERT_TRAVERSAL(random_access_traversal_tag)
\r
354 // Maybe readd with same_distance
\r
355 // BOOST_STATIC_ASSERT(
\r
356 // (detail::same_category_and_difference<Derived,OtherDerived>::value)
\r
358 return y.base() - m_iterator;
\r
361 # undef BOOST_ITERATOR_ADAPTOR_ASSERT_TRAVERSAL
\r
363 private: // data members
\r
367 } // namespace boost
\r
369 #include <boost/iterator/detail/config_undef.hpp>
\r
371 #endif // BOOST_ITERATOR_ADAPTOR_23022003THW_HPP
\r