find_backward_test.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420
  1. /*
  2. Copyright (c) T. Zachary Laine 2018.
  3. Distributed under the Boost Software License, Version 1.0. (See accompanying
  4. file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  5. For more information, see http://www.boost.org
  6. */
  7. #include <iostream>
  8. #include <boost/algorithm/find_backward.hpp>
  9. #define BOOST_TEST_MAIN
  10. #include <boost/test/unit_test.hpp>
  11. #include <vector>
  12. #include <list>
  13. namespace ba = boost::algorithm;
  14. template <typename Container>
  15. struct dist_t
  16. {
  17. dist_t(Container & cont) : cont_(cont) {}
  18. template<typename Iter>
  19. std::ptrdiff_t operator()(Iter it) const
  20. {
  21. return std::distance(cont_.begin(), it);
  22. }
  23. Container & cont_;
  24. };
  25. BOOST_CXX14_CONSTEXPR bool check_constexpr_backward()
  26. {
  27. int in_data[] = {1, 2, 3, 4, 5};
  28. bool res = true;
  29. const int* from = in_data;
  30. const int* to = in_data + 5;
  31. const int* start = ba::find_backward(from, to, 1); // stops on first
  32. res = (res && start == from);
  33. start = ba::find_backward(in_data, 1); // stops on first
  34. res = (res && start == from);
  35. const int* end = ba::find_backward(from, to, 6); // stops on the end
  36. res = (res && end == to);
  37. end = ba::find_backward(in_data, 6); // stops on the end
  38. res = (res && end == to);
  39. const int* three = ba::find_backward(from, to, 3); // stops on third element
  40. res = (res && three == in_data + 2);
  41. three = ba::find_backward(in_data, 3); // stops on third element
  42. res = (res && three == in_data + 2);
  43. return res;
  44. }
  45. void test_find_backward()
  46. {
  47. {
  48. std::vector<int> v1;
  49. const dist_t<std::vector<int> > dist(v1);
  50. for (int i = 5; i < 15; ++i)
  51. v1.push_back(i);
  52. BOOST_CHECK_EQUAL(
  53. dist(ba::find_backward(v1.begin(), v1.end(), 0)), v1.size());
  54. BOOST_CHECK_EQUAL(
  55. dist(ba::find_backward(v1.begin(), v1.end(), 100)), v1.size());
  56. BOOST_CHECK_EQUAL(
  57. dist(ba::find_backward(v1.begin(), v1.end(), v1.back())),
  58. v1.size() - 1);
  59. BOOST_CHECK_EQUAL(
  60. dist(ba::find_backward(v1.begin(), v1.end(), v1.front())), 0);
  61. BOOST_CHECK_EQUAL(dist(ba::find_backward(v1, 0)), v1.size());
  62. BOOST_CHECK_EQUAL(dist(ba::find_backward(v1, 100)), v1.size());
  63. BOOST_CHECK_EQUAL(
  64. dist(ba::find_backward(v1, v1.back())), v1.size() - 1);
  65. BOOST_CHECK_EQUAL(dist(ba::find_backward(v1, v1.front())), 0);
  66. }
  67. // With bidirectional iterators.
  68. {
  69. std::list<int> l1;
  70. const dist_t<std::list<int> > dist(l1);
  71. for (int i = 5; i < 15; ++i)
  72. l1.push_back(i);
  73. BOOST_CHECK_EQUAL(
  74. dist(ba::find_backward(l1.begin(), l1.end(), 0)), l1.size());
  75. BOOST_CHECK_EQUAL(
  76. dist(ba::find_backward(l1.begin(), l1.end(), 100)), l1.size());
  77. BOOST_CHECK_EQUAL(
  78. dist(ba::find_backward(l1.begin(), l1.end(), l1.back())),
  79. l1.size() - 1);
  80. BOOST_CHECK_EQUAL(
  81. dist(ba::find_backward(l1.begin(), l1.end(), l1.front())), 0);
  82. BOOST_CHECK_EQUAL(dist(ba::find_backward(l1, 0)), l1.size());
  83. BOOST_CHECK_EQUAL(dist(ba::find_backward(l1, 100)), l1.size());
  84. BOOST_CHECK_EQUAL(
  85. dist(ba::find_backward(l1, l1.back())), l1.size() - 1);
  86. BOOST_CHECK_EQUAL(dist(ba::find_backward(l1, l1.front())), 0);
  87. }
  88. BOOST_CXX14_CONSTEXPR bool ce_result = check_constexpr_backward();
  89. BOOST_CHECK(ce_result);
  90. }
  91. struct equals
  92. {
  93. BOOST_CXX14_CONSTEXPR equals(int n) : n_(n) {}
  94. BOOST_CXX14_CONSTEXPR bool operator()(int i) { return i == n_; }
  95. int n_;
  96. };
  97. BOOST_CXX14_CONSTEXPR bool check_constexpr_if_backward()
  98. {
  99. int in_data[] = {1, 2, 3, 4, 5};
  100. bool res = true;
  101. const int* from = in_data;
  102. const int* to = in_data + 5;
  103. const int* start = ba::find_if_backward(from, to, equals(1)); // stops on first
  104. res = (res && start == from);
  105. start = ba::find_if_backward(in_data, equals(1)); // stops on first
  106. res = (res && start == from);
  107. const int* end = ba::find_if_backward(from, to, equals(6)); // stops on the end
  108. res = (res && end == to);
  109. end = ba::find_if_backward(in_data, equals(6)); // stops on the end
  110. res = (res && end == to);
  111. const int* three = ba::find_if_backward(from, to, equals(3)); // stops on third element
  112. res = (res && three == in_data + 2);
  113. three = ba::find_if_backward(in_data, equals(3)); // stops on third element
  114. res = (res && three == in_data + 2);
  115. return res;
  116. }
  117. void test_find_if_backward()
  118. {
  119. {
  120. std::vector<int> v1;
  121. const dist_t<std::vector<int> > dist(v1);
  122. for (int i = 5; i < 15; ++i)
  123. v1.push_back(i);
  124. BOOST_CHECK_EQUAL(
  125. dist(ba::find_if_backward(v1.begin(), v1.end(), equals(0))),
  126. v1.size());
  127. BOOST_CHECK_EQUAL(
  128. dist(ba::find_if_backward(v1.begin(), v1.end(), equals(100))),
  129. v1.size());
  130. BOOST_CHECK_EQUAL(
  131. dist(ba::find_if_backward(v1.begin(), v1.end(), equals(v1.back()))),
  132. v1.size() - 1);
  133. BOOST_CHECK_EQUAL(
  134. dist(
  135. ba::find_if_backward(v1.begin(), v1.end(), equals(v1.front()))),
  136. 0);
  137. BOOST_CHECK_EQUAL(dist(ba::find_if_backward(v1, equals(0))), v1.size());
  138. BOOST_CHECK_EQUAL(
  139. dist(ba::find_if_backward(v1, equals(100))), v1.size());
  140. BOOST_CHECK_EQUAL(
  141. dist(ba::find_if_backward(v1, equals(v1.back()))), v1.size() - 1);
  142. BOOST_CHECK_EQUAL(
  143. dist(ba::find_if_backward(v1, equals(v1.front()))), 0);
  144. }
  145. // With bidirectional iterators.
  146. {
  147. std::list<int> l1;
  148. const dist_t<std::list<int> > dist(l1);
  149. for (int i = 5; i < 15; ++i)
  150. l1.push_back(i);
  151. BOOST_CHECK_EQUAL(
  152. dist(ba::find_if_backward(l1.begin(), l1.end(), equals(0))),
  153. l1.size());
  154. BOOST_CHECK_EQUAL(
  155. dist(ba::find_if_backward(l1.begin(), l1.end(), equals(100))),
  156. l1.size());
  157. BOOST_CHECK_EQUAL(
  158. dist(ba::find_if_backward(l1.begin(), l1.end(), equals(l1.back()))),
  159. l1.size() - 1);
  160. BOOST_CHECK_EQUAL(
  161. dist(
  162. ba::find_if_backward(l1.begin(), l1.end(), equals(l1.front()))),
  163. 0);
  164. BOOST_CHECK_EQUAL(dist(ba::find_if_backward(l1, equals(0))), l1.size());
  165. BOOST_CHECK_EQUAL(
  166. dist(ba::find_if_backward(l1, equals(100))), l1.size());
  167. BOOST_CHECK_EQUAL(
  168. dist(ba::find_if_backward(l1, equals(l1.back()))), l1.size() - 1);
  169. BOOST_CHECK_EQUAL(
  170. dist(ba::find_if_backward(l1, equals(l1.front()))), 0);
  171. }
  172. BOOST_CXX14_CONSTEXPR bool ce_result = check_constexpr_if_backward();
  173. BOOST_CHECK(ce_result);
  174. }
  175. struct not_equals
  176. {
  177. BOOST_CXX14_CONSTEXPR not_equals(int n) : n_(n) {}
  178. BOOST_CXX14_CONSTEXPR bool operator()(int i) { return i != n_; }
  179. int n_;
  180. };
  181. BOOST_CXX14_CONSTEXPR bool check_constexpr_if_not_backward()
  182. {
  183. int in_data[] = {1, 2, 3, 4, 5};
  184. bool res = true;
  185. const int* from = in_data;
  186. const int* to = in_data + 5;
  187. const int* start = ba::find_if_not_backward(from, to, not_equals(1)); // stops on first
  188. res = (res && start == from);
  189. start = ba::find_if_not_backward(in_data, not_equals(1)); // stops on first
  190. res = (res && start == from);
  191. const int* end = ba::find_if_not_backward(from, to, not_equals(6)); // stops on the end
  192. res = (res && end == to);
  193. end = ba::find_if_not_backward(in_data, not_equals(6)); // stops on the end
  194. res = (res && end == to);
  195. const int* three = ba::find_if_not_backward(from, to, not_equals(3)); // stops on third element
  196. res = (res && three == in_data + 2);
  197. three = ba::find_if_not_backward(in_data, not_equals(3)); // stops on third element
  198. res = (res && three == in_data + 2);
  199. return res;
  200. }
  201. void test_find_if_not_backward()
  202. {
  203. {
  204. std::vector<int> v1;
  205. const dist_t<std::vector<int> > dist(v1);
  206. for (int i = 5; i < 15; ++i)
  207. v1.push_back(i);
  208. BOOST_CHECK_EQUAL(
  209. dist(ba::find_if_not_backward(v1.begin(), v1.end(), not_equals(0))),
  210. v1.size());
  211. BOOST_CHECK_EQUAL(
  212. dist(ba::find_if_not_backward(
  213. v1.begin(), v1.end(), not_equals(100))),
  214. v1.size());
  215. BOOST_CHECK_EQUAL(
  216. dist(ba::find_if_not_backward(
  217. v1.begin(), v1.end(), not_equals(v1.back()))),
  218. v1.size() - 1);
  219. BOOST_CHECK_EQUAL(
  220. dist(ba::find_if_not_backward(
  221. v1.begin(), v1.end(), not_equals(v1.front()))),
  222. 0);
  223. BOOST_CHECK_EQUAL(
  224. dist(ba::find_if_not_backward(v1, not_equals(0))), v1.size());
  225. BOOST_CHECK_EQUAL(
  226. dist(ba::find_if_not_backward(v1, not_equals(100))), v1.size());
  227. BOOST_CHECK_EQUAL(
  228. dist(ba::find_if_not_backward(v1, not_equals(v1.back()))),
  229. v1.size() - 1);
  230. BOOST_CHECK_EQUAL(
  231. dist(ba::find_if_not_backward(v1, not_equals(v1.front()))), 0);
  232. }
  233. // With bidirectional iterators.
  234. {
  235. std::list<int> l1;
  236. const dist_t<std::list<int> > dist(l1);
  237. for (int i = 5; i < 15; ++i)
  238. l1.push_back(i);
  239. BOOST_CHECK_EQUAL(
  240. dist(ba::find_if_not_backward(l1.begin(), l1.end(), not_equals(0))),
  241. l1.size());
  242. BOOST_CHECK_EQUAL(
  243. dist(ba::find_if_not_backward(
  244. l1.begin(), l1.end(), not_equals(100))),
  245. l1.size());
  246. BOOST_CHECK_EQUAL(
  247. dist(ba::find_if_not_backward(
  248. l1.begin(), l1.end(), not_equals(l1.back()))),
  249. l1.size() - 1);
  250. BOOST_CHECK_EQUAL(
  251. dist(ba::find_if_not_backward(
  252. l1.begin(), l1.end(), not_equals(l1.front()))),
  253. 0);
  254. BOOST_CHECK_EQUAL(
  255. dist(ba::find_if_not_backward(l1, not_equals(0))), l1.size());
  256. BOOST_CHECK_EQUAL(
  257. dist(ba::find_if_not_backward(l1, not_equals(100))), l1.size());
  258. BOOST_CHECK_EQUAL(
  259. dist(ba::find_if_not_backward(l1, not_equals(l1.back()))),
  260. l1.size() - 1);
  261. BOOST_CHECK_EQUAL(
  262. dist(ba::find_if_not_backward(l1, not_equals(l1.front()))), 0);
  263. }
  264. BOOST_CXX14_CONSTEXPR bool ce_result = check_constexpr_if_not_backward();
  265. BOOST_CHECK(ce_result);
  266. }
  267. BOOST_CXX14_CONSTEXPR bool check_constexpr_not_backward()
  268. {
  269. int in_data[] = {1, 5, 5, 5, 5};
  270. bool res = true;
  271. const int* from = in_data;
  272. const int* to = in_data + 5;
  273. const int* start = ba::find_not_backward(from, to, 5); // stops on first
  274. res = (res && start == from);
  275. start = ba::find_not_backward(in_data, 5); // stops on first
  276. res = (res && start == from);
  277. const int in_data_2[] = {6, 6, 6, 6, 6};
  278. const int* end = ba::find_not_backward(in_data_2, in_data_2 + 5, 6); // stops on the end
  279. res = (res && end == in_data_2 + 5);
  280. end = ba::find_not_backward(in_data_2, 6); // stops on the end
  281. res = (res && end == in_data_2 + 5);
  282. return res;
  283. }
  284. void test_find_not_backward()
  285. {
  286. {
  287. std::vector<int> v1;
  288. const dist_t<std::vector<int> > dist(v1);
  289. for (int i = 0; i < 5; ++i)
  290. v1.push_back(0);
  291. for (int i = 0; i < 5; ++i)
  292. v1.push_back(1);
  293. BOOST_CHECK_EQUAL(
  294. dist(ba::find_not_backward(v1.begin(), v1.end(), 1)), 4);
  295. BOOST_CHECK_EQUAL(
  296. dist(ba::find_not_backward(v1.begin(), v1.end(), 0)),
  297. v1.size() - 1);
  298. BOOST_CHECK_EQUAL(
  299. dist(ba::find_not_backward(v1.begin(), v1.end(), 2)),
  300. v1.size() - 1);
  301. BOOST_CHECK_EQUAL(dist(ba::find_not_backward(v1, 1)), 4);
  302. BOOST_CHECK_EQUAL(dist(ba::find_not_backward(v1, 0)), v1.size() - 1);
  303. BOOST_CHECK_EQUAL(dist(ba::find_not_backward(v1, 2)), v1.size() - 1);
  304. v1.resize(5);
  305. BOOST_CHECK_EQUAL(
  306. dist(ba::find_not_backward(v1.begin(), v1.end(), 0)), v1.size());
  307. BOOST_CHECK_EQUAL(dist(ba::find_not_backward(v1, 0)), v1.size());
  308. }
  309. // With bidirectional iterators.
  310. {
  311. std::list<int> l1;
  312. const dist_t<std::list<int> > dist(l1);
  313. for (int i = 0; i < 5; ++i)
  314. l1.push_back(0);
  315. for (int i = 0; i < 5; ++i)
  316. l1.push_back(1);
  317. BOOST_CHECK_EQUAL(
  318. dist(ba::find_not_backward(l1.begin(), l1.end(), 1)), 4);
  319. BOOST_CHECK_EQUAL(
  320. dist(ba::find_not_backward(l1.begin(), l1.end(), 0)),
  321. l1.size() - 1);
  322. BOOST_CHECK_EQUAL(
  323. dist(ba::find_not_backward(l1.begin(), l1.end(), 2)),
  324. l1.size() - 1);
  325. BOOST_CHECK_EQUAL(dist(ba::find_not_backward(l1, 1)), 4);
  326. BOOST_CHECK_EQUAL(dist(ba::find_not_backward(l1, 0)), l1.size() - 1);
  327. BOOST_CHECK_EQUAL(dist(ba::find_not_backward(l1, 2)), l1.size() - 1);
  328. l1.resize(5);
  329. BOOST_CHECK_EQUAL(
  330. dist(ba::find_not_backward(l1.begin(), l1.end(), 0)), l1.size());
  331. BOOST_CHECK_EQUAL(dist(ba::find_not_backward(l1, 0)), l1.size());
  332. }
  333. BOOST_CXX14_CONSTEXPR bool ce_result = check_constexpr_not_backward();
  334. BOOST_CHECK(ce_result);
  335. }
  336. BOOST_AUTO_TEST_CASE(test_main)
  337. {
  338. test_find_backward();
  339. test_find_if_backward();
  340. test_find_if_not_backward();
  341. test_find_not_backward();
  342. }