]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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> | |
7c673cae FG |
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 | } |