flatten_iterator.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368
  1. // Boost.Geometry (aka GGL, Generic Geometry Library)
  2. // Unit Test
  3. // Copyright (c) 2014, Oracle and/or its affiliates.
  4. // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
  5. // Licensed under the Boost Software License version 1.0.
  6. // http://www.boost.org/users/license.html
  7. #ifndef BOOST_TEST_MODULE
  8. #define BOOST_TEST_MODULE test_flatten_iterator
  9. #endif
  10. #include <boost/test/included/unit_test.hpp>
  11. #include <cstddef>
  12. #include <iostream>
  13. #include <string>
  14. #include <sstream>
  15. #include <algorithm>
  16. #include <iterator>
  17. #include <vector>
  18. #include <list>
  19. #include <boost/core/ignore_unused.hpp>
  20. #include <boost/mpl/if.hpp>
  21. #include <boost/type_traits/is_const.hpp>
  22. #include <boost/assign/std/vector.hpp>
  23. #include <boost/assign/std/list.hpp>
  24. #include <boost/assign/std/set.hpp>
  25. #include "test_iterator_common.hpp"
  26. #include <boost/geometry/iterators/flatten_iterator.hpp>
  27. using namespace boost::assign;
  28. template <typename InnerContainer>
  29. struct access_begin
  30. {
  31. typedef typename boost::mpl::if_
  32. <
  33. typename boost::is_const<InnerContainer>::type,
  34. typename InnerContainer::const_iterator,
  35. typename InnerContainer::iterator
  36. >::type return_type;
  37. static inline return_type apply(InnerContainer& inner)
  38. {
  39. return inner.begin();
  40. }
  41. };
  42. template <typename InnerContainer>
  43. struct access_end
  44. {
  45. typedef typename boost::mpl::if_
  46. <
  47. typename boost::is_const<InnerContainer>::type,
  48. typename InnerContainer::const_iterator,
  49. typename InnerContainer::iterator
  50. >::type return_type;
  51. static inline return_type apply(InnerContainer& inner)
  52. {
  53. return inner.end();
  54. }
  55. };
  56. template <typename NestedContainer>
  57. inline std::size_t number_of_elements(NestedContainer const& c)
  58. {
  59. std::size_t num_elements(0);
  60. for (typename NestedContainer::const_iterator outer = c.begin();
  61. outer != c.end(); ++outer)
  62. {
  63. num_elements += outer->size();
  64. }
  65. return num_elements;
  66. }
  67. struct test_flatten_iterator
  68. {
  69. template
  70. <
  71. typename FlattenIterator,
  72. typename ConstFlattenIterator,
  73. typename NestedContainer
  74. >
  75. static inline
  76. void test_using_max_element(FlattenIterator first,
  77. FlattenIterator beyond,
  78. ConstFlattenIterator const_first,
  79. ConstFlattenIterator const_beyond,
  80. NestedContainer const& c)
  81. {
  82. typedef typename std::iterator_traits
  83. <
  84. FlattenIterator
  85. >::value_type value_type;
  86. typedef typename NestedContainer::const_iterator const_outer_iterator;
  87. typedef typename NestedContainer::value_type inner_container;
  88. typedef typename inner_container::const_iterator const_inner_iterator;
  89. if ( first == beyond )
  90. {
  91. return;
  92. }
  93. FlattenIterator it_max = std::max_element(first, beyond);
  94. ConstFlattenIterator const_it_max =
  95. std::max_element(const_first, const_beyond);
  96. BOOST_CHECK( it_max == const_it_max );
  97. BOOST_CHECK( *it_max == *const_it_max );
  98. value_type old_value = *const_first;
  99. value_type new_value = *it_max + 1;
  100. *first = *it_max + 1;
  101. const_outer_iterator outer = c.begin();
  102. while ( outer->begin() == outer->end() )
  103. {
  104. ++outer;
  105. }
  106. const_inner_iterator inner = outer->begin();
  107. BOOST_CHECK( *inner == new_value );
  108. #ifdef BOOST_GEOMETRY_TEST_DEBUG
  109. std::cout << std::endl;
  110. std::cout << "modified 1st element of 1st non-empty "
  111. << "inner container:" << std::endl;
  112. print_nested_container(std::cout, c.begin(), c.end(), "nested :")
  113. << std::endl;
  114. print_container(std::cout, first, beyond, "flattened:") << std::endl;
  115. #endif
  116. *first = old_value;
  117. BOOST_CHECK( *inner == old_value );
  118. }
  119. template <typename NestedContainer>
  120. static inline void apply(NestedContainer& c,
  121. std::string const& case_id,
  122. std::string const& container_id)
  123. {
  124. boost::ignore_unused(case_id, container_id);
  125. #ifdef BOOST_GEOMETRY_TEST_DEBUG
  126. std::stringstream sstream;
  127. sstream << case_id << " [" << container_id << "]";
  128. std::cout << "case id: " << sstream.str() << std::endl;
  129. #endif
  130. typedef typename NestedContainer::const_iterator const_outer_iterator;
  131. typedef typename NestedContainer::iterator outer_iterator;
  132. typedef typename NestedContainer::value_type inner_container;
  133. typedef typename inner_container::const_iterator const_inner_iterator;
  134. typedef typename inner_container::iterator inner_iterator;
  135. typedef boost::geometry::flatten_iterator
  136. <
  137. const_outer_iterator,
  138. const_inner_iterator,
  139. typename inner_container::value_type const,
  140. access_begin<inner_container const>,
  141. access_end<inner_container const>
  142. > const_flatten_iterator;
  143. typedef boost::geometry::flatten_iterator
  144. <
  145. outer_iterator,
  146. inner_iterator,
  147. typename inner_container::value_type,
  148. access_begin<inner_container>,
  149. access_end<inner_container>
  150. > flatten_iterator;
  151. typedef typename std::iterator_traits
  152. <
  153. flatten_iterator
  154. >::value_type value_type;
  155. flatten_iterator begin(c.begin(), c.end());
  156. flatten_iterator end(c.end());
  157. const_flatten_iterator const_begin(begin);
  158. const_flatten_iterator const_end(end);
  159. const_begin = begin;
  160. const_end = end;
  161. // test copying, dereferencing and element equality
  162. std::vector<value_type> combined;
  163. for (const_outer_iterator outer = c.begin();
  164. outer != c.end(); ++outer)
  165. {
  166. std::copy(outer->begin(), outer->end(),
  167. std::back_inserter(combined));
  168. }
  169. test_equality(begin, end, combined);
  170. test_equality(const_begin, const_end, combined);
  171. combined.clear();
  172. std::copy(begin, end, std::back_inserter(combined));
  173. test_equality(begin, end, combined);
  174. test_equality(const_begin, const_end, combined);
  175. combined.clear();
  176. std::copy(const_begin, const_end, std::back_inserter(combined));
  177. test_equality(begin, end, combined);
  178. test_equality(const_begin, const_end, combined);
  179. // test sizes (and std::distance)
  180. test_size(begin, end, combined);
  181. test_size(const_begin, const_end, combined);
  182. #ifdef BOOST_GEOMETRY_TEST_DEBUG
  183. print_nested_container(std::cout, c.begin(), c.end(), "nested :")
  184. << std::endl;
  185. print_container(std::cout, begin, end, "flattened :")
  186. << std::endl;
  187. if ( begin != end )
  188. {
  189. std::cout << "min element: "
  190. << *std::min_element(begin, end)
  191. << std::endl;
  192. std::cout << "max element: "
  193. << *std::max_element(const_begin, const_end)
  194. << std::endl;
  195. }
  196. #endif
  197. // perform reversals (std::reverse)
  198. test_using_reverse(begin, end, combined);
  199. // test std::max_element, dereferencing and value assigment
  200. test_using_max_element(begin, end, const_begin, const_end, c);
  201. // test std::count_if / std::remove_if
  202. test_using_remove_if(begin, end, combined);
  203. #ifdef BOOST_GEOMETRY_TEST_DEBUG
  204. std::cout << "====================" << std::endl << std::endl;
  205. #endif
  206. }
  207. };
  208. // the actual test cases -- START
  209. template <int CaseNumber>
  210. struct test_case_per_container;
  211. template<>
  212. struct test_case_per_container<0>
  213. {
  214. template <typename NestedContainer>
  215. static inline void apply(std::string const& case_id,
  216. std::string const& container_id)
  217. {
  218. NestedContainer c;
  219. test_flatten_iterator::apply(c, case_id, container_id);
  220. }
  221. };
  222. template<>
  223. struct test_case_per_container<1>
  224. {
  225. template <typename NestedContainer>
  226. static inline void apply(std::string const& case_id,
  227. std::string const& container_id)
  228. {
  229. NestedContainer c;
  230. for (int i = 0; i < 5; ++i)
  231. {
  232. c += typename NestedContainer::value_type();
  233. }
  234. test_flatten_iterator::apply(c, case_id, container_id);
  235. }
  236. };
  237. template<>
  238. struct test_case_per_container<2>
  239. {
  240. template <typename NestedContainer>
  241. static inline void apply(std::string const& case_id,
  242. std::string const& container_id)
  243. {
  244. NestedContainer c;
  245. typename NestedContainer::value_type ic[4];
  246. ic[0] += 5,4,3,2,1;
  247. ic[1] += 6,7,8;
  248. ic[2] += 9;
  249. ic[3] += 9,8,7,6,5;
  250. c += ic[0],ic[1],ic[2],ic[3];
  251. test_flatten_iterator::apply(c, case_id, container_id);
  252. }
  253. };
  254. template<>
  255. struct test_case_per_container<3>
  256. {
  257. template <typename NestedContainer>
  258. static inline void apply(std::string const& case_id,
  259. std::string const& container_id)
  260. {
  261. NestedContainer c;
  262. typename NestedContainer::value_type ic[20];
  263. ic[2] += 5,4,3,2,1;
  264. ic[3] += 6,7,8;
  265. ic[8] += 9;
  266. ic[9] += 9,8,7,6,5;
  267. ic[14] += 4,3,2,1;
  268. for (std::size_t i = 0; i < 20; ++i)
  269. {
  270. c += ic[i];
  271. }
  272. test_flatten_iterator::apply(c, case_id, container_id);
  273. }
  274. };
  275. // the actual test cases -- END
  276. template <int CaseNumber>
  277. inline void test_case_all_containers(std::string const& case_id)
  278. {
  279. typedef typename std::vector<std::vector<int> > VV;
  280. typedef typename std::vector<std::list<int> > VL;
  281. typedef typename std::list<std::vector<int> > LV;
  282. typedef typename std::list<std::list<int> > LL;
  283. #ifdef BOOST_GEOMETRY_TEST_DEBUG
  284. std::cout << std::endl << std::endl;
  285. #endif
  286. test_case_per_container<CaseNumber>::template apply<VV>(case_id, "VV");
  287. test_case_per_container<CaseNumber>::template apply<VL>(case_id, "VL");
  288. test_case_per_container<CaseNumber>::template apply<LV>(case_id, "LV");
  289. test_case_per_container<CaseNumber>::template apply<LL>(case_id, "LL");
  290. #ifdef BOOST_GEOMETRY_TEST_DEBUG
  291. std::cout << std::endl;
  292. std::cout << "********************************************************"
  293. << std::endl << std::endl;
  294. #endif
  295. }
  296. BOOST_AUTO_TEST_CASE( test_flatten_iterator_all )
  297. {
  298. test_case_all_containers<0>("empty");
  299. test_case_all_containers<1>("case1");
  300. test_case_all_containers<2>("case2");
  301. test_case_all_containers<3>("case3");
  302. }