[857] | 1 | // Copyright David Abrahams 2002.
|
---|
| 2 | // Distributed under the Boost Software License, Version 1.0. (See
|
---|
| 3 | // accompanying file LICENSE_1_0.txt or copy at
|
---|
| 4 | // http://www.boost.org/LICENSE_1_0.txt)
|
---|
| 5 | #ifndef ITERATOR_DWA2002512_HPP
|
---|
| 6 | # define ITERATOR_DWA2002512_HPP
|
---|
| 7 |
|
---|
| 8 | # include <boost/python/detail/prefix.hpp>
|
---|
| 9 |
|
---|
| 10 | # include <boost/python/detail/target.hpp>
|
---|
| 11 | # include <boost/python/object/iterator.hpp>
|
---|
| 12 | # include <boost/python/object_core.hpp>
|
---|
| 13 |
|
---|
| 14 | # include <boost/type_traits/cv_traits.hpp>
|
---|
| 15 | # include <boost/type_traits/transform_traits.hpp>
|
---|
| 16 |
|
---|
| 17 | # include <boost/bind.hpp>
|
---|
| 18 | # include <boost/bind/protect.hpp>
|
---|
| 19 |
|
---|
| 20 | namespace boost { namespace python {
|
---|
| 21 |
|
---|
| 22 | namespace detail
|
---|
| 23 | {
|
---|
| 24 | // Adds an additional layer of binding to
|
---|
| 25 | // objects::make_iterator(...), which allows us to pass member
|
---|
| 26 | // function and member data pointers.
|
---|
| 27 | template <class Target, class Accessor1, class Accessor2, class NextPolicies>
|
---|
| 28 | inline object make_iterator(
|
---|
| 29 | Accessor1 get_start
|
---|
| 30 | , Accessor2 get_finish
|
---|
| 31 | , NextPolicies next_policies
|
---|
| 32 | , Target&(*)()
|
---|
| 33 | )
|
---|
| 34 | {
|
---|
| 35 | return objects::make_iterator_function<Target>(
|
---|
| 36 | boost::protect(boost::bind(get_start, _1))
|
---|
| 37 | , boost::protect(boost::bind(get_finish, _1))
|
---|
| 38 | , next_policies
|
---|
| 39 | );
|
---|
| 40 | }
|
---|
| 41 |
|
---|
| 42 | // Guts of template class iterators<>, below.
|
---|
| 43 | template <bool const_ = false>
|
---|
| 44 | struct iterators_impl
|
---|
| 45 | {
|
---|
| 46 | template <class T>
|
---|
| 47 | struct apply
|
---|
| 48 | {
|
---|
| 49 | typedef typename T::iterator iterator;
|
---|
| 50 | static iterator begin(T& x) { return x.begin(); }
|
---|
| 51 | static iterator end(T& x) { return x.end(); }
|
---|
| 52 | };
|
---|
| 53 | };
|
---|
| 54 |
|
---|
| 55 | template <>
|
---|
| 56 | struct iterators_impl<true>
|
---|
| 57 | {
|
---|
| 58 | template <class T>
|
---|
| 59 | struct apply
|
---|
| 60 | {
|
---|
| 61 | typedef typename T::const_iterator iterator;
|
---|
| 62 | static iterator begin(T& x) { return x.begin(); }
|
---|
| 63 | static iterator end(T& x) { return x.end(); }
|
---|
| 64 | };
|
---|
| 65 | };
|
---|
| 66 | }
|
---|
| 67 |
|
---|
| 68 | // An "ordinary function generator" which contains static begin(x) and
|
---|
| 69 | // end(x) functions that invoke T::begin() and T::end(), respectively.
|
---|
| 70 | template <class T>
|
---|
| 71 | struct iterators
|
---|
| 72 | : detail::iterators_impl<
|
---|
| 73 | boost::is_const<T>::value
|
---|
| 74 | >::template apply<T>
|
---|
| 75 | {
|
---|
| 76 | };
|
---|
| 77 |
|
---|
| 78 | // Create an iterator-building function which uses the given
|
---|
| 79 | // accessors. Deduce the Target type from the accessors. The iterator
|
---|
| 80 | // returns copies of the inderlying elements.
|
---|
| 81 | template <class Accessor1, class Accessor2>
|
---|
| 82 | object range(Accessor1 start, Accessor2 finish)
|
---|
| 83 | {
|
---|
| 84 | return detail::make_iterator(
|
---|
| 85 | start, finish
|
---|
| 86 | , objects::default_iterator_call_policies()
|
---|
| 87 | , detail::target(start)
|
---|
| 88 | );
|
---|
| 89 | }
|
---|
| 90 |
|
---|
| 91 | // Create an iterator-building function which uses the given accessors
|
---|
| 92 | // and next() policies. Deduce the Target type.
|
---|
| 93 | template <class NextPolicies, class Accessor1, class Accessor2>
|
---|
| 94 | object range(Accessor1 start, Accessor2 finish, NextPolicies* = 0)
|
---|
| 95 | {
|
---|
| 96 | return detail::make_iterator(start, finish, NextPolicies(), detail::target(start));
|
---|
| 97 | }
|
---|
| 98 |
|
---|
| 99 | // Create an iterator-building function which uses the given accessors
|
---|
| 100 | // and next() policies, operating on the given Target type
|
---|
| 101 | template <class NextPolicies, class Target, class Accessor1, class Accessor2>
|
---|
| 102 | object range(Accessor1 start, Accessor2 finish, NextPolicies* = 0, boost::type<Target>* = 0)
|
---|
| 103 | {
|
---|
| 104 | // typedef typename add_reference<Target>::type target;
|
---|
| 105 | return detail::make_iterator(start, finish, NextPolicies(), (Target&(*)())0);
|
---|
| 106 | }
|
---|
| 107 |
|
---|
| 108 | // A Python callable object which produces an iterator traversing
|
---|
| 109 | // [x.begin(), x.end()), where x is an instance of the Container
|
---|
| 110 | // type. NextPolicies are used as the CallPolicies for the iterator's
|
---|
| 111 | // next() function.
|
---|
| 112 | template <class Container
|
---|
| 113 | , class NextPolicies = objects::default_iterator_call_policies>
|
---|
| 114 | struct iterator : object
|
---|
| 115 | {
|
---|
| 116 | iterator()
|
---|
| 117 | : object(
|
---|
| 118 | python::range<NextPolicies>(
|
---|
| 119 | &iterators<Container>::begin, &iterators<Container>::end
|
---|
| 120 | ))
|
---|
| 121 | {
|
---|
| 122 | }
|
---|
| 123 | };
|
---|
| 124 |
|
---|
| 125 | }} // namespace boost::python
|
---|
| 126 |
|
---|
| 127 | #endif // ITERATOR_DWA2002512_HPP
|
---|