• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
test_iter(Container & cont)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
operator ()boost_range_test_algorithm_unique::unique_test_policy::test_range47             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
operator ()boost_range_test_algorithm_unique::unique_test_policy::test_range_overload75             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
reference(Container & cont)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
test_iter(Container & cont)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 
pred() const116         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
operator ()boost_range_test_algorithm_unique::unique_pred_test_policy::test_range123             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
operator ()boost_range_test_algorithm_unique::unique_pred_test_policy::test_range_overload149             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
reference(Container & cont)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>
test_unique_impl(TestPolicy policy,Pred 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 
operator ()boost_range_test_algorithm_unique::equal_div_2215         bool operator()(const T& left, const T& right) const
216         {
217             return left / 2 == right / 2;
218         }
219     };
220 
221     template<class Container>
test_unique_impl()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 
test_unique()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*
init_unit_test_suite(int argc,char * argv[])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