unique.cpp 8.0 KB

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