1 // (C) Copyright Jeremy Siek 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
6 // Revision History
7 // 22 Nov 2002 Thomas Witt
8 // Added interoperability check.
9 // 28 Oct 2002 Jeremy Siek
10 // Updated for new iterator adaptors.
11 // 08 Mar 2001 Jeremy Siek
12 // Moved test of transform iterator into its own file. It to
13 // to be in iterator_adaptor_test.cpp.
14
15 #include <boost/assert.hpp>
16 #include <boost/config.hpp>
17 #include <algorithm>
18 #include <boost/iterator/transform_iterator.hpp>
19 #include <boost/iterator/iterator_concepts.hpp>
20 #include <boost/iterator/new_iterator_tests.hpp>
21 #include <boost/pending/iterator_tests.hpp>
22 #include <boost/bind.hpp>
23 #include <boost/concept_check.hpp>
24
25 #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
26 namespace boost { namespace detail
27 {
28 template<> struct function_object_result<int (*)(int)>
29 {
30 typedef int type;
31 };
32 }}
33 #endif
34
35 struct mult_functor {
36 // Functors used with transform_iterator must be
37 // DefaultConstructible, as the transform_iterator must be
38 // DefaultConstructible to satisfy the requirements for
39 // TrivialIterator.
mult_functormult_functor40 mult_functor() { }
mult_functormult_functor41 mult_functor(int aa) : a(aa) { }
operator ()mult_functor42 int operator()(int b) const { return a * b; }
43 int a;
44 };
45
46 struct adaptable_mult_functor
47 : mult_functor
48 {
49 typedef int result_type;
50 typedef int argument_type;
51 // Functors used with transform_iterator must be
52 // DefaultConstructible, as the transform_iterator must be
53 // DefaultConstructible to satisfy the requirements for
54 // TrivialIterator.
adaptable_mult_functoradaptable_mult_functor55 adaptable_mult_functor() { }
adaptable_mult_functoradaptable_mult_functor56 adaptable_mult_functor(int aa) : mult_functor(aa) { }
57 };
58
59
60 struct const_select_first
61 {
62 typedef int const& result_type;
63
operator ()const_select_first64 int const& operator()(std::pair<int, int>const& p) const
65 {
66 return p.first;
67 }
68 };
69
70 struct select_first
71 : const_select_first // derivation to allow conversions
72 {
73 typedef int& result_type;
74
operator ()select_first75 int& operator()(std::pair<int, int>& p) const
76 {
77 return p.first;
78 }
79 };
80
81 struct select_second
82 {
83 typedef int& result_type;
84
operator ()select_second85 int& operator()(std::pair<int, int>& p) const
86 {
87 return p.second;
88 }
89 };
90
91 struct value_select_first
92 {
93 typedef int result_type;
94
operator ()value_select_first95 int operator()(std::pair<int, int>const& p) const
96 {
97 return p.first;
98 }
99 };
100
mult_2(int arg)101 int mult_2(int arg)
102 {
103 return arg*2;
104 }
105
106 struct polymorphic_mult_functor
107 {
108 //Implement result_of protocol
109 template <class FArgs> struct result;
110 template <class F, class T> struct result<const F(T )> {typedef T type;};
111 template <class F, class T> struct result<const F(T& )> {typedef T type;};
112 template <class F, class T> struct result<const F(const T&)> {typedef T type;};
113 template <class F, class T> struct result<F(T )> {typedef void type;};
114 template <class F, class T> struct result<F(T& )> {typedef void type;};
115 template <class F, class T> struct result<F(const T&)> {typedef void type;};
116
117 template <class T>
operator ()polymorphic_mult_functor118 T operator()(const T& _arg) const {return _arg*2;}
119 template <class T>
operator ()polymorphic_mult_functor120 void operator()(const T& _arg) { BOOST_ASSERT(0); }
121 };
122
123 int
main()124 main()
125 {
126 const int N = 10;
127
128 // Concept checks
129 {
130 typedef boost::transform_iterator<adaptable_mult_functor, int*> iter_t;
131 typedef boost::transform_iterator<adaptable_mult_functor, int const*> c_iter_t;
132
133 boost::function_requires< boost_concepts::InteroperableIteratorConcept<iter_t, c_iter_t> >();
134 }
135
136 // Test transform_iterator
137 {
138 int x[N], y[N];
139 for (int k = 0; k < N; ++k)
140 x[k] = k;
141 std::copy(x, x + N, y);
142
143 for (int k2 = 0; k2 < N; ++k2)
144 x[k2] = x[k2] * 2;
145
146 typedef boost::transform_iterator<adaptable_mult_functor, int*> iter_t;
147 iter_t i(y, adaptable_mult_functor(2));
148 boost::input_iterator_test(i, x[0], x[1]);
149 boost::input_iterator_test(iter_t(&y[0], adaptable_mult_functor(2)), x[0], x[1]);
150
151 boost::random_access_readable_iterator_test(i, N, x);
152 }
153
154 // Test transform_iterator non adaptable functor
155 {
156 int x[N], y[N];
157 for (int k = 0; k < N; ++k)
158 x[k] = k;
159 std::copy(x, x + N, y);
160
161 for (int k2 = 0; k2 < N; ++k2)
162 x[k2] = x[k2] * 2;
163
164 typedef boost::transform_iterator<mult_functor, int*, int> iter_t;
165 iter_t i(y, mult_functor(2));
166 boost::input_iterator_test(i, x[0], x[1]);
167 boost::input_iterator_test(iter_t(&y[0], mult_functor(2)), x[0], x[1]);
168
169 boost::random_access_readable_iterator_test(i, N, x);
170 }
171
172 // Test transform_iterator default argument handling
173 {
174 {
175 typedef boost::transform_iterator<adaptable_mult_functor, int*, float> iter_t;
176 BOOST_STATIC_ASSERT((boost::is_same<iter_t::reference, float>::value));
177 BOOST_STATIC_ASSERT((boost::is_same<iter_t::value_type, float>::value));
178 }
179
180 {
181 typedef boost::transform_iterator<adaptable_mult_functor, int*, boost::use_default, float> iter_t;
182 BOOST_STATIC_ASSERT((boost::is_same<iter_t::reference, int>::value));
183 BOOST_STATIC_ASSERT((boost::is_same<iter_t::value_type, float>::value));
184 }
185
186 {
187 typedef boost::transform_iterator<adaptable_mult_functor, int*, float, double> iter_t;
188 BOOST_STATIC_ASSERT((boost::is_same<iter_t::reference, float>::value));
189 BOOST_STATIC_ASSERT((boost::is_same<iter_t::value_type, double>::value));
190 }
191 }
192
193 // Test transform_iterator with function pointers
194 {
195 int x[N], y[N];
196 for (int k = 0; k < N; ++k)
197 x[k] = k;
198 std::copy(x, x + N, y);
199
200 for (int k2 = 0; k2 < N; ++k2)
201 x[k2] = x[k2] * 2;
202
203 boost::input_iterator_test(
204 boost::make_transform_iterator(y, mult_2), x[0], x[1]);
205
206 boost::input_iterator_test(
207 boost::make_transform_iterator(&y[0], mult_2), x[0], x[1]);
208
209 boost::random_access_readable_iterator_test(
210 boost::make_transform_iterator(y, mult_2), N, x);
211
212 }
213
214 // Test transform_iterator as projection iterator
215 {
216 typedef std::pair<int, int> pair_t;
217
218 int x[N];
219 int y[N];
220 pair_t values[N];
221
222 for(int i = 0; i < N; ++i) {
223
224 x[i] = i;
225 y[i] = N - (i + 1);
226
227 }
228
229 std::copy(
230 x
231 , x + N
232 , boost::make_transform_iterator((pair_t*)values, select_first())
233 );
234
235 std::copy(
236 y
237 , y + N
238 , boost::make_transform_iterator((pair_t*)values, select_second())
239 );
240
241 boost::random_access_readable_iterator_test(
242 boost::make_transform_iterator((pair_t*)values, value_select_first())
243 , N
244 , x
245 );
246
247 boost::random_access_readable_iterator_test(
248 boost::make_transform_iterator((pair_t*)values, const_select_first())
249 , N, x
250 );
251
252 boost::constant_lvalue_iterator_test(
253 boost::make_transform_iterator((pair_t*)values, const_select_first()), x[0]);
254
255 boost::non_const_lvalue_iterator_test(
256 boost::make_transform_iterator((pair_t*)values, select_first()), x[0], 17);
257
258 boost::const_nonconst_iterator_test(
259 ++boost::make_transform_iterator((pair_t*)values, select_first())
260 , boost::make_transform_iterator((pair_t*)values, const_select_first())
261 );
262 }
263
264 // Test transform_iterator with polymorphic object function
265 {
266 int x[N], y[N];
267 for (int k = 0; k < N; ++k)
268 x[k] = k;
269 std::copy(x, x + N, y);
270
271 for (int k2 = 0; k2 < N; ++k2)
272 x[k2] = x[k2] * 2;
273
274 boost::input_iterator_test(
275 boost::make_transform_iterator(y, polymorphic_mult_functor()), x[0], x[1]);
276
277 boost::input_iterator_test(
278 boost::make_transform_iterator(&y[0], polymorphic_mult_functor()), x[0], x[1]);
279
280 boost::random_access_readable_iterator_test(
281 boost::make_transform_iterator(y, polymorphic_mult_functor()), N, x);
282 }
283
284 return boost::report_errors();
285 }
286