[12] | 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 |
---|