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 | # if defined(BOOST_MSVC) && (BOOST_MSVC == 1400) /* |
18 | > warning C4180: qualifier applied to function type has no meaning; ignored |
19 | Peter Dimov wrote: |
20 | This warning is caused by an overload resolution bug in VC8 that cannot be |
21 | worked around and will probably not be fixed by MS in the VC8 line. The |
22 | problematic overload is only instantiated and never called, and the code |
23 | works correctly. */ |
24 | # pragma warning(disable: 4180) |
25 | # endif |
26 | |
27 | # include <boost/bind.hpp> |
28 | # include <boost/bind/protect.hpp> |
29 | |
30 | namespace boost { namespace python { |
31 | |
32 | namespace detail |
33 | { |
34 | // Adds an additional layer of binding to |
35 | // objects::make_iterator(...), which allows us to pass member |
36 | // function and member data pointers. |
37 | template <class Target, class Accessor1, class Accessor2, class NextPolicies> |
38 | inline object make_iterator( |
39 | Accessor1 get_start |
40 | , Accessor2 get_finish |
41 | , NextPolicies next_policies |
42 | , Target&(*)() |
43 | ) |
44 | { |
45 | return objects::make_iterator_function<Target>( |
46 | boost::protect(boost::bind(get_start, _1)) |
47 | , boost::protect(boost::bind(get_finish, _1)) |
48 | , next_policies |
49 | ); |
50 | } |
51 | |
52 | // Guts of template class iterators<>, below. |
53 | template <bool const_ = false> |
54 | struct iterators_impl |
55 | { |
56 | template <class T> |
57 | struct apply |
58 | { |
59 | typedef typename T::iterator iterator; |
60 | static iterator begin(T& x) { return x.begin(); } |
61 | static iterator end(T& x) { return x.end(); } |
62 | }; |
63 | }; |
64 | |
65 | template <> |
66 | struct iterators_impl<true> |
67 | { |
68 | template <class T> |
69 | struct apply |
70 | { |
71 | typedef typename T::const_iterator iterator; |
72 | static iterator begin(T& x) { return x.begin(); } |
73 | static iterator end(T& x) { return x.end(); } |
74 | }; |
75 | }; |
76 | } |
77 | |
78 | // An "ordinary function generator" which contains static begin(x) and |
79 | // end(x) functions that invoke T::begin() and T::end(), respectively. |
80 | template <class T> |
81 | struct iterators |
82 | : detail::iterators_impl< |
83 | boost::is_const<T>::value |
84 | >::template apply<T> |
85 | { |
86 | }; |
87 | |
88 | // Create an iterator-building function which uses the given |
89 | // accessors. Deduce the Target type from the accessors. The iterator |
90 | // returns copies of the inderlying elements. |
91 | template <class Accessor1, class Accessor2> |
92 | object range(Accessor1 start, Accessor2 finish) |
93 | { |
94 | return detail::make_iterator( |
95 | start, finish |
96 | , objects::default_iterator_call_policies() |
97 | , detail::target(start) |
98 | ); |
99 | } |
100 | |
101 | // Create an iterator-building function which uses the given accessors |
102 | // and next() policies. Deduce the Target type. |
103 | template <class NextPolicies, class Accessor1, class Accessor2> |
104 | object range(Accessor1 start, Accessor2 finish, NextPolicies* = 0) |
105 | { |
106 | return detail::make_iterator(start, finish, NextPolicies(), detail::target(start)); |
107 | } |
108 | |
109 | // Create an iterator-building function which uses the given accessors |
110 | // and next() policies, operating on the given Target type |
111 | template <class NextPolicies, class Target, class Accessor1, class Accessor2> |
112 | object range(Accessor1 start, Accessor2 finish, NextPolicies* = 0, boost::type<Target>* = 0) |
113 | { |
114 | // typedef typename add_reference<Target>::type target; |
115 | return detail::make_iterator(start, finish, NextPolicies(), (Target&(*)())0); |
116 | } |
117 | |
118 | // A Python callable object which produces an iterator traversing |
119 | // [x.begin(), x.end()), where x is an instance of the Container |
120 | // type. NextPolicies are used as the CallPolicies for the iterator's |
121 | // next() function. |
122 | template <class Container |
123 | , class NextPolicies = objects::default_iterator_call_policies> |
124 | struct iterator : object |
125 | { |
126 | iterator() |
127 | : object( |
128 | python::range<NextPolicies>( |
129 | &iterators<Container>::begin, &iterators<Container>::end |
130 | )) |
131 | { |
132 | } |
133 | }; |
134 | |
135 | }} // namespace boost::python |
136 | |
137 | #endif // ITERATOR_DWA2002512_HPP |
138 | |