1// Boost.Range library
2//
3// Copyright Neil Groves 2010. Use, modification and
4// distribution is subject to the Boost Software License, Version
5// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
6// http://www.boost.org/LICENSE_1_0.txt)
7//
8#ifndef BOOST_RANGE_ADAPTOR_TEST_TYPE_ERASED_TEST_HPP
9#define BOOST_RANGE_ADAPTOR_TEST_TYPE_ERASED_TEST_HPP
10
11#include <boost/range/algorithm/fill.hpp>
12#include <boost/range/algorithm_ext/push_back.hpp>
13#include <boost/assign.hpp>
14#include <boost/test/test_tools.hpp>
15
16namespace boost_range_adaptor_type_erased_test
17{
18
19class MockType
20{
21public:
22 MockType()
23 : m_x(0)
24 {
25 }
26
27 MockType(boost::int32_t x)
28 : m_x(x)
29 {
30 }
31
32 boost::int32_t get() const { return m_x; }
33
34 inline bool operator==(const MockType& other) const
35 {
36 return m_x == other.m_x;
37 }
38
39 inline bool operator!=(const MockType& other) const
40 {
41 return m_x != other.m_x;
42 }
43
44private:
45 boost::int32_t m_x;
46};
47
48class MockType2 : public MockType
49{
50public:
51 MockType2() {}
52 MockType2(boost::int32_t x) : MockType(x) { }
53 MockType2(const MockType& other) : MockType(other) { }
54};
55
56inline std::ostream& operator<<(std::ostream& out, const MockType& obj)
57{
58 out << obj.get();
59 return out;
60}
61
62template<class Container>
63void test_type_erased_impl(Container& c)
64{
65 using namespace boost::adaptors;
66 typedef typename boost::range_value<Container>::type value_type;
67 typedef typename boost::adaptors::type_erased<> type_erased_t;
68
69
70 std::vector<value_type> output;
71
72 boost::push_back(output, boost::adaptors::type_erase(c, type_erased_t()));
73
74 BOOST_CHECK_EQUAL_COLLECTIONS( output.begin(), output.end(),
75 c.begin(), c.end() );
76
77 output.clear();
78 boost::push_back(output, c | type_erased_t());
79
80 BOOST_CHECK_EQUAL_COLLECTIONS( output.begin(), output.end(),
81 c.begin(), c.end() );
82}
83
84template<class Container>
85void test_const_and_mutable(Container& c)
86{
87 test_type_erased_impl(c);
88
89 const Container& const_c = c;
90 test_type_erased_impl(const_c);
91}
92
93template<class Container>
94void test_driver()
95{
96 using namespace boost::assign;
97
98 typedef typename boost::range_value<Container>::type value_type;
99
100 Container c;
101 test_const_and_mutable(c);
102
103 c += value_type(1);
104 test_const_and_mutable(c);
105
106 c += value_type(2);
107 test_const_and_mutable(c);
108}
109
110template<
111 class Traversal
112 , class Container
113>
114void test_writeable(Container&, boost::single_pass_traversal_tag)
115{}
116
117template<
118 class Traversal
119 , class Container
120>
121void test_writeable(Container& source, boost::forward_traversal_tag)
122{
123 using namespace boost::adaptors;
124
125 typedef typename boost::range_value<Container>::type value_type;
126 typedef typename boost::range_difference<Container>::type difference_type;
127 typedef typename boost::range_reference<Container>::type mutable_reference_type;
128 typedef boost::any_range<
129 value_type
130 , Traversal
131 , mutable_reference_type
132 , difference_type
133 > mutable_any_range;
134
135 mutable_any_range r = source | boost::adaptors::type_erased<>();
136 std::vector<value_type> output_test;
137 boost::fill(r, value_type(1));
138 BOOST_CHECK_EQUAL( boost::distance(r), boost::distance(source) );
139 std::vector<value_type> reference_output(source.size(), value_type(1));
140 BOOST_CHECK_EQUAL_COLLECTIONS( reference_output.begin(), reference_output.end(),
141 r.begin(), r.end() );
142
143}
144
145template<
146 class Container
147 , class Traversal
148 , class Buffer
149>
150void test_type_erased_impl()
151{
152 using namespace boost::adaptors;
153
154 typedef typename boost::range_value<Container>::type value_type;
155
156 typedef typename boost::any_range_type_generator<
157 Container
158 , boost::use_default
159 , Traversal
160 , boost::use_default
161 , boost::use_default
162 , Buffer
163 >::type mutable_any_range;
164
165 typedef typename boost::any_range_type_generator<
166 const Container
167 , boost::use_default
168 , Traversal
169 , boost::use_default
170 , boost::use_default
171 , Buffer
172 >::type const_any_range;
173
174 typedef boost::adaptors::type_erased<
175 boost::use_default
176 , Traversal
177 , boost::use_default
178 , boost::use_default
179 , Buffer
180 > type_erased_t;
181
182 Container source;
183 for (int i = 0; i < 10; ++i)
184 source.push_back(value_type(i));
185
186 mutable_any_range r(source);
187 BOOST_CHECK_EQUAL_COLLECTIONS( source.begin(), source.end(),
188 r.begin(), r.end() );
189
190 r = mutable_any_range();
191 BOOST_CHECK_EQUAL( r.empty(), true );
192
193 r = source | type_erased_t();
194 BOOST_CHECK_EQUAL_COLLECTIONS( source.begin(), source.end(),
195 r.begin(), r.end() );
196 r = mutable_any_range();
197
198 r = boost::adaptors::type_erase(source, type_erased_t());
199 BOOST_CHECK_EQUAL_COLLECTIONS( source.begin(), source.end(),
200 r.begin(), r.end() );
201 r = mutable_any_range();
202
203 test_writeable<Traversal>(source, Traversal());
204
205 // convert and construct a const any_range from a mutable source
206 // range
207 const_any_range cr(source);
208 BOOST_CHECK_EQUAL_COLLECTIONS( source.begin(), source.end(),
209 cr.begin(), cr.end() );
210 // assign an empty range and ensure that this correctly results
211 // in an empty range. This is important for the validity of
212 // the rest of the tests.
213 cr = const_any_range();
214 BOOST_CHECK_EQUAL( cr.empty(), true );
215
216 // Test the pipe type_erased adaptor from a constant source
217 // range to a constant any_range
218 const Container& const_source = source;
219 cr = const_any_range();
220 cr = const_source | type_erased_t();
221 BOOST_CHECK_EQUAL_COLLECTIONS( const_source.begin(), const_source.end(),
222 cr.begin(), cr.end() );
223
224 // Test the pipe type erased adaptor from a mutable source
225 // range to a constant any_range
226 cr = const_any_range();
227 cr = source | type_erased_t();
228 BOOST_CHECK_EQUAL_COLLECTIONS( source.begin(), source.end(),
229 cr.begin(), cr.end() );
230
231 // Use the function form of the type_erase adaptor from a constant
232 // source range
233 cr = const_any_range();
234 cr = boost::adaptors::type_erase(const_source, type_erased_t());
235 BOOST_CHECK_EQUAL_COLLECTIONS( const_source.begin(), const_source.end(),
236 cr.begin(), cr.end() );
237
238 // Assignment from mutable to const...
239 cr = const_any_range();
240 cr = r;
241 BOOST_CHECK_EQUAL_COLLECTIONS( cr.begin(), cr.end(),
242 r.begin(), r.end() );
243
244 // Converting copy from mutable to const...
245 cr = const_any_range();
246 cr = const_any_range(r);
247 BOOST_CHECK_EQUAL_COLLECTIONS( cr.begin(), cr.end(),
248 r.begin(), r.end() );
249}
250
251template<
252 class Container
253 , class Traversal
254 , class Buffer
255>
256class test_type_erased_impl_fn
257{
258public:
259 typedef void result_type;
260 void operator()()
261 {
262 test_type_erased_impl< Container, Traversal, Buffer >();
263 }
264};
265
266template<
267 class Container
268 , class Traversal
269>
270void test_type_erased_exercise_buffer_types()
271{
272 using boost::any_iterator_default_buffer;
273 using boost::any_iterator_buffer;
274 using boost::any_iterator_heap_only_buffer;
275 using boost::any_iterator_stack_only_buffer;
276
277 test_type_erased_impl_fn< Container, Traversal, any_iterator_default_buffer >()();
278 test_type_erased_impl_fn< Container, Traversal, any_iterator_heap_only_buffer >()();
279 test_type_erased_impl_fn< Container, Traversal, any_iterator_buffer<1> >()();
280 test_type_erased_impl_fn< Container, Traversal, any_iterator_buffer<2> >()();
281 test_type_erased_impl_fn< Container, Traversal, any_iterator_buffer<32> >()();
282 test_type_erased_impl_fn< Container, Traversal, any_iterator_buffer<64> >()();
283 test_type_erased_impl_fn< Container, Traversal, any_iterator_buffer<128> >()();
284 test_type_erased_impl_fn< Container, Traversal, any_iterator_stack_only_buffer<128> >()();
285}
286
287} // namespace boost_range_adaptor_type_erased_test
288
289#endif // include guard
290

source code of boost/libs/range/test/adaptor_test/type_erased_test.hpp