|
1 // (C) Copyright David Abrahams 2002. |
|
2 // (C) Copyright Jeremy Siek 2002. |
|
3 // (C) Copyright Thomas Witt 2002. |
|
4 // Distributed under the Boost Software License, Version 1.0. (See |
|
5 // accompanying file LICENSE_1_0.txt or copy at |
|
6 // http://www.boost.org/LICENSE_1_0.txt) |
|
7 #ifndef BOOST_TRANSFORM_ITERATOR_23022003THW_HPP |
|
8 #define BOOST_TRANSFORM_ITERATOR_23022003THW_HPP |
|
9 |
|
10 #include <boost/function.hpp> |
|
11 #include <boost/iterator.hpp> |
|
12 #include <boost/iterator/detail/enable_if.hpp> |
|
13 #include <boost/iterator/iterator_adaptor.hpp> |
|
14 #include <boost/iterator/iterator_categories.hpp> |
|
15 #include <boost/mpl/not.hpp> |
|
16 #include <boost/mpl/bool.hpp> |
|
17 #include <boost/type_traits/function_traits.hpp> |
|
18 #include <boost/type_traits/is_const.hpp> |
|
19 #include <boost/type_traits/is_class.hpp> |
|
20 #include <boost/type_traits/is_function.hpp> |
|
21 #include <boost/type_traits/is_reference.hpp> |
|
22 #include <boost/type_traits/remove_const.hpp> |
|
23 #include <boost/type_traits/remove_reference.hpp> |
|
24 |
|
25 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1310)) |
|
26 # include <boost/type_traits/is_base_and_derived.hpp> |
|
27 |
|
28 #endif |
|
29 #include <boost/iterator/detail/config_def.hpp> |
|
30 |
|
31 |
|
32 namespace boost |
|
33 { |
|
34 template <class UnaryFunction, class Iterator, class Reference = use_default, class Value = use_default> |
|
35 class transform_iterator; |
|
36 |
|
37 namespace detail |
|
38 { |
|
39 |
|
40 template <class UnaryFunction> |
|
41 struct function_object_result |
|
42 { |
|
43 typedef typename UnaryFunction::result_type type; |
|
44 }; |
|
45 |
|
46 #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION |
|
47 template <class Return, class Argument> |
|
48 struct function_object_result<Return(*)(Argument)> |
|
49 { |
|
50 typedef Return type; |
|
51 }; |
|
52 #endif |
|
53 |
|
54 // Compute the iterator_adaptor instantiation to be used for transform_iterator |
|
55 template <class UnaryFunction, class Iterator, class Reference, class Value> |
|
56 struct transform_iterator_base |
|
57 { |
|
58 private: |
|
59 // By default, dereferencing the iterator yields the same as |
|
60 // the function. Do we need to adjust the way |
|
61 // function_object_result is computed for the standard |
|
62 // proposal (e.g. using Doug's result_of)? |
|
63 typedef typename ia_dflt_help< |
|
64 Reference |
|
65 , function_object_result<UnaryFunction> |
|
66 >::type reference; |
|
67 |
|
68 // To get the default for Value: remove any reference on the |
|
69 // result type, but retain any constness to signal |
|
70 // non-writability. Note that if we adopt Thomas' suggestion |
|
71 // to key non-writability *only* on the Reference argument, |
|
72 // we'd need to strip constness here as well. |
|
73 typedef typename ia_dflt_help< |
|
74 Value |
|
75 , remove_reference<reference> |
|
76 >::type cv_value_type; |
|
77 |
|
78 public: |
|
79 typedef iterator_adaptor< |
|
80 transform_iterator<UnaryFunction, Iterator, Reference, Value> |
|
81 , Iterator |
|
82 , cv_value_type |
|
83 , use_default // Leave the traversal category alone |
|
84 , reference |
|
85 > type; |
|
86 }; |
|
87 } |
|
88 |
|
89 template <class UnaryFunction, class Iterator, class Reference, class Value> |
|
90 class transform_iterator |
|
91 : public detail::transform_iterator_base<UnaryFunction, Iterator, Reference, Value>::type |
|
92 { |
|
93 typedef typename |
|
94 detail::transform_iterator_base<UnaryFunction, Iterator, Reference, Value>::type |
|
95 super_t; |
|
96 |
|
97 friend class iterator_core_access; |
|
98 |
|
99 public: |
|
100 transform_iterator() { } |
|
101 |
|
102 transform_iterator(Iterator const& x, UnaryFunction f) |
|
103 : super_t(x), m_f(f) { } |
|
104 |
|
105 explicit transform_iterator(Iterator const& x) |
|
106 : super_t(x) |
|
107 { |
|
108 // Pro8 is a little too aggressive about instantiating the |
|
109 // body of this function. |
|
110 #if !BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003)) |
|
111 // don't provide this constructor if UnaryFunction is a |
|
112 // function pointer type, since it will be 0. Too dangerous. |
|
113 BOOST_STATIC_ASSERT(is_class<UnaryFunction>::value); |
|
114 #endif |
|
115 } |
|
116 |
|
117 template< |
|
118 class OtherUnaryFunction |
|
119 , class OtherIterator |
|
120 , class OtherReference |
|
121 , class OtherValue> |
|
122 transform_iterator( |
|
123 transform_iterator<OtherUnaryFunction, OtherIterator, OtherReference, OtherValue> const& t |
|
124 , typename enable_if_convertible<OtherIterator, Iterator>::type* = 0 |
|
125 #if !BOOST_WORKAROUND(BOOST_MSVC, == 1310) |
|
126 , typename enable_if_convertible<OtherUnaryFunction, UnaryFunction>::type* = 0 |
|
127 #endif |
|
128 ) |
|
129 : super_t(t.base()), m_f(t.functor()) |
|
130 {} |
|
131 |
|
132 UnaryFunction functor() const |
|
133 { return m_f; } |
|
134 |
|
135 private: |
|
136 typename super_t::reference dereference() const |
|
137 { return m_f(*this->base()); } |
|
138 |
|
139 // Probably should be the initial base class so it can be |
|
140 // optimized away via EBO if it is an empty class. |
|
141 UnaryFunction m_f; |
|
142 }; |
|
143 |
|
144 template <class UnaryFunction, class Iterator> |
|
145 transform_iterator<UnaryFunction, Iterator> |
|
146 make_transform_iterator(Iterator it, UnaryFunction fun) |
|
147 { |
|
148 return transform_iterator<UnaryFunction, Iterator>(it, fun); |
|
149 } |
|
150 |
|
151 // Version which allows explicit specification of the UnaryFunction |
|
152 // type. |
|
153 // |
|
154 // This generator is not provided if UnaryFunction is a function |
|
155 // pointer type, because it's too dangerous: the default-constructed |
|
156 // function pointer in the iterator be 0, leading to a runtime |
|
157 // crash. |
|
158 template <class UnaryFunction, class Iterator> |
|
159 #if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) |
|
160 typename mpl::if_< |
|
161 #else |
|
162 typename iterators::enable_if< |
|
163 #endif |
|
164 is_class<UnaryFunction> // We should probably find a cheaper test than is_class<> |
|
165 , transform_iterator<UnaryFunction, Iterator> |
|
166 #if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) |
|
167 , int[3] |
|
168 #endif |
|
169 >::type |
|
170 make_transform_iterator(Iterator it) |
|
171 { |
|
172 return transform_iterator<UnaryFunction, Iterator>(it, UnaryFunction()); |
|
173 } |
|
174 |
|
175 #if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) && !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) |
|
176 template <class Return, class Argument, class Iterator> |
|
177 transform_iterator< Return (*)(Argument), Iterator, Return> |
|
178 make_transform_iterator(Iterator it, Return (*fun)(Argument)) |
|
179 { |
|
180 return transform_iterator<Return (*)(Argument), Iterator, Return>(it, fun); |
|
181 } |
|
182 #endif |
|
183 |
|
184 } // namespace boost |
|
185 |
|
186 #include <boost/iterator/detail/config_undef.hpp> |
|
187 |
|
188 #endif // BOOST_TRANSFORM_ITERATOR_23022003THW_HPP |