1 | // Boost.Range library |
2 | // |
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) |
7 | // |
8 | // |
9 | // For more information, see http://www.boost.org/libs/range/ |
10 | // |
11 | #include <boost/range/algorithm/unique.hpp> |
12 | #include <boost/range/detail/range_return.hpp> |
13 | |
14 | #include <boost/test/test_tools.hpp> |
15 | #include <boost/test/unit_test.hpp> |
16 | |
17 | #include <boost/assign.hpp> |
18 | #include <boost/config.hpp> |
19 | #include "../test_driver/range_overload_test_driver.hpp" |
20 | #include <algorithm> |
21 | #include <functional> |
22 | #include <list> |
23 | #include <numeric> |
24 | #include <deque> |
25 | #include <vector> |
26 | |
27 | namespace boost_range_test_algorithm_unique |
28 | { |
29 | // test the 'unique' algorithm without a predicate |
30 | class unique_test_policy |
31 | { |
32 | public: |
33 | template< class Container > |
34 | BOOST_DEDUCED_TYPENAME boost::range_iterator<Container>::type |
35 | test_iter(Container& cont) |
36 | { |
37 | // There isn't an iterator return version of boost::unique, so just |
38 | // perform the standard algorithm |
39 | return std::unique(cont.begin(), cont.end()); |
40 | } |
41 | |
42 | template< boost::range_return_value return_type > |
43 | struct test_range |
44 | { |
45 | template< class Container, class Policy > |
46 | BOOST_DEDUCED_TYPENAME boost::range_return<Container,return_type>::type |
47 | operator()(Policy&, Container& cont) |
48 | { |
49 | typedef BOOST_DEDUCED_TYPENAME boost::range_return<Container,return_type>::type result_t; |
50 | |
51 | Container cont2(cont); |
52 | |
53 | result_t result = boost::unique<return_type>(cont); |
54 | |
55 | boost::unique<return_type>(boost::make_iterator_range(cont2)); |
56 | |
57 | BOOST_CHECK_EQUAL_COLLECTIONS( cont.begin(), cont.end(), |
58 | cont2.begin(), cont2.end() ); |
59 | |
60 | return result; |
61 | } |
62 | }; |
63 | |
64 | template<typename Container> |
65 | struct test_range_overload |
66 | { |
67 | BOOST_STATIC_CONSTANT( |
68 | ::boost::range_return_value, |
69 | result_type = ::boost::return_begin_found); |
70 | |
71 | template<typename Policy> |
72 | BOOST_DEDUCED_TYPENAME boost::range_return< |
73 | Container, result_type |
74 | >::type |
75 | operator()(Policy& policy, Container& cont) |
76 | { |
77 | typedef BOOST_DEDUCED_TYPENAME boost::range_return< |
78 | Container,result_type>::type result_t; |
79 | |
80 | Container cont2(cont); |
81 | |
82 | result_t result = boost::unique(cont); |
83 | |
84 | boost::unique(boost::make_iterator_range(cont2)); |
85 | |
86 | BOOST_CHECK_EQUAL_COLLECTIONS( |
87 | cont.begin(), cont.end(), |
88 | cont2.begin(), cont2.end()); |
89 | |
90 | return result; |
91 | } |
92 | }; |
93 | |
94 | template< class Container > |
95 | BOOST_DEDUCED_TYPENAME boost::range_iterator<Container>::type |
96 | reference(Container& cont) |
97 | { |
98 | return std::unique(cont.begin(), cont.end()); |
99 | } |
100 | }; |
101 | |
102 | // test the 'unique' algorithm with a predicate |
103 | template<class Pred> |
104 | class unique_pred_test_policy |
105 | { |
106 | public: |
107 | template< class Container > |
108 | BOOST_DEDUCED_TYPENAME boost::range_iterator<Container>::type |
109 | test_iter(Container& cont) |
110 | { |
111 | // There isn't an iterator return version of boost::unique, so just |
112 | // perform the standard algorithm |
113 | return std::unique(cont.begin(), cont.end(), Pred()); |
114 | } |
115 | |
116 | Pred pred() const { return Pred(); } |
117 | |
118 | template< boost::range_return_value return_type > |
119 | struct test_range |
120 | { |
121 | template< class Container, class Policy > |
122 | BOOST_DEDUCED_TYPENAME boost::range_return<Container,return_type>::type |
123 | operator()(Policy& policy, Container& cont) |
124 | { |
125 | typedef BOOST_DEDUCED_TYPENAME boost::range_return<Container,return_type>::type result_t; |
126 | |
127 | Container cont2(cont); |
128 | |
129 | result_t result = boost::unique<return_type>(cont, policy.pred()); |
130 | |
131 | boost::unique<return_type>(boost::make_iterator_range(cont2), policy.pred()); |
132 | |
133 | BOOST_CHECK_EQUAL_COLLECTIONS( cont.begin(), cont.end(), |
134 | cont2.begin(), cont2.end() ); |
135 | |
136 | return result; |
137 | } |
138 | }; |
139 | |
140 | template<typename Container> |
141 | struct test_range_overload |
142 | { |
143 | BOOST_STATIC_CONSTANT( |
144 | ::boost::range_return_value, |
145 | result_type = ::boost::return_begin_found); |
146 | |
147 | template<typename Policy> |
148 | BOOST_DEDUCED_TYPENAME boost::range_return<Container,result_type>::type |
149 | operator()(Policy& policy, Container& cont) |
150 | { |
151 | typedef BOOST_DEDUCED_TYPENAME boost::range_return< |
152 | Container,result_type>::type result_t; |
153 | |
154 | Container cont2(cont); |
155 | |
156 | result_t result = boost::unique(cont, policy.pred()); |
157 | |
158 | boost::unique(boost::make_iterator_range(cont2), policy.pred()); |
159 | |
160 | BOOST_CHECK_EQUAL_COLLECTIONS( |
161 | cont.begin(), cont.end(), |
162 | cont2.begin(), cont2.end()); |
163 | |
164 | return result; |
165 | } |
166 | }; |
167 | |
168 | template< class Container > |
169 | BOOST_DEDUCED_TYPENAME boost::range_iterator<Container>::type |
170 | reference(Container& cont) |
171 | { |
172 | return std::unique(cont.begin(), cont.end(), Pred()); |
173 | } |
174 | }; |
175 | |
176 | template<class Container, class TestPolicy, class Pred> |
177 | void test_unique_impl(TestPolicy policy, Pred pred) |
178 | { |
179 | using namespace boost::assign; |
180 | |
181 | typedef BOOST_DEDUCED_TYPENAME Container::value_type value_t; |
182 | |
183 | boost::range_test::range_overload_test_driver test_driver; |
184 | |
185 | Container cont; |
186 | |
187 | test_driver(cont, policy); |
188 | |
189 | cont.clear(); |
190 | cont += 1; |
191 | |
192 | std::vector<value_t> temp(cont.begin(), cont.end()); |
193 | std::sort(temp.begin(), temp.end(), pred); |
194 | cont.assign(temp.begin(), temp.end()); |
195 | |
196 | test_driver(cont, policy); |
197 | |
198 | cont.clear(); |
199 | cont += 1,2,2,2,2,3,4,5,6,7,8,9; |
200 | |
201 | temp.assign(cont.begin(), cont.end()); |
202 | std::sort(temp.begin(), temp.end(), pred); |
203 | cont.assign(temp.begin(), temp.end()); |
204 | |
205 | test_driver(cont, policy); |
206 | } |
207 | |
208 | template<typename T> |
209 | struct equal_div_2 |
210 | { |
211 | typedef bool result_type; |
212 | typedef const T& first_argument_type; |
213 | typedef const T& second_argument_type; |
214 | |
215 | bool operator()(const T& left, const T& right) const |
216 | { |
217 | return left / 2 == right / 2; |
218 | } |
219 | }; |
220 | |
221 | template<class Container> |
222 | void test_unique_impl() |
223 | { |
224 | test_unique_impl<Container>( |
225 | unique_test_policy(), |
226 | std::less<int>() |
227 | ); |
228 | |
229 | test_unique_impl<Container>( |
230 | unique_pred_test_policy<std::equal_to<int> >(), |
231 | std::less<int>() |
232 | ); |
233 | |
234 | test_unique_impl<Container>( |
235 | unique_pred_test_policy<std::equal_to<int> >(), |
236 | std::greater<int>() |
237 | ); |
238 | |
239 | test_unique_impl<Container>( |
240 | unique_pred_test_policy<equal_div_2<int> >(), |
241 | std::less<int>() |
242 | ); |
243 | } |
244 | |
245 | void test_unique() |
246 | { |
247 | test_unique_impl< std::vector<int> >(); |
248 | test_unique_impl< std::list<int> >(); |
249 | test_unique_impl< std::deque<int> >(); |
250 | } |
251 | } |
252 | |
253 | boost::unit_test::test_suite* |
254 | init_unit_test_suite(int argc, char* argv[]) |
255 | { |
256 | boost::unit_test::test_suite* test |
257 | = BOOST_TEST_SUITE( "RangeTestSuite.algorithm.unique" ); |
258 | |
259 | test->add( BOOST_TEST_CASE( &boost_range_test_algorithm_unique::test_unique ) ); |
260 | |
261 | return test; |
262 | } |
263 | |