3 // Copyright Neil Groves 2009. 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)
9 // For more information, see http://www.boost.org/libs/range/
11 // The strided_defect_Trac5014 test case is a modified version of a test case
12 // contributed by Michel Morin as part of the trac ticket.
14 // The deque test case has been removed due to erroneous standard library
15 // implementations causing test failures.
17 #include <boost/range/adaptor/strided.hpp>
19 #include <boost/config.hpp>
20 #include <boost/test/test_tools.hpp>
21 #include <boost/test/unit_test.hpp>
23 #include <boost/assign.hpp>
24 #include <boost/range/algorithm_ext.hpp>
33 template< class Container
>
34 void strided_test_impl( Container
& c
, int stride_size
)
36 using namespace boost::adaptors
;
39 // This requirement was too restrictive. It makes the use of the
40 // strided adaptor too dangerous, and a simple solution existed
41 // to make it safe, hence the strided adaptor has been modified
42 // and this restriction no longer applies.
43 //BOOST_ASSERT( c.size() % STRIDE_SIZE == 0 );
48 typedef BOOST_DEDUCED_TYPENAME
Container::const_iterator
49 iterator_t BOOST_RANGE_UNUSED
;
50 typedef BOOST_DEDUCED_TYPENAME
Container::difference_type
51 diff_t BOOST_RANGE_UNUSED
;
52 typedef BOOST_DEDUCED_TYPENAME
Container::size_type
53 size_type BOOST_RANGE_UNUSED
;
54 iterator_t it
= c
.begin();
56 iterator_t last
= c
.end();
59 reference
.push_back(*it
);
61 for (int i
= 0; (it
!= last
) && (i
< stride_size
); ++i
)
67 boost::push_back( test
, c
| strided(stride_size
) );
69 BOOST_CHECK_EQUAL_COLLECTIONS( test
.begin(), test
.end(),
70 reference
.begin(), reference
.end() );
73 boost::push_back( test2
, adaptors::stride(c
, stride_size
) );
75 BOOST_CHECK_EQUAL_COLLECTIONS( test2
.begin(), test2
.end(),
76 reference
.begin(), reference
.end() );
78 // Test the const versions:
79 const Container
& cc
= c
;
81 boost::push_back( test3
, cc
| strided(stride_size
) );
83 BOOST_CHECK_EQUAL_COLLECTIONS( test3
.begin(), test3
.end(),
84 reference
.begin(), reference
.end() );
87 boost::push_back( test4
, adaptors::stride(cc
, stride_size
) );
89 BOOST_CHECK_EQUAL_COLLECTIONS( test4
.begin(), test4
.end(),
90 reference
.begin(), reference
.end() );
93 template< class Container
>
94 void strided_test_impl(int stride_size
)
96 using namespace boost::assign
;
101 strided_test_impl(c
, stride_size
);
105 strided_test_impl(c
, stride_size
);
107 // Test many elements
108 c
+= 1,1,1,2,2,3,4,5,6,6,6,7,8,9;
109 strided_test_impl(c
, stride_size
);
111 // Test an odd number of elements to determine that the relaxation
112 // of the requirements has been successful
113 // Test a sequence of length 1 with a stride of 2
116 strided_test_impl(c
, stride_size
);
118 // Test a sequence of length 2 with a stride of 2
121 strided_test_impl(c
, stride_size
);
123 // Test a sequence of length 3 with a stride of 2
126 strided_test_impl(c
, stride_size
);
129 template<typename Container
>
130 void strided_test_zero_stride()
135 typedef boost::strided_range
<Container
> strided_range_t
;
136 strided_range_t
rng( boost::adaptors::stride(c
, 0) );
137 boost::ignore_unused_variable_warning(rng
);
138 typedef BOOST_DEDUCED_TYPENAME
boost::range_iterator
<strided_range_t
>::type iter_t
;
140 typedef BOOST_DEDUCED_TYPENAME
boost::iterator_traversal
<
141 BOOST_DEDUCED_TYPENAME
Container::const_iterator
142 >::type container_traversal_tag
;
144 iter_t first
= boost::range_detail::make_begin_strided_iterator(
145 c
, 0, container_traversal_tag());
147 iter_t last
= boost::range_detail::make_end_strided_iterator(
148 c
, 0, container_traversal_tag());
151 for (int i
= 0; i
< 10; ++i
, ++it
)
153 BOOST_CHECK(it
== first
);
157 template<typename Container
>
158 void strided_test_impl()
160 strided_test_zero_stride
< Container
>();
162 const int MAX_STRIDE_SIZE
= 10;
163 for (int stride_size
= 1; stride_size
<= MAX_STRIDE_SIZE
; ++stride_size
)
165 strided_test_impl
< Container
>(stride_size
);
171 strided_test_impl
< std::vector
<int> >();
172 strided_test_impl
< std::list
<int> >();
175 void strided_defect_Trac5014()
177 using namespace boost::assign
;
180 for (int i
= 0; i
< 30; ++i
)
183 std::vector
<int> reference
;
184 reference
+= 0,4,8,12,16,20,24,28;
186 std::vector
<int> output
;
187 boost::push_back(output
, v
| boost::adaptors::strided(4));
189 BOOST_CHECK_EQUAL_COLLECTIONS( reference
.begin(), reference
.end(),
190 output
.begin(), output
.end() );
192 BOOST_CHECK_EQUAL( output
.back(), 28 );
195 template<typename BaseIterator
, typename Category
>
196 class strided_mock_iterator
197 : public boost::iterator_adaptor
<
198 strided_mock_iterator
<BaseIterator
,Category
>
204 typedef boost::iterator_adaptor
<
205 strided_mock_iterator
211 explicit strided_mock_iterator(BaseIterator it
)
219 ++(this->base_reference());
222 friend class boost::iterator_core_access
;
225 template<typename Category
, typename Range
>
226 boost::iterator_range
<strided_mock_iterator
<BOOST_DEDUCED_TYPENAME
boost::range_iterator
<Range
>::type
, Category
> >
227 as_mock_range(Range
& rng
)
229 typedef BOOST_DEDUCED_TYPENAME
boost::range_iterator
<Range
>::type range_iter_t
;
230 typedef strided_mock_iterator
<range_iter_t
, Category
> mock_iter_t
;
232 return boost::iterator_range
<mock_iter_t
>(
233 mock_iter_t(boost::begin(rng
)),
234 mock_iter_t(boost::end(rng
)));
237 void strided_test_traversal()
239 using namespace boost::assign
;
242 for (int i
= 0; i
< 30; ++i
)
245 std::vector
<int> reference
;
246 reference
+= 0,4,8,12,16,20,24,28;
248 std::vector
<int> output
;
249 boost::push_back(output
, as_mock_range
<boost::forward_traversal_tag
>(v
) | boost::adaptors::strided(4));
251 BOOST_CHECK_EQUAL_COLLECTIONS( reference
.begin(), reference
.end(),
252 output
.begin(), output
.end() );
255 boost::push_back(output
, as_mock_range
<boost::bidirectional_traversal_tag
>(v
) | boost::adaptors::strided(4));
257 BOOST_CHECK_EQUAL_COLLECTIONS( reference
.begin(), reference
.end(),
258 output
.begin(), output
.end() );
261 boost::push_back(output
, as_mock_range
<boost::random_access_traversal_tag
>(v
) | boost::adaptors::strided(4));
263 BOOST_CHECK_EQUAL_COLLECTIONS( reference
.begin(), reference
.end(),
264 output
.begin(), output
.end() );
267 template<typename Range
>
268 void strided_test_ticket_5236_check_bidirectional(const Range
& rng
)
270 BOOST_CHECK_EQUAL( boost::distance(rng
), 1 );
271 BOOST_CHECK_EQUAL( std::distance(boost::begin(rng
), boost::prior(boost::end(rng
))), 0 );
274 template<typename Range
>
275 void strided_test_ticket_5236_check(const Range
& rng
)
277 strided_test_ticket_5236_check_bidirectional(rng
);
279 typename
boost::range_iterator
<const Range
>::type it
= boost::end(rng
);
281 BOOST_CHECK_EQUAL( std::distance(boost::begin(rng
), it
), 0 );
284 void strided_test_ticket_5236()
288 strided_test_ticket_5236_check( v
| boost::adaptors::strided(2) );
290 // Ensure that there is consistency between the random-access implementation
291 // and the bidirectional.
295 strided_test_ticket_5236_check_bidirectional( l
| boost::adaptors::strided(2) );
301 boost::unit_test::test_suite
*
302 init_unit_test_suite(int argc
, char* argv
[])
304 boost::unit_test::test_suite
* test
305 = BOOST_TEST_SUITE( "RangeTestSuite.adaptor.strided" );
307 test
->add( BOOST_TEST_CASE( &boost::strided_test
) );
308 test
->add( BOOST_TEST_CASE( &boost::strided_defect_Trac5014
) );
309 test
->add( BOOST_TEST_CASE( &boost::strided_test_traversal
) );
310 test
->add( BOOST_TEST_CASE( &boost::strided_test_ticket_5236
) );