1 | // Boost.Range library |
2 | // |
3 | // Copyright Neil Groves 2014. 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 | // |
9 | // For more information, see http://www.boost.org/libs/range/ |
10 | // |
11 | #include <boost/range/adaptor/indexed.hpp> |
12 | |
13 | #include <boost/test/test_tools.hpp> |
14 | #include <boost/test/unit_test.hpp> |
15 | |
16 | #include <boost/assign.hpp> |
17 | #include <boost/foreach.hpp> |
18 | #include <boost/range/algorithm_ext.hpp> |
19 | #include <boost/range/concepts.hpp> |
20 | |
21 | #include <algorithm> |
22 | #include <list> |
23 | #include <vector> |
24 | |
25 | #include "../test_utils.hpp" |
26 | |
27 | namespace boost_range_test |
28 | { |
29 | namespace |
30 | { |
31 | |
32 | template<typename Container, typename AdaptedRange> |
33 | void check_result( |
34 | const Container& reference_range, |
35 | const AdaptedRange& adapted_range, |
36 | std::ptrdiff_t start_index |
37 | ) |
38 | { |
39 | typedef typename boost::range_iterator<const Container>::type |
40 | reference_iterator; |
41 | |
42 | typedef typename boost::range_iterator<const AdaptedRange>::type |
43 | adapted_iterator; |
44 | |
45 | BOOST_REQUIRE_EQUAL(boost::size(reference_range), |
46 | boost::size(adapted_range)); |
47 | |
48 | reference_iterator reference_it = boost::begin(reference_range); |
49 | adapted_iterator adapted_it = boost::begin(adapted_range); |
50 | for (std::ptrdiff_t i = start_index; |
51 | reference_it != boost::end(reference_range); |
52 | ++reference_it, ++adapted_it, ++i) |
53 | { |
54 | BOOST_CHECK_EQUAL(i, adapted_it->index()); |
55 | BOOST_CHECK_EQUAL(*reference_it, adapted_it->value()); |
56 | } |
57 | } |
58 | |
59 | template<typename Container> |
60 | void indexed_test_impl(Container& c, std::ptrdiff_t start_index) |
61 | { |
62 | // This is my preferred syntax using the | operator. |
63 | check_result(c, c | boost::adaptors::indexed(), 0); |
64 | check_result(c, c | boost::adaptors::indexed(start_index), start_index); |
65 | |
66 | // This is the function syntax |
67 | check_result(c, boost::adaptors::index(c), 0); |
68 | check_result(c, boost::adaptors::index(c, start_index), start_index); |
69 | } |
70 | |
71 | template<typename Container> |
72 | void indexed_test_impl(Container& c) |
73 | { |
74 | indexed_test_impl(c, 0); |
75 | indexed_test_impl(c, -1); |
76 | indexed_test_impl(c, 4); |
77 | } |
78 | |
79 | template<typename Container> |
80 | void indexed_test_impl() |
81 | { |
82 | using namespace boost::assign; |
83 | |
84 | Container c; |
85 | |
86 | // test empty container |
87 | indexed_test_impl(c); |
88 | |
89 | // test one element |
90 | c += 1; |
91 | indexed_test_impl(c); |
92 | |
93 | // test many elements |
94 | c += 1,2,2,2,3,4,4,4,4,5,6,7,8,9,9; |
95 | indexed_test_impl(c); |
96 | } |
97 | |
98 | template<typename Traversal, typename Range> |
99 | void check_traversal(const Range& rng) |
100 | { |
101 | BOOST_STATIC_ASSERT( |
102 | boost::is_convertible< |
103 | typename boost::range_traversal<const Range>::type, |
104 | Traversal |
105 | >::value); |
106 | } |
107 | |
108 | template<typename Traversal, typename Range> |
109 | void check_not_traversal(const Range& rng) |
110 | { |
111 | BOOST_STATIC_ASSERT( |
112 | !boost::is_convertible< |
113 | typename boost::range_traversal<const Range>::type, |
114 | Traversal |
115 | >::value); |
116 | } |
117 | |
118 | void indexed_test() |
119 | { |
120 | indexed_test_impl< std::vector< int > >(); |
121 | indexed_test_impl< std::list< int > >(); |
122 | |
123 | std::vector<int> vi; |
124 | |
125 | check_traversal<boost::random_access_traversal_tag>( |
126 | rng: vi | boost::adaptors::indexed()); |
127 | |
128 | std::list<int> li; |
129 | |
130 | check_traversal<boost::forward_traversal_tag>( |
131 | rng: li | boost::adaptors::indexed()); |
132 | |
133 | check_not_traversal<boost::bidirectional_traversal_tag>( |
134 | rng: li | boost::adaptors::indexed()); |
135 | |
136 | check_not_traversal<boost::random_access_traversal_tag>( |
137 | rng: li | boost::adaptors::indexed()); |
138 | } |
139 | |
140 | } // anonymous namesapce |
141 | } // namespace boost_range_test |
142 | |
143 | boost::unit_test::test_suite* |
144 | init_unit_test_suite(int, char*[]) |
145 | { |
146 | boost::unit_test::test_suite* test |
147 | = BOOST_TEST_SUITE( "Boost.Range indexed adaptor test suite" ); |
148 | |
149 | test->add(BOOST_TEST_CASE(&boost_range_test::indexed_test)); |
150 | |
151 | return test; |
152 | } |
153 | |