test_algorithm_impl.hpp 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122
  1. /* Copyright 2016-2018 Joaquin M Lopez Munoz.
  2. * Distributed under the Boost Software License, Version 1.0.
  3. * (See accompanying file LICENSE_1_0.txt or copy at
  4. * http://www.boost.org/LICENSE_1_0.txt)
  5. *
  6. * See http://www.boost.org/libs/poly_collection for library home page.
  7. */
  8. #ifndef BOOST_POLY_COLLECTION_TEST_TEST_ALGORITHM_IMPL_HPP
  9. #define BOOST_POLY_COLLECTION_TEST_TEST_ALGORITHM_IMPL_HPP
  10. #if defined(_MSC_VER)
  11. #pragma once
  12. #endif
  13. #include <algorithm>
  14. #include <boost/config.hpp>
  15. #include <boost/core/lightweight_test.hpp>
  16. #include <boost/detail/workaround.hpp>
  17. #include <boost/function_output_iterator.hpp>
  18. #include <boost/poly_collection/algorithm.hpp>
  19. #include <functional>
  20. #include <iterator>
  21. #include <random>
  22. #include <type_traits>
  23. #include <utility>
  24. #include <vector>
  25. #include "test_utilities.hpp"
  26. using namespace test_utilities;
  27. #if BOOST_WORKAROUND(BOOST_MSVC,>=1910)
  28. /* https://lists.boost.org/Archives/boost/2017/06/235687.php */
  29. #define DEFINE_ALGORITHM(name,f) \
  30. template<typename... Ts> \
  31. struct name \
  32. { \
  33. template<typename... Args> \
  34. auto operator()(Args&&... args)const \
  35. { \
  36. return f<Ts...>(std::forward<Args>(args)...); \
  37. } \
  38. };
  39. #elif BOOST_WORKAROUND(BOOST_GCC_VERSION,<50200)
  40. /* problem here is with return type containing <Ts...> */
  41. #define DEFINE_ALGORITHM(name,f) \
  42. template<typename... Ts> \
  43. struct name \
  44. { \
  45. template<typename... Args> \
  46. auto operator()(Args&&... args)const-> \
  47. decltype(f(std::forward<Args>(args)...)) \
  48. { \
  49. return f<Ts...>(std::forward<Args>(args)...); \
  50. } \
  51. };
  52. #else
  53. #define DEFINE_ALGORITHM(name,f) \
  54. template<typename... Ts> \
  55. struct name \
  56. { \
  57. template<typename... Args> \
  58. auto operator()(Args&&... args)const-> \
  59. decltype(f<Ts...>(std::forward<Args>(args)...)) \
  60. { \
  61. return f<Ts...>(std::forward<Args>(args)...); \
  62. } \
  63. };
  64. #endif
  65. DEFINE_ALGORITHM(std_all_of,std::all_of)
  66. DEFINE_ALGORITHM(poly_all_of,boost::poly_collection::all_of)
  67. DEFINE_ALGORITHM(std_any_of,std::any_of)
  68. DEFINE_ALGORITHM(poly_any_of,boost::poly_collection::any_of)
  69. DEFINE_ALGORITHM(std_none_of,std::none_of)
  70. DEFINE_ALGORITHM(poly_none_of,boost::poly_collection::none_of)
  71. DEFINE_ALGORITHM(std_for_each,std::for_each)
  72. DEFINE_ALGORITHM(poly_for_each,boost::poly_collection::for_each)
  73. DEFINE_ALGORITHM(poly_for_each_n,boost::poly_collection::for_each_n)
  74. DEFINE_ALGORITHM(std_find,std::find)
  75. DEFINE_ALGORITHM(poly_find,boost::poly_collection::find)
  76. DEFINE_ALGORITHM(std_find_if,std::find_if)
  77. DEFINE_ALGORITHM(poly_find_if,boost::poly_collection::find_if)
  78. DEFINE_ALGORITHM(std_find_if_not,std::find_if_not)
  79. DEFINE_ALGORITHM(poly_find_if_not,boost::poly_collection::find_if_not)
  80. DEFINE_ALGORITHM(std_find_end,std::find_end)
  81. DEFINE_ALGORITHM(poly_find_end,boost::poly_collection::find_end)
  82. DEFINE_ALGORITHM(std_find_first_of,std::find_first_of)
  83. DEFINE_ALGORITHM(poly_find_first_of,boost::poly_collection::find_first_of)
  84. DEFINE_ALGORITHM(std_adjacent_find,std::adjacent_find)
  85. DEFINE_ALGORITHM(poly_adjacent_find,boost::poly_collection::adjacent_find)
  86. DEFINE_ALGORITHM(std_count,std::count)
  87. DEFINE_ALGORITHM(poly_count,boost::poly_collection::count)
  88. DEFINE_ALGORITHM(std_count_if,std::count_if)
  89. DEFINE_ALGORITHM(poly_count_if,boost::poly_collection::count_if)
  90. DEFINE_ALGORITHM(std_cpp11_mismatch,std::mismatch) /* note std_cpp11 prefix */
  91. DEFINE_ALGORITHM(poly_mismatch,boost::poly_collection::mismatch)
  92. DEFINE_ALGORITHM(std_cpp11_equal,std::equal) /* note std_cpp11 prefix */
  93. DEFINE_ALGORITHM(poly_equal,boost::poly_collection::equal)
  94. DEFINE_ALGORITHM(std_cpp11_is_permutation,std::is_permutation) /* std_cpp11 */
  95. DEFINE_ALGORITHM(poly_is_permutation,boost::poly_collection::is_permutation)
  96. DEFINE_ALGORITHM(std_search,std::search)
  97. DEFINE_ALGORITHM(poly_search,boost::poly_collection::search)
  98. DEFINE_ALGORITHM(std_search_n,std::search_n)
  99. DEFINE_ALGORITHM(poly_search_n,boost::poly_collection::search_n)
  100. DEFINE_ALGORITHM(std_copy,std::copy)
  101. DEFINE_ALGORITHM(poly_copy,boost::poly_collection::copy)
  102. DEFINE_ALGORITHM(std_copy_n,std::copy_n)
  103. DEFINE_ALGORITHM(poly_copy_n,boost::poly_collection::copy_n)
  104. DEFINE_ALGORITHM(std_copy_if,std::copy_if)
  105. DEFINE_ALGORITHM(poly_copy_if,boost::poly_collection::copy_if)
  106. DEFINE_ALGORITHM(std_move,std::move)
  107. DEFINE_ALGORITHM(poly_move,boost::poly_collection::move)
  108. DEFINE_ALGORITHM(std_transform,std::transform)
  109. DEFINE_ALGORITHM(poly_transform,boost::poly_collection::transform)
  110. DEFINE_ALGORITHM(std_replace_copy,std::replace_copy)
  111. DEFINE_ALGORITHM(poly_replace_copy,boost::poly_collection::replace_copy)
  112. DEFINE_ALGORITHM(std_replace_copy_if,std::replace_copy_if)
  113. DEFINE_ALGORITHM(poly_replace_copy_if,boost::poly_collection::replace_copy_if)
  114. DEFINE_ALGORITHM(std_remove_copy,std::remove_copy)
  115. DEFINE_ALGORITHM(poly_remove_copy,boost::poly_collection::remove_copy)
  116. DEFINE_ALGORITHM(std_remove_copy_if,std::remove_copy_if)
  117. DEFINE_ALGORITHM(poly_remove_copy_if,boost::poly_collection::remove_copy_if)
  118. DEFINE_ALGORITHM(std_unique_copy,std::unique_copy)
  119. DEFINE_ALGORITHM(poly_unique_copy,boost::poly_collection::unique_copy)
  120. DEFINE_ALGORITHM(poly_sample,boost::poly_collection::sample)
  121. DEFINE_ALGORITHM(std_rotate_copy,std::rotate_copy)
  122. DEFINE_ALGORITHM(poly_rotate_copy,boost::poly_collection::rotate_copy)
  123. DEFINE_ALGORITHM(std_is_partitioned,std::is_partitioned)
  124. DEFINE_ALGORITHM(poly_is_partitioned,boost::poly_collection::is_partitioned)
  125. DEFINE_ALGORITHM(std_partition_copy,std::partition_copy)
  126. DEFINE_ALGORITHM(poly_partition_copy,boost::poly_collection::partition_copy)
  127. DEFINE_ALGORITHM(std_partition_point,std::partition_point)
  128. DEFINE_ALGORITHM(poly_partition_point,boost::poly_collection::partition_point)
  129. template<typename...>
  130. struct std_for_each_n
  131. {
  132. /* implemented here as the algorithm is C++17 */
  133. template<typename InputIterator,typename Size,typename Function>
  134. InputIterator operator()(InputIterator first,Size n,Function f)const
  135. {
  136. for(;n>0;++first,(void)--n)f(*first);
  137. return first;
  138. }
  139. };
  140. template<typename... Ts>
  141. struct std_mismatch:std_cpp11_mismatch<Ts...>
  142. {
  143. using std_cpp11_mismatch<Ts...>::operator();
  144. /* C++14 variants */
  145. template<typename InputIterator1,typename InputIterator2>
  146. std::pair<InputIterator1,InputIterator2> operator()(
  147. InputIterator1 first1,InputIterator1 last1,
  148. InputIterator2 first2,InputIterator2 last2)const
  149. {
  150. while(first1!=last1&&first2!=last2&&*first1==*first2){
  151. ++first1;
  152. ++first2;
  153. }
  154. return {first1,first2};
  155. }
  156. template<typename InputIterator1,typename InputIterator2,typename Predicate>
  157. std::pair<InputIterator1,InputIterator2> operator()(
  158. InputIterator1 first1,InputIterator1 last1,
  159. InputIterator2 first2,InputIterator2 last2,Predicate pred)const
  160. {
  161. while(first1!=last1&&first2!=last2&&pred(*first1,*first2)){
  162. ++first1;
  163. ++first2;
  164. }
  165. return {first1,first2};
  166. }
  167. };
  168. template<typename... Ts>
  169. struct std_equal:std_cpp11_equal<Ts...>
  170. {
  171. using std_cpp11_equal<Ts...>::operator();
  172. /* C++14 variants */
  173. template<typename InputIterator1,typename InputIterator2>
  174. bool operator()(
  175. InputIterator1 first1,InputIterator1 last1,
  176. InputIterator2 first2,InputIterator2 last2)const
  177. {
  178. for(;first1!=last1&&first2!=last2;++first1,++first2){
  179. if(!(*first1==*first2))return false;
  180. }
  181. return first1==last1&&first2==last2;
  182. }
  183. template<typename InputIterator1,typename InputIterator2,typename Predicate>
  184. bool operator()(
  185. InputIterator1 first1,InputIterator1 last1,
  186. InputIterator2 first2,InputIterator2 last2,Predicate pred)const
  187. {
  188. for(;first1!=last1&&first2!=last2;++first1,++first2){
  189. if(!pred(*first1,*first2))return false;
  190. }
  191. return first1==last1&&first2==last2;
  192. }
  193. };
  194. template<typename... Ts>
  195. struct std_is_permutation:std_cpp11_is_permutation<Ts...>
  196. {
  197. using std_cpp11_is_permutation<Ts...>::operator();
  198. /* The implementation of predicate-based std::is_permutation in GCC<=4.8
  199. * version of libstdc++-v3 incorrectly triggers the instantiation of
  200. * ForwardIterator2::value_type, which fails when this is an abstract class.
  201. * The implementation below ripped from libc++ source code.
  202. */
  203. template<
  204. typename ForwardIterator1,typename ForwardIterator2,typename Predicate
  205. >
  206. bool operator()(
  207. ForwardIterator1 first1,ForwardIterator1 last1,
  208. ForwardIterator2 first2,Predicate pred)const
  209. {
  210. using difference_type=
  211. typename std::iterator_traits<ForwardIterator1>::difference_type;
  212. for(;first1!=last1;++first1,(void)++first2){
  213. if(!pred(*first1,*first2))goto not_done;
  214. }
  215. return true;
  216. not_done:
  217. difference_type l1=std::distance(first1,last1);
  218. if(l1==difference_type(1))return false;
  219. ForwardIterator2 last2=std::next(first2,l1);
  220. for(ForwardIterator1 i=first1;i!= last1;++i){
  221. for(ForwardIterator1 j=first1;j!=i;++j)if(pred(*j,*i))goto next_iter;
  222. {
  223. difference_type c2=0;
  224. for(ForwardIterator2 j=first2;j!=last2;++j)if(pred(*i,*j))++c2;
  225. if(c2==0)return false;
  226. difference_type c1=1;
  227. for(ForwardIterator1 j=std::next(i);j!=last1;++j)if(pred(*i,*j))++c1;
  228. if(c1!=c2)return false;
  229. }
  230. next_iter:;
  231. }
  232. return true;
  233. }
  234. /* C++14 variants */
  235. template<typename ForwardIterator1,typename ForwardIterator2>
  236. bool operator()(
  237. ForwardIterator1 first1,ForwardIterator1 last1,
  238. ForwardIterator2 first2,ForwardIterator2 last2)const
  239. {
  240. if(std::distance(first1,last1)!=std::distance(first2,last2))return false;
  241. return (*this)(first1,last1,first2);
  242. }
  243. template<
  244. typename ForwardIterator1,typename ForwardIterator2,typename Predicate
  245. >
  246. bool operator()(
  247. ForwardIterator1 first1,ForwardIterator1 last1,
  248. ForwardIterator2 first2,ForwardIterator2 last2,Predicate pred)const
  249. {
  250. if(std::distance(first1,last1)!=std::distance(first2,last2))return false;
  251. return (*this)(first1,last1,first2,pred);
  252. }
  253. };
  254. template<typename...>
  255. struct std_sample
  256. {
  257. /* Implemented here as the algorithm is C++17 and because we need to control
  258. * the implementation to do white-box testing. Only the ForwardIterator
  259. * version required.
  260. */
  261. template<
  262. typename ForwardIterator,typename OutputIterator,
  263. typename Distance, typename UniformRandomBitGenerator
  264. >
  265. OutputIterator operator()(
  266. ForwardIterator first,ForwardIterator last,
  267. OutputIterator res, Distance n,UniformRandomBitGenerator&& g)const
  268. {
  269. Distance m=std::distance(first,last);
  270. for(n=(std::min)(n,m);n!=0;++first){
  271. auto r=std::uniform_int_distribution<Distance>(0,--m)(g);
  272. if (r<n){
  273. *res++=*first;
  274. --n;
  275. }
  276. }
  277. return res;
  278. }
  279. };
  280. template<
  281. typename ControlAlgorithm,typename Algorithm,
  282. typename PolyCollection,typename... Args
  283. >
  284. void test_algorithm(PolyCollection& p,Args&&... args)
  285. {
  286. Algorithm alg;
  287. ControlAlgorithm control;
  288. for(auto first=p.begin(),end=p.end();;++first){
  289. for(auto last=first;;++last){
  290. BOOST_TEST(
  291. alg(first,last,std::forward<Args>(args)...)==
  292. control(first,last,std::forward<Args>(args)...));
  293. if(last==end)break;
  294. }
  295. if(first==end)break;
  296. }
  297. }
  298. template<
  299. typename ControlAlgorithm,typename... Algorithms,
  300. typename PolyCollection,typename... Args
  301. >
  302. void test_algorithms(PolyCollection& p,Args&&... args)
  303. {
  304. do_((test_algorithm<ControlAlgorithm,Algorithms>(
  305. p,std::forward<Args>(args)...),0)...);
  306. do_((test_algorithm<ControlAlgorithm,Algorithms>(
  307. const_cast<const PolyCollection&>(p),std::forward<Args>(args)...),0)...);
  308. }
  309. template<
  310. typename ControlAlgorithm,typename... Algorithms,
  311. typename PolyCollection,typename... Args
  312. >
  313. void test_algorithms_with_equality_impl(
  314. std::true_type,PolyCollection& p,Args&&... args)
  315. {
  316. test_algorithms<ControlAlgorithm,Algorithms...>(
  317. p,std::forward<Args>(args)...);
  318. }
  319. template<
  320. typename ControlAlgorithm,typename... Algorithm,
  321. typename PolyCollection,typename... Args
  322. >
  323. void test_algorithms_with_equality_impl(
  324. std::false_type,PolyCollection&,Args&&...)
  325. {
  326. }
  327. template<
  328. typename ControlAlgorithm,typename... Algorithms,
  329. typename PolyCollection,typename... Args
  330. >
  331. void test_algorithms_with_equality(PolyCollection& p,Args&&... args)
  332. {
  333. test_algorithms_with_equality_impl<ControlAlgorithm,Algorithms...>(
  334. is_equality_comparable<typename PolyCollection::value_type>{},
  335. p,std::forward<Args>(args)...);
  336. }
  337. template<
  338. typename ControlAlgorithm,typename Algorithm,
  339. typename ToInt,typename PolyCollection
  340. >
  341. void test_for_each_n_algorithm(ToInt to_int,PolyCollection& p)
  342. {
  343. Algorithm alg;
  344. ControlAlgorithm control;
  345. for(auto first=p.begin(),end=p.end();;++first){
  346. for(auto n=std::distance(first,end);n>=0;--n){
  347. int res1=0,res2=0;
  348. auto acc1=compose(to_int,[&](int x){res1+=x;});
  349. auto acc2=compose(to_int,[&](int x){res2+=x;});
  350. auto it1=alg(first,n,acc1),
  351. it2=control(first,n,acc2);
  352. BOOST_TEST(it1==it2);
  353. BOOST_TEST(res1==res2);
  354. }
  355. if(first==end)break;
  356. }
  357. }
  358. template<
  359. typename ControlAlgorithm,typename... Algorithms,
  360. typename ToInt,typename PolyCollection
  361. >
  362. void test_for_each_n_algorithms(ToInt to_int,PolyCollection& p)
  363. {
  364. do_((test_for_each_n_algorithm<ControlAlgorithm,Algorithms>(
  365. to_int,p),0)...);
  366. do_((test_for_each_n_algorithm<ControlAlgorithm,Algorithms>(
  367. to_int,const_cast<const PolyCollection&>(p)),0)...);
  368. }
  369. template<
  370. typename ControlAlgorithm,typename Algorithm,
  371. typename ToInt,typename PolyCollection,typename... Args
  372. >
  373. void test_copy_algorithm(ToInt to_int,PolyCollection& p,Args&&... args)
  374. {
  375. Algorithm alg;
  376. ControlAlgorithm control;
  377. for(auto first=p.begin(),end=p.end();;++first){
  378. for(auto last=first;;++last){
  379. using vector=std::vector<int>;
  380. vector v1,v2;
  381. auto insert1=compose(to_int,[&](int x){v1.push_back(x);});
  382. auto insert2=compose(to_int,[&](int x){v2.push_back(x);});
  383. auto out1=boost::make_function_output_iterator(std::ref(insert1));
  384. auto out2=boost::make_function_output_iterator(std::ref(insert2));
  385. out1=alg(first,last,out1,std::forward<Args>(args)...);
  386. out2=control(first,last,out2,std::forward<Args>(args)...);
  387. BOOST_TEST(v1==v2);
  388. if(last==end)break;
  389. }
  390. if(first==end)break;
  391. }
  392. }
  393. template<
  394. typename ControlAlgorithm,typename... Algorithms,
  395. typename ToInt,typename PolyCollection,typename... Args
  396. >
  397. void test_copy_algorithms(ToInt to_int,PolyCollection& p,Args&&... args)
  398. {
  399. do_((test_copy_algorithm<ControlAlgorithm,Algorithms>(
  400. to_int,p,std::forward<Args>(args)...),0)...);
  401. do_((test_copy_algorithm<ControlAlgorithm,Algorithms>(
  402. to_int,const_cast<const PolyCollection&>(p),
  403. std::forward<Args>(args)...),0)...);
  404. }
  405. template<
  406. typename ControlAlgorithm,typename... Algorithms,
  407. typename ToInt,typename PolyCollection,typename... Args
  408. >
  409. void test_copy_algorithms_with_equality_impl(
  410. std::true_type,ToInt to_int,PolyCollection& p,Args&&... args)
  411. {
  412. test_copy_algorithms<ControlAlgorithm,Algorithms...>(
  413. to_int,p,std::forward<Args>(args)...);
  414. }
  415. template<
  416. typename ControlAlgorithm,typename... Algorithm,
  417. typename ToInt,typename PolyCollection,typename... Args
  418. >
  419. void test_copy_algorithms_with_equality_impl(
  420. std::false_type,ToInt,PolyCollection&,Args&&...)
  421. {
  422. }
  423. template<
  424. typename ControlAlgorithm,typename... Algorithms,
  425. typename ToInt,typename PolyCollection,typename... Args
  426. >
  427. void test_copy_algorithms_with_equality(
  428. ToInt to_int,PolyCollection& p,Args&&... args)
  429. {
  430. test_copy_algorithms_with_equality_impl<ControlAlgorithm,Algorithms...>(
  431. is_equality_comparable<typename PolyCollection::value_type>{},
  432. to_int,p,std::forward<Args>(args)...);
  433. }
  434. template<
  435. typename ControlAlgorithm,typename Algorithm,
  436. typename ToInt,typename PolyCollection,typename... Args
  437. >
  438. void test_copy_n_algorithm(ToInt to_int,PolyCollection& p,Args&&... args)
  439. {
  440. Algorithm alg;
  441. ControlAlgorithm control;
  442. for(auto first=p.begin(),end=p.end();;++first){
  443. for(std::ptrdiff_t n=0,m=std::distance(first,end);n<=m;++n){
  444. using vector=std::vector<int>;
  445. vector v1,v2;
  446. auto insert1=compose(to_int,[&](int x){v1.push_back(x);});
  447. auto insert2=compose(to_int,[&](int x){v2.push_back(x);});
  448. auto out1=boost::make_function_output_iterator(std::ref(insert1));
  449. auto out2=boost::make_function_output_iterator(std::ref(insert2));
  450. alg(first,n,out1,std::forward<Args>(args)...);
  451. control(first,n,out2,std::forward<Args>(args)...);
  452. BOOST_TEST(v1==v2);
  453. }
  454. if(first==end)break;
  455. }
  456. }
  457. template<
  458. typename ControlAlgorithm,typename... Algorithms,
  459. typename ToInt,typename PolyCollection,typename... Args
  460. >
  461. void test_copy_n_algorithms(ToInt to_int,PolyCollection& p,Args&&... args)
  462. {
  463. do_((test_copy_n_algorithm<ControlAlgorithm,Algorithms>(
  464. to_int,p,std::forward<Args>(args)...),0)...);
  465. do_((test_copy_n_algorithm<ControlAlgorithm,Algorithms>(
  466. to_int,const_cast<const PolyCollection&>(p),
  467. std::forward<Args>(args)...),0)...);
  468. }
  469. template<
  470. typename ControlAlgorithm,typename Algorithm,
  471. typename ToInt,typename PolyCollection
  472. >
  473. void test_transform2_algorithm(ToInt to_int,PolyCollection& p)
  474. {
  475. Algorithm alg;
  476. ControlAlgorithm control;
  477. for(auto first=p.begin(),end=p.end();;++first){
  478. for(auto last=first;;++last){
  479. using vector=std::vector<int>;
  480. auto op=compose_all(to_int,[](int x,int y){return x+y;});
  481. vector v1,v2;
  482. auto insert1=[&](int x){v1.push_back(x);};
  483. auto insert2=[&](int x){v2.push_back(x);};
  484. auto out1=boost::make_function_output_iterator(std::ref(insert1));
  485. auto out2=boost::make_function_output_iterator(std::ref(insert2));
  486. out1=alg(first,last,p.begin(),out1,op);
  487. out2=control(first,last,p.begin(),out2,op);
  488. BOOST_TEST(v1==v2);
  489. if(last==end)break;
  490. }
  491. if(first==end)break;
  492. }
  493. }
  494. template<
  495. typename ControlAlgorithm,typename... Algorithms,
  496. typename ToInt,typename PolyCollection
  497. >
  498. void test_transform2_algorithms(ToInt to_int,PolyCollection& p)
  499. {
  500. do_((test_transform2_algorithm<ControlAlgorithm,Algorithms>(
  501. to_int,p),0)...);
  502. do_((test_transform2_algorithm<ControlAlgorithm,Algorithms>(
  503. to_int,const_cast<const PolyCollection&>(p)),0)...);
  504. }
  505. template<
  506. typename ControlAlgorithm,typename Algorithm,
  507. typename ToInt,typename PolyCollection
  508. >
  509. void test_rotate_copy_algorithm(ToInt to_int,PolyCollection& p)
  510. {
  511. Algorithm alg;
  512. ControlAlgorithm control;
  513. for(auto first=p.begin(),end=p.end();;++first){
  514. for(auto last=first;;++last){
  515. for(auto middle=first;;++middle){
  516. using vector=std::vector<int>;
  517. vector v1,v2;
  518. auto insert1=compose(to_int,[&](int x){v1.push_back(x);});
  519. auto insert2=compose(to_int,[&](int x){v2.push_back(x);});
  520. auto out1=boost::make_function_output_iterator(std::ref(insert1));
  521. auto out2=boost::make_function_output_iterator(std::ref(insert2));
  522. out1=alg(first,middle,last,out1);
  523. out2=control(first,middle,last,out2);
  524. BOOST_TEST(v1==v2);
  525. if(middle==last)break;
  526. }
  527. if(last==end)break;
  528. }
  529. if(first==end)break;
  530. }
  531. }
  532. template<
  533. typename ControlAlgorithm,typename... Algorithms,
  534. typename ToInt,typename PolyCollection
  535. >
  536. void test_rotate_copy_algorithms(ToInt to_int,PolyCollection& p)
  537. {
  538. do_((test_rotate_copy_algorithm<ControlAlgorithm,Algorithms>(
  539. to_int,p),0)...);
  540. do_((test_rotate_copy_algorithm<ControlAlgorithm,Algorithms>(
  541. to_int,const_cast<const PolyCollection&>(p)),0)...);
  542. }
  543. template<
  544. typename ControlAlgorithm,typename Algorithm,
  545. typename ToInt,typename PolyCollection,typename Predicate
  546. >
  547. void test_partition_copy_algorithm(
  548. ToInt to_int,PolyCollection& p,Predicate pred)
  549. {
  550. Algorithm alg;
  551. ControlAlgorithm control;
  552. for(auto first=p.begin(),end=p.end();;++first){
  553. for(auto last=first;;++last){
  554. using vector=std::vector<int>;
  555. vector v11,v12,v21,v22;
  556. auto insert11=compose(to_int,[&](int x){v11.push_back(x);});
  557. auto insert12=compose(to_int,[&](int x){v12.push_back(x);});
  558. auto insert21=compose(to_int,[&](int x){v21.push_back(x);});
  559. auto insert22=compose(to_int,[&](int x){v22.push_back(x);});
  560. auto out11=boost::make_function_output_iterator(std::ref(insert11));
  561. auto out12=boost::make_function_output_iterator(std::ref(insert12));
  562. auto out21=boost::make_function_output_iterator(std::ref(insert21));
  563. auto out22=boost::make_function_output_iterator(std::ref(insert22));
  564. std::tie(out11,out12)=alg(first,last,out11,out12,pred);
  565. std::tie(out21,out22)=control(first,last,out21,out22,pred);
  566. BOOST_TEST(v11==v21);
  567. BOOST_TEST(v12==v22);
  568. if(last==end)break;
  569. }
  570. if(first==end)break;
  571. }
  572. }
  573. template<
  574. typename ControlAlgorithm,typename... Algorithms,
  575. typename ToInt,typename PolyCollection,typename Predicate
  576. >
  577. void test_partition_copy_algorithms(
  578. ToInt to_int,PolyCollection& p,Predicate pred)
  579. {
  580. do_((test_partition_copy_algorithm<ControlAlgorithm,Algorithms>(
  581. to_int,p,pred),0)...);
  582. do_((test_partition_copy_algorithm<ControlAlgorithm,Algorithms>(
  583. to_int,const_cast<const PolyCollection&>(p),pred),0)...);
  584. }
  585. template<typename ToInt>
  586. struct poly_accumulator_class
  587. {
  588. poly_accumulator_class(const ToInt& to_int):res{0},to_int(to_int){}
  589. bool operator==(const poly_accumulator_class& x)const{return res==x.res;}
  590. template<typename T> void operator()(const T& x){res+=to_int(x);}
  591. int res;
  592. ToInt to_int;
  593. };
  594. template<typename ToInt>
  595. poly_accumulator_class<ToInt> poly_accumulator(const ToInt& to_int)
  596. {
  597. return to_int;
  598. }
  599. template<typename Algorithm>
  600. struct force_arg_copying
  601. {
  602. Algorithm alg;
  603. template<typename T>
  604. static T copy(const T& x){return x;}
  605. template<typename... Args>
  606. auto operator()(Args&&... args)const
  607. ->decltype(std::declval<Algorithm>()(copy(args)...))
  608. {
  609. return alg(copy(args)...);
  610. }
  611. };
  612. template<
  613. typename PolyCollection,typename ValueFactory,typename ToInt,
  614. typename... Types
  615. >
  616. void test_algorithm()
  617. {
  618. PolyCollection p;
  619. ValueFactory v;
  620. ToInt to_int;
  621. fill<constraints<>,Types...>(p,v,2);
  622. {
  623. auto always_true=compose(to_int,[](int){return true;});
  624. auto always_false=compose(to_int,[](int){return false;});
  625. auto pred=compose(to_int,[](int x){return x%2==0;});
  626. test_algorithms<std_all_of<>,poly_all_of<>,poly_all_of<Types...>>(
  627. p,always_true);
  628. test_algorithms<std_all_of<>,poly_all_of<>,poly_all_of<Types...>>(
  629. p,always_false);
  630. test_algorithms<std_all_of<>,poly_all_of<>,poly_all_of<Types...>>(
  631. p,pred);
  632. test_algorithms<std_any_of<>,poly_any_of<>,poly_any_of<Types...>>(
  633. p,always_true);
  634. test_algorithms<std_any_of<>,poly_any_of<>,poly_any_of<Types...>>(
  635. p,always_false);
  636. test_algorithms<std_any_of<>,poly_any_of<>,poly_any_of<Types...>>(
  637. p,pred);
  638. test_algorithms<std_none_of<>,poly_none_of<>,poly_none_of<Types...>>(
  639. p,always_true);
  640. test_algorithms<std_none_of<>,poly_none_of<>,poly_none_of<Types...>>(
  641. p,always_false);
  642. test_algorithms<std_none_of<>,poly_none_of<>,poly_none_of<Types...>>(
  643. p,pred);
  644. }
  645. {
  646. test_algorithms<std_for_each<>,poly_for_each<>,poly_for_each<Types...>>(
  647. p,poly_accumulator(to_int));
  648. test_for_each_n_algorithms<
  649. std_for_each_n<>,poly_for_each_n<>,poly_for_each_n<Types...>
  650. >(to_int,p);
  651. }
  652. {
  653. for(const auto& x:p){
  654. test_algorithms_with_equality<
  655. std_find<>,poly_find<>,only_eq_comparable<poly_find,Types...>
  656. >(p,x);
  657. }
  658. }
  659. {
  660. auto it=p.begin();
  661. std::advance(it,p.size()/2);
  662. int n=to_int(*it);
  663. auto pred=compose(to_int,[=](int x){return x==n;});
  664. test_algorithms<std_find_if<>,poly_find_if<>,poly_find_if<Types...>>(
  665. p,pred);
  666. test_algorithms<
  667. std_find_if_not<>,poly_find_if_not<>,poly_find_if_not<Types...>
  668. >(p,pred);
  669. }
  670. {
  671. auto first=p.begin(),end=first;
  672. std::advance(end,+p.size()/2);
  673. for(;first!=end;++first){
  674. test_algorithms_with_equality<
  675. std_find_end<>,poly_find_end<>,
  676. only_eq_comparable<poly_find_end,Types...>
  677. >(p,first,end);
  678. test_algorithms_with_equality<
  679. std_search<>,poly_search<>,
  680. only_eq_comparable<poly_search,Types...>
  681. >(p,first,end);
  682. }
  683. }
  684. {
  685. std::vector<int> v;
  686. for(const auto& x:p)v.push_back(to_int(x));
  687. v.erase(v.begin()+v.size()/2,v.end());
  688. for(auto first=v.begin(),end=v.begin()+v.size()/2;first!=end;++first){
  689. for(int i=1;i<4;++i){
  690. auto pred=compose(to_int,[&](int x,int y){return x%i==y%i;});
  691. test_algorithms<
  692. std_find_end<>,poly_find_end<>,poly_find_end<Types...>
  693. >(p,first,end,pred);
  694. test_algorithms<std_search<>,poly_search<>,poly_search<Types...>>(
  695. p,first,end,pred);
  696. }
  697. }
  698. }
  699. {
  700. using value_type=typename PolyCollection::value_type;
  701. using vector=std::vector<std::reference_wrapper<const value_type>>;
  702. vector v;
  703. for(const auto& x:p){
  704. switch(v.size()%3){
  705. case 0:v.push_back(x);break;
  706. case 1:v.push_back(*p.begin());break;
  707. default:{}
  708. }
  709. }
  710. for(auto first=v.begin(),end=v.end();;++first){
  711. for(auto last=first;;++last){
  712. test_algorithms_with_equality<
  713. std_find_first_of<>,poly_find_first_of<>,
  714. only_eq_comparable<poly_find_first_of,Types...>
  715. >(p,first,last);
  716. if(last==end)break;
  717. }
  718. if(first==end)break;
  719. }
  720. }
  721. {
  722. std::vector<int> v;
  723. for(const auto& x:p){
  724. switch(v.size()%3){
  725. case 0:v.push_back(to_int(x));break;
  726. case 1:v.push_back(-1);break;
  727. default:{}
  728. }
  729. }
  730. for(auto first=v.begin(),end=v.end();;++first){
  731. for(auto last=first;;++last){
  732. test_algorithms<
  733. std_find_first_of<>,poly_find_first_of<>,poly_find_first_of<Types...>
  734. >(p,first,last,compose(to_int,std::equal_to<int>{}));
  735. if(last==end)break;
  736. }
  737. if(first==end)break;
  738. }
  739. }
  740. {
  741. test_algorithms_with_equality<
  742. std_adjacent_find<>,poly_adjacent_find<>,
  743. only_eq_comparable<poly_adjacent_find,Types...>
  744. >(p);
  745. }
  746. {
  747. std::vector<int> v;
  748. for(const auto& x:p)v.push_back(to_int(x));
  749. v.push_back(-1);
  750. for(auto first=v.begin(),end=v.end()-1;first!=end;++first){
  751. int n1=*first,n2=*(first+1);
  752. test_algorithms<
  753. std_adjacent_find<>,poly_adjacent_find<>,poly_adjacent_find<Types...>
  754. >(p,compose_all(to_int,[=](int x,int y){return x==n1&&y==n2;}));
  755. }
  756. }
  757. {
  758. for(const auto& x:p){
  759. test_algorithms_with_equality<
  760. std_count<>,poly_count<>,only_eq_comparable<poly_count,Types...>
  761. >(p,x);
  762. }
  763. }
  764. {
  765. for(int i=1;i<4;++i){
  766. test_algorithms<std_count_if<>,poly_count_if<>,poly_count_if<Types...>>(
  767. p,compose(to_int,[&](int x){return x%i==0;}));
  768. }
  769. }
  770. {
  771. using value_type=typename PolyCollection::value_type;
  772. using vector=std::vector<std::reference_wrapper<const value_type>>;
  773. vector v;
  774. for(const auto& x:p)v.push_back(x);
  775. v.back()=v.front();
  776. auto w=v;
  777. v.insert(v.end(),w.begin(),w.end());
  778. for(auto first=v.begin(),end=v.begin()+v.size()/2;first!=end;++first){
  779. test_algorithms_with_equality<
  780. std_mismatch<>,poly_mismatch<>,
  781. only_eq_comparable<poly_mismatch,Types...>
  782. >(p,first);
  783. test_algorithms_with_equality<
  784. std_mismatch<>,poly_mismatch<>,
  785. only_eq_comparable<poly_mismatch,Types...>
  786. >(p,first,end);
  787. test_algorithms_with_equality<
  788. std_equal<>,poly_equal<>,only_eq_comparable<poly_equal,Types...>
  789. >(p,first);
  790. test_algorithms_with_equality<
  791. std_equal<>,poly_equal<>,only_eq_comparable<poly_equal,Types...>
  792. >(p,first,end);
  793. }
  794. test_algorithms_with_equality<
  795. std_mismatch<>,poly_mismatch<>,only_eq_comparable<poly_mismatch,Types...>
  796. >(p,v.end(),v.end());
  797. test_algorithms_with_equality<
  798. std_equal<>,poly_equal<>,only_eq_comparable<poly_equal,Types...>
  799. >(p,v.end(),v.end());
  800. }
  801. {
  802. std::vector<int> v;
  803. for(const auto& x:p)v.push_back(to_int(x));
  804. v.back()=-1;
  805. auto w=v;
  806. v.insert(v.end(),w.begin(),w.end());
  807. auto pred=compose(to_int,std::equal_to<int>{});
  808. for(auto first=v.begin(),end=v.begin()+v.size()/2;first!=end;++first){
  809. test_algorithms<std_mismatch<>,poly_mismatch<>,poly_mismatch<Types...>>(
  810. p,first,pred);
  811. test_algorithms<std_mismatch<>,poly_mismatch<>,poly_mismatch<Types...>>(
  812. p,first,end,pred);
  813. test_algorithms<std_equal<>,poly_equal<>,poly_equal<Types...>>(
  814. p,first,pred);
  815. test_algorithms<std_equal<>,poly_equal<>,poly_equal<Types...>>(
  816. p,first,end,pred);
  817. }
  818. test_algorithms<std_mismatch<>,poly_mismatch<>,poly_mismatch<Types...>>(
  819. p,v.end(),v.end(),pred);
  820. test_algorithms<std_equal<>,poly_equal<>,poly_equal<Types...>>(
  821. p,v.end(),v.end(),pred);
  822. }
  823. {
  824. using value_type=typename PolyCollection::value_type;
  825. using vector=std::vector<std::reference_wrapper<const value_type>>;
  826. vector v;
  827. for(const auto& x:p)v.push_back(x);
  828. auto w=v;
  829. std::mt19937 gen{73642};
  830. std::shuffle(w.begin(),w.end(),gen);
  831. v.insert(v.end(),w.begin(),w.end());
  832. auto pred=compose_all(to_int,std::equal_to<int>{});
  833. for(auto first=unwrap_iterator(v.begin()),
  834. end=unwrap_iterator(v.begin()+v.size()/2);first!=end;++first){
  835. test_algorithms_with_equality<
  836. std_is_permutation<>,
  837. poly_is_permutation<>,
  838. only_eq_comparable<poly_is_permutation,Types...>
  839. >(p,first);
  840. test_algorithms<
  841. std_is_permutation<>,
  842. poly_is_permutation<>,poly_is_permutation<Types...>
  843. >(p,first,pred);
  844. test_algorithms_with_equality<
  845. std_is_permutation<>,
  846. poly_is_permutation<>,
  847. only_eq_comparable<poly_is_permutation,Types...>
  848. >(p,first,end);
  849. test_algorithms<
  850. std_is_permutation<>,
  851. poly_is_permutation<>,poly_is_permutation<Types...>
  852. >(p,first,end,pred);
  853. }
  854. test_algorithms_with_equality<
  855. std_is_permutation<>,
  856. poly_is_permutation<>,
  857. only_eq_comparable<poly_is_permutation,Types...>
  858. >(p,unwrap_iterator(v.end()),unwrap_iterator(v.end()));
  859. test_algorithms<
  860. std_is_permutation<>,
  861. poly_is_permutation<>,poly_is_permutation<Types...>
  862. >(p,unwrap_iterator(v.end()),unwrap_iterator(v.end()),pred);
  863. }
  864. {
  865. /* search tested above */
  866. }
  867. {
  868. for(const auto&x: p){
  869. for(int n=0;n<3;++n){
  870. test_algorithms_with_equality<
  871. std_search_n<>,poly_search_n<>,
  872. only_eq_comparable<poly_search_n,Types...>
  873. >(p,n,x);
  874. }
  875. }
  876. }
  877. {
  878. for(int n=0;n<6;++n){
  879. test_algorithms<std_search_n<>,poly_search_n<>,poly_search_n<Types...>>(
  880. p,n,0,compose(to_int,[&](int x,int y){return x%(6-n)==y%(6-n);}));
  881. }
  882. }
  883. {
  884. test_copy_algorithms<std_copy<>,poly_copy<>,poly_copy<Types...>>(
  885. to_int,p);
  886. }
  887. {
  888. test_copy_n_algorithms<std_copy_n<>,poly_copy_n<>,poly_copy_n<Types...>>(
  889. to_int,p);
  890. }
  891. {
  892. auto always_true=compose(to_int,[](int){return true;});
  893. auto always_false=compose(to_int,[](int){return false;});
  894. auto pred=compose(to_int,[](int x){return x%2==0;});
  895. test_copy_algorithms<std_copy_if<>,poly_copy_if<>,poly_copy_if<Types...>>(
  896. to_int,p,always_true);
  897. test_copy_algorithms<std_copy_if<>,poly_copy_if<>,poly_copy_if<Types...>>(
  898. to_int,p,always_false);
  899. test_copy_algorithms<std_copy_if<>,poly_copy_if<>,poly_copy_if<Types...>>(
  900. to_int,p,pred);
  901. }
  902. {
  903. test_copy_algorithms<std_move<>,poly_move<>,poly_move<Types...>>(
  904. to_int,p); /* we're not checking std::move is properly used internally */
  905. }
  906. {
  907. auto f=compose(to_int,[](int x){return -x;});
  908. auto int_id=[](int x){return x;};
  909. test_copy_algorithms<
  910. std_transform<>,poly_transform<>,poly_transform<Types...>
  911. >(int_id,p,f);
  912. }
  913. {
  914. test_transform2_algorithms<
  915. std_transform<>,poly_transform<>,poly_transform<Types...>
  916. >(to_int,p);
  917. }
  918. {
  919. const auto& y=*p.begin();
  920. for(const auto& x:p){
  921. test_copy_algorithms_with_equality<
  922. std_replace_copy<>,poly_replace_copy<>,
  923. only_eq_comparable<poly_replace_copy,Types...>
  924. >(to_int,p,x,y);
  925. test_copy_algorithms_with_equality<
  926. std_remove_copy<>,poly_remove_copy<>,
  927. only_eq_comparable<poly_remove_copy,Types...>
  928. >(to_int,p,x);
  929. }
  930. }
  931. {
  932. auto always_true=compose(to_int,[](int){return true;});
  933. auto always_false=compose(to_int,[](int){return false;});
  934. auto pred=compose(to_int,[](int x){return x%2==0;});
  935. auto& x=*p.begin();
  936. test_copy_algorithms<
  937. std_replace_copy_if<>,
  938. poly_replace_copy_if<>,poly_replace_copy_if<Types...>
  939. >(to_int,p,always_true,x);
  940. test_copy_algorithms<
  941. std_replace_copy_if<>,
  942. poly_replace_copy_if<>,poly_replace_copy_if<Types...>
  943. >(to_int,p,always_false,x);
  944. test_copy_algorithms<
  945. std_replace_copy_if<>,
  946. poly_replace_copy_if<>,poly_replace_copy_if<Types...>
  947. >(to_int,p,pred,x);
  948. test_copy_algorithms<
  949. std_remove_copy_if<>,
  950. poly_remove_copy_if<>,poly_remove_copy_if<Types...>
  951. >(to_int,p,always_true);
  952. test_copy_algorithms<
  953. std_remove_copy_if<>,
  954. poly_remove_copy_if<>,poly_remove_copy_if<Types...>
  955. >(to_int,p,always_false);
  956. test_copy_algorithms<
  957. std_remove_copy_if<>,
  958. poly_remove_copy_if<>,poly_remove_copy_if<Types...>
  959. >(to_int,p,pred);
  960. }
  961. {
  962. test_copy_algorithms_with_equality<
  963. std_unique_copy<>,poly_unique_copy<>,
  964. only_eq_comparable<poly_unique_copy,Types...>
  965. >(to_int,p);
  966. }
  967. {
  968. for(int n=0;n<6;++n){
  969. test_copy_algorithms<
  970. std_unique_copy<>,poly_unique_copy<>,poly_unique_copy<Types...>
  971. >(to_int,p,
  972. compose_all(to_int,[&](int x,int y){return x%(6-n)==y%(6-n);}));
  973. }
  974. }
  975. {
  976. test_rotate_copy_algorithms<
  977. std_rotate_copy<>,poly_rotate_copy<>,poly_rotate_copy<Types...>
  978. >(to_int,p);
  979. }
  980. {
  981. /* force_arg_copying used to avoid sharing mt19937's state */
  982. for(auto n=p.size()+1;n-->0;){
  983. test_copy_algorithms<
  984. force_arg_copying<std_sample<>>,
  985. force_arg_copying<poly_sample<>>,
  986. force_arg_copying<poly_sample<Types...>>
  987. >(to_int,p,n,std::mt19937{});
  988. }
  989. }
  990. {
  991. for(int n=0;n<6;++n){
  992. auto pred=compose(to_int,[&](int x){return x%(6-n)<=(6-n)/2;});
  993. test_algorithms<
  994. std_is_partitioned<>,
  995. poly_is_partitioned<>,poly_is_partitioned<Types...>
  996. >(p,pred);
  997. test_partition_copy_algorithms<
  998. std_partition_copy<>,
  999. poly_partition_copy<>,poly_partition_copy<Types...>
  1000. >(to_int,p,pred);
  1001. test_algorithms<
  1002. std_partition_point<>,
  1003. poly_partition_point<>,poly_partition_point<Types...>
  1004. >(p,pred);
  1005. }
  1006. }
  1007. }
  1008. #endif