algorithm.hpp 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068
  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_ALGORITHM_HPP
  9. #define BOOST_POLY_COLLECTION_ALGORITHM_HPP
  10. #if defined(_MSC_VER)
  11. #pragma once
  12. #endif
  13. #include <algorithm>
  14. #include <boost/poly_collection/detail/auto_iterator.hpp>
  15. #include <boost/poly_collection/detail/functional.hpp>
  16. #include <boost/poly_collection/detail/iterator_traits.hpp>
  17. #include <boost/poly_collection/detail/segment_split.hpp>
  18. #include <boost/poly_collection/detail/type_restitution.hpp>
  19. #include <iterator>
  20. #include <type_traits>
  21. #include <utility>
  22. /* Improved performance versions of std algorithms over poly_collection.
  23. * poly_collection::alg is expected to be faster than the homonym std::alg
  24. * because the latter does a traversal over a segmented structured, where
  25. * incrementing requires checking for segment change, whereas the former
  26. * for-loops over flat segments.
  27. * Additionally, poly_collection::alg<Ti...>(...,f) *restitutes* Ti when
  28. * passing elements to f, i.e. if the concrete type of the element is Ti
  29. * then f is invoked with a [const] Ti&, which can dramatically improve
  30. * performance when f has specific overloads for Ti (like, for instance,
  31. * generic lambdas) as static optimization can kick in (devirtualization
  32. * being a particular example).
  33. */
  34. namespace boost{
  35. namespace poly_collection{
  36. namespace detail{
  37. namespace algorithm{
  38. template<typename Iterator>
  39. using enable_if_poly_collection_iterator=typename std::enable_if<
  40. !std::is_void<typename poly_collection_of<Iterator>::type>::value
  41. >::type*;
  42. BOOST_POLY_COLLECTION_DEFINE_OVERLOAD_SET(std_all_of,std::all_of)
  43. template<
  44. typename... Ts,typename Iterator,typename Predicate,
  45. enable_if_poly_collection_iterator<Iterator> =nullptr
  46. >
  47. bool all_of(const Iterator& first,const Iterator& last,Predicate pred)
  48. {
  49. auto alg=restitute_range<Ts...>(std_all_of{},pred);
  50. for(auto i:detail::segment_split(first,last))if(!alg(i))return false;
  51. return true;
  52. }
  53. BOOST_POLY_COLLECTION_DEFINE_OVERLOAD_SET(std_any_of,std::any_of)
  54. template<
  55. typename... Ts,typename Iterator,typename Predicate,
  56. enable_if_poly_collection_iterator<Iterator> =nullptr
  57. >
  58. bool any_of(const Iterator& first,const Iterator& last,Predicate pred)
  59. {
  60. auto alg=restitute_range<Ts...>(std_any_of{},pred);
  61. for(auto i:detail::segment_split(first,last))if(alg(i))return true;
  62. return false;
  63. }
  64. BOOST_POLY_COLLECTION_DEFINE_OVERLOAD_SET(std_none_of,std::none_of)
  65. template<
  66. typename... Ts,typename Iterator,typename Predicate,
  67. enable_if_poly_collection_iterator<Iterator> =nullptr
  68. >
  69. bool none_of(const Iterator& first,const Iterator& last,Predicate pred)
  70. {
  71. auto alg=restitute_range<Ts...>(std_none_of{},pred);
  72. for(auto i:detail::segment_split(first,last))if(!alg(i))return false;
  73. return true;
  74. }
  75. struct for_each_alg
  76. {
  77. template<typename InputIterator,typename Function>
  78. void operator()(
  79. InputIterator first,InputIterator last,Function& f)const /* note the & */
  80. {
  81. for(;first!=last;++first)f(*first);
  82. }
  83. };
  84. template<
  85. typename... Ts,typename Iterator,typename Function,
  86. enable_if_poly_collection_iterator<Iterator> =nullptr
  87. >
  88. Function for_each(const Iterator& first,const Iterator& last,Function f)
  89. {
  90. for_each_segment(first,last,restitute_range<Ts...>(for_each_alg{},f));
  91. return std::move(f);
  92. }
  93. template<
  94. typename Algorithm,typename... Ts,
  95. typename Iterator,typename... Args,
  96. enable_if_poly_collection_iterator<Iterator> =nullptr
  97. >
  98. Iterator generic_find(
  99. const Iterator& first,const Iterator& last,Args&&... args)
  100. {
  101. using traits=iterator_traits<Iterator>;
  102. using local_base_iterator=typename traits::local_base_iterator;
  103. auto alg=restitute_range<Ts...>(
  104. cast_return<local_base_iterator>(Algorithm{}),
  105. std::forward<Args>(args)...);
  106. for(auto i:detail::segment_split(first,last)){
  107. auto it=alg(i);
  108. if(it!=i.end())
  109. return traits::iterator_from(
  110. it,traits::end_base_segment_info_iterator_from(last));
  111. }
  112. return last;
  113. }
  114. BOOST_POLY_COLLECTION_DEFINE_OVERLOAD_SET(std_find,std::find)
  115. template<
  116. typename... Ts,typename Iterator,typename T,
  117. enable_if_poly_collection_iterator<Iterator> =nullptr
  118. >
  119. Iterator find(const Iterator& first,const Iterator& last,const T& x)
  120. {
  121. return generic_find<std_find,Ts...>(first,last,x);
  122. }
  123. BOOST_POLY_COLLECTION_DEFINE_OVERLOAD_SET(std_find_if,std::find_if)
  124. template<
  125. typename... Ts,typename Iterator,typename Predicate,
  126. enable_if_poly_collection_iterator<Iterator> =nullptr
  127. >
  128. Iterator find_if(const Iterator& first,const Iterator& last,Predicate pred)
  129. {
  130. return generic_find<std_find_if,Ts...>(first,last,pred);
  131. }
  132. BOOST_POLY_COLLECTION_DEFINE_OVERLOAD_SET(std_find_if_not,std::find_if_not)
  133. template<
  134. typename... Ts,typename Iterator,typename Predicate,
  135. enable_if_poly_collection_iterator<Iterator> =nullptr
  136. >
  137. Iterator find_if_not(const Iterator& first,const Iterator& last,Predicate pred)
  138. {
  139. return generic_find<std_find_if_not,Ts...>(first,last,pred);
  140. }
  141. /* find_end defined after search below */
  142. BOOST_POLY_COLLECTION_DEFINE_OVERLOAD_SET(std_find_first_of,std::find_first_of)
  143. template<
  144. typename... Ts,typename Iterator,typename ForwardIterator,
  145. enable_if_poly_collection_iterator<Iterator> =nullptr
  146. >
  147. Iterator find_first_of(
  148. const Iterator& first1,const Iterator& last1,
  149. ForwardIterator first2,ForwardIterator last2)
  150. {
  151. return generic_find<std_find_first_of,Ts...>(first1,last1,first2,last2);
  152. }
  153. template<
  154. typename... Ts,typename Iterator,
  155. typename ForwardIterator,typename BinaryPredicate,
  156. enable_if_poly_collection_iterator<Iterator> =nullptr
  157. >
  158. Iterator find_first_of(
  159. const Iterator& first1,const Iterator& last1,
  160. ForwardIterator first2,ForwardIterator last2,BinaryPredicate pred)
  161. {
  162. return generic_find<std_find_first_of,Ts...>(first1,last1,first2,last2,pred);
  163. }
  164. template<typename... Ts>
  165. struct adjacent_find_alg
  166. {
  167. template<
  168. typename LocalIterator,typename BinaryPredicate,typename LocalBaseIterator
  169. >
  170. LocalBaseIterator operator()(
  171. LocalIterator first,LocalIterator last,BinaryPredicate pred,
  172. bool& carry,const std::type_info* prev_info, /* note the &s */
  173. LocalBaseIterator& prev)const
  174. {
  175. if(first==last)return LocalBaseIterator{last};
  176. if(carry){
  177. auto p=restitute_iterator<Ts...>(deref_to(pred));
  178. if(p(*prev_info,prev,first))return prev;
  179. }
  180. auto res=std::adjacent_find(first,last,pred);
  181. if(res==last){
  182. carry=true;
  183. prev_info=&typeid(
  184. typename std::iterator_traits<LocalIterator>::value_type);
  185. prev=LocalBaseIterator{last-1};
  186. }
  187. else carry=false;
  188. return LocalBaseIterator{res};
  189. }
  190. };
  191. template<
  192. typename... Ts,typename Iterator,typename BinaryPredicate,
  193. enable_if_poly_collection_iterator<Iterator> =nullptr
  194. >
  195. Iterator adjacent_find(
  196. const Iterator& first,const Iterator& last,BinaryPredicate pred)
  197. {
  198. using traits=iterator_traits<Iterator>;
  199. using local_base_iterator=typename traits::local_base_iterator;
  200. bool carry=false;
  201. const std::type_info* prev_info{&typeid(void)};
  202. local_base_iterator prev;
  203. return generic_find<adjacent_find_alg<Ts...>,Ts...>(
  204. first,last,pred,carry,prev_info,prev);
  205. }
  206. template<
  207. typename... Ts,typename Iterator,
  208. enable_if_poly_collection_iterator<Iterator> =nullptr
  209. >
  210. Iterator adjacent_find(const Iterator& first,const Iterator& last)
  211. {
  212. return algorithm::adjacent_find<Ts...>(first,last,transparent_equal_to{});
  213. }
  214. template<
  215. typename Algorithm,typename... Ts,
  216. typename Iterator,typename... Args,
  217. enable_if_poly_collection_iterator<Iterator> =nullptr
  218. >
  219. std::ptrdiff_t generic_count(
  220. const Iterator& first,const Iterator& last,Args&&... args)
  221. {
  222. auto alg=restitute_range<Ts...>(Algorithm{},std::forward<Args>(args)...);
  223. std::ptrdiff_t res=0;
  224. for(auto i:detail::segment_split(first,last))res+=alg(i);
  225. return res;
  226. }
  227. BOOST_POLY_COLLECTION_DEFINE_OVERLOAD_SET(std_count,std::count)
  228. template<
  229. typename... Ts,typename Iterator,typename T,
  230. enable_if_poly_collection_iterator<Iterator> =nullptr
  231. >
  232. std::ptrdiff_t count(const Iterator& first,const Iterator& last,const T& x)
  233. {
  234. return generic_count<std_count,Ts...>(first,last,x);
  235. }
  236. BOOST_POLY_COLLECTION_DEFINE_OVERLOAD_SET(std_count_if,std::count_if)
  237. template<
  238. typename... Ts,typename Iterator,typename Predicate,
  239. enable_if_poly_collection_iterator<Iterator> =nullptr
  240. >
  241. std::ptrdiff_t count_if(
  242. const Iterator& first,const Iterator& last,Predicate pred)
  243. {
  244. return generic_count<std_count_if,Ts...>(first,last,pred);
  245. }
  246. struct mismatch_alg
  247. {
  248. template<
  249. typename InputIterator1,
  250. typename InputIterator2,typename BinaryPredicate
  251. >
  252. InputIterator1 operator()(
  253. InputIterator1 first1,InputIterator1 last1,
  254. InputIterator2& first2,BinaryPredicate pred)const /* note the & */
  255. {
  256. while(first1!=last1&&pred(*first1,*first2)){
  257. ++first1;
  258. ++first2;
  259. }
  260. return first1;
  261. }
  262. template<
  263. typename InputIterator1,
  264. typename InputIterator2,typename BinaryPredicate
  265. >
  266. InputIterator1 operator()(
  267. InputIterator1 first1,InputIterator1 last1,
  268. InputIterator2& first2,InputIterator2 last2, /* note the & */
  269. BinaryPredicate pred)const
  270. {
  271. while(first1!=last1&&first2!=last2&&pred(*first1,*first2)){
  272. ++first1;
  273. ++first2;
  274. }
  275. return first1;
  276. }
  277. };
  278. template<
  279. typename... Ts,typename Iterator,
  280. typename InputIterator,typename BinaryPredicate,
  281. enable_if_poly_collection_iterator<Iterator> =nullptr
  282. >
  283. std::pair<Iterator,InputIterator> mismatch(
  284. const Iterator& first1,const Iterator& last1,
  285. InputIterator first2,BinaryPredicate pred)
  286. {
  287. auto it=generic_find<mismatch_alg,Ts...>(first1,last1,first2,pred);
  288. return {it,first2};
  289. }
  290. template<
  291. typename... Ts,typename Iterator,typename InputIterator,
  292. enable_if_poly_collection_iterator<Iterator> =nullptr
  293. >
  294. std::pair<Iterator,InputIterator> mismatch(
  295. const Iterator& first1,const Iterator& last1,InputIterator first2)
  296. {
  297. return algorithm::mismatch<Ts...>(
  298. first1,last1,first2,transparent_equal_to{});
  299. }
  300. template<
  301. typename... Ts,typename Iterator,
  302. typename InputIterator,typename BinaryPredicate,
  303. enable_if_poly_collection_iterator<Iterator> =nullptr
  304. >
  305. std::pair<Iterator,InputIterator> mismatch(
  306. const Iterator& first1,const Iterator& last1,
  307. InputIterator first2,InputIterator last2,BinaryPredicate pred)
  308. {
  309. auto it=generic_find<mismatch_alg,Ts...>(first1,last1,first2,last2,pred);
  310. return {it,first2};
  311. }
  312. template<
  313. typename... Ts,typename Iterator,typename InputIterator,
  314. enable_if_poly_collection_iterator<Iterator> =nullptr
  315. >
  316. std::pair<Iterator,InputIterator> mismatch(
  317. const Iterator& first1,const Iterator& last1,
  318. InputIterator first2,InputIterator last2)
  319. {
  320. return algorithm::mismatch<Ts...>(
  321. first1,last1,first2,last2,transparent_equal_to{});
  322. }
  323. struct equal_alg
  324. {
  325. template<
  326. typename InputIterator1,
  327. typename InputIterator2,typename BinaryPredicate
  328. >
  329. bool operator()(
  330. InputIterator1 first1,InputIterator1 last1,
  331. InputIterator2& first2,BinaryPredicate pred)const /* note the & */
  332. {
  333. for(;first1!=last1;++first1,++first2){
  334. if(!pred(*first1,*first2))return false;
  335. }
  336. return true;
  337. }
  338. template<
  339. typename InputIterator1,
  340. typename InputIterator2,typename BinaryPredicate
  341. >
  342. bool operator()(
  343. InputIterator1 first1,InputIterator1 last1,
  344. InputIterator2& first2,InputIterator2 last2, /* note the & */
  345. BinaryPredicate pred)const
  346. {
  347. for(;first1!=last1&&first2!=last2;++first1,++first2){
  348. if(!pred(*first1,*first2))return false;
  349. }
  350. return first1==last1; /* don't check first2==last2 as op is partial */
  351. }
  352. };
  353. template<
  354. typename... Ts,typename Iterator,
  355. typename InputIterator,typename BinaryPredicate,
  356. enable_if_poly_collection_iterator<Iterator> =nullptr
  357. >
  358. bool equal(
  359. const Iterator& first1,const Iterator& last1,
  360. InputIterator first2,BinaryPredicate pred)
  361. {
  362. auto alg=restitute_range<Ts...>(equal_alg{},first2,pred);
  363. for(auto i:detail::segment_split(first1,last1))if(!alg(i))return false;
  364. return true;
  365. }
  366. template<
  367. typename... Ts,typename Iterator,typename InputIterator,
  368. enable_if_poly_collection_iterator<Iterator> =nullptr
  369. >
  370. bool equal(
  371. const Iterator& first1,const Iterator& last1,InputIterator first2)
  372. {
  373. return algorithm::equal<Ts...>(first1,last1,first2,transparent_equal_to{});
  374. }
  375. template<
  376. typename... Ts,typename Iterator,
  377. typename InputIterator,typename BinaryPredicate,
  378. enable_if_poly_collection_iterator<Iterator> =nullptr
  379. >
  380. bool equal(
  381. const Iterator& first1,const Iterator& last1,
  382. InputIterator first2,InputIterator last2,BinaryPredicate pred)
  383. {
  384. auto alg=restitute_range<Ts...>(equal_alg{},first2,last2,pred);
  385. for(auto i:detail::segment_split(first1,last1))if(!alg(i))return false;
  386. return first2==last2;
  387. }
  388. template<
  389. typename... Ts,typename Iterator,typename InputIterator,
  390. enable_if_poly_collection_iterator<Iterator> =nullptr
  391. >
  392. bool equal(
  393. const Iterator& first1,const Iterator& last1,
  394. InputIterator first2,InputIterator last2)
  395. {
  396. return algorithm::equal<Ts...>(
  397. first1,last1,first2,last2,transparent_equal_to{});
  398. }
  399. template<
  400. typename... Ts,typename Iterator,
  401. typename ForwardIterator,typename BinaryPredicate,
  402. enable_if_poly_collection_iterator<Iterator> =nullptr
  403. >
  404. bool is_permutation_suffix(
  405. const Iterator& first1,const Iterator& last1,
  406. ForwardIterator first2,ForwardIterator last2,BinaryPredicate pred)
  407. {
  408. using traits=iterator_traits<Iterator>;
  409. auto send=traits::end_base_segment_info_iterator_from(last1);
  410. for(auto i:detail::segment_split(first1,last1)){
  411. for(auto lbscan=i.begin();lbscan!=i.end();++lbscan){
  412. auto& info=i.type_info();
  413. auto p=head_closure(
  414. restitute_iterator<Ts...>(deref_1st_to(pred)),info,lbscan);
  415. auto scan=traits::iterator_from(lbscan,send);
  416. if(algorithm::find_if<Ts...>(first1,scan,p)!=scan)continue;
  417. std::ptrdiff_t matches=std::count_if(first2,last2,p);
  418. if(matches==0||
  419. matches!=algorithm::count_if<Ts...>(scan,last1,p))return false;
  420. }
  421. }
  422. return true;
  423. }
  424. template<
  425. typename... Ts,typename Iterator,
  426. typename ForwardIterator,typename BinaryPredicate,
  427. enable_if_poly_collection_iterator<Iterator> =nullptr
  428. >
  429. bool is_permutation(
  430. Iterator first1,Iterator last1,ForwardIterator first2,BinaryPredicate pred)
  431. {
  432. std::tie(first1,first2)=algorithm::mismatch<Ts...>(first1,last1,first2,pred);
  433. auto last2=std::next(first2,std::distance(first1,last1));
  434. return is_permutation_suffix<Ts...>(first1,last1,first2,last2,pred);
  435. }
  436. template<
  437. typename... Ts,typename Iterator,typename ForwardIterator,
  438. enable_if_poly_collection_iterator<Iterator> =nullptr
  439. >
  440. bool is_permutation(
  441. const Iterator& first1,const Iterator& last1,ForwardIterator first2)
  442. {
  443. return algorithm::is_permutation<Ts...>(
  444. first1,last1,first2,transparent_equal_to{});
  445. }
  446. template<
  447. typename... Ts,typename Iterator,
  448. typename ForwardIterator,typename BinaryPredicate,
  449. enable_if_poly_collection_iterator<Iterator> =nullptr
  450. >
  451. bool is_permutation(
  452. Iterator first1,Iterator last1,
  453. ForwardIterator first2,ForwardIterator last2,BinaryPredicate pred)
  454. {
  455. std::tie(first1,first2)=algorithm::mismatch<Ts...>(
  456. first1,last1,first2,last2,pred);
  457. if(std::distance(first1,last1)!=std::distance(first2,last2))return false;
  458. else return is_permutation_suffix<Ts...>(first1,last1,first2,last2,pred);
  459. }
  460. template<
  461. typename... Ts,typename Iterator,typename ForwardIterator,
  462. enable_if_poly_collection_iterator<Iterator> =nullptr
  463. >
  464. bool is_permutation(
  465. const Iterator& first1,const Iterator& last1,
  466. ForwardIterator first2,ForwardIterator last2)
  467. {
  468. return algorithm::is_permutation<Ts...>(
  469. first1,last1,first2,last2,transparent_equal_to{});
  470. }
  471. template<
  472. typename... Ts,typename Iterator,
  473. typename ForwardIterator,typename BinaryPredicate,
  474. enable_if_poly_collection_iterator<Iterator> =nullptr
  475. >
  476. Iterator search(
  477. const Iterator& first1,const Iterator& last1,
  478. ForwardIterator first2,ForwardIterator last2,BinaryPredicate pred)
  479. {
  480. using traits=iterator_traits<Iterator>;
  481. auto send=traits::end_base_segment_info_iterator_from(last1);
  482. for(auto i:detail::segment_split(first1,last1)){
  483. for(auto lbit=i.begin(),lbend=i.end();lbit!=lbend;++lbit){
  484. Iterator it=traits::iterator_from(lbit,send);
  485. if(algorithm::mismatch<Ts...>(it,last1,first2,last2,pred).second==last2)
  486. return it;
  487. }
  488. }
  489. return last1;
  490. }
  491. template<
  492. typename... Ts,typename Iterator,typename ForwardIterator,
  493. enable_if_poly_collection_iterator<Iterator> =nullptr
  494. >
  495. Iterator search(
  496. const Iterator& first1,const Iterator& last1,
  497. ForwardIterator first2,ForwardIterator last2)
  498. {
  499. return algorithm::search<Ts...>(
  500. first1,last1,first2,last2,transparent_equal_to{});
  501. }
  502. template<
  503. typename... Ts,typename Iterator,
  504. typename ForwardIterator,typename BinaryPredicate,
  505. enable_if_poly_collection_iterator<Iterator> =nullptr
  506. >
  507. Iterator find_end(
  508. Iterator first1,Iterator last1,
  509. ForwardIterator first2,ForwardIterator last2,BinaryPredicate pred)
  510. {
  511. if(first2==last2)return last1;
  512. for(Iterator res=last1;;){
  513. Iterator res1=algorithm::search<Ts...>(first1,last1,first2,last2,pred);
  514. if(res1==last1)return res;
  515. else{
  516. first1=res=res1;
  517. ++first1;
  518. }
  519. }
  520. }
  521. template<
  522. typename... Ts,typename Iterator,typename ForwardIterator,
  523. enable_if_poly_collection_iterator<Iterator> =nullptr
  524. >
  525. Iterator find_end(
  526. const Iterator& first1,const Iterator& last1,
  527. ForwardIterator first2,ForwardIterator last2)
  528. {
  529. return algorithm::find_end<Ts...>(
  530. first1,last1,first2,last2,transparent_equal_to{});
  531. }
  532. struct search_n_alg
  533. {
  534. template<
  535. typename ForwardIterator,typename Size,
  536. typename T,typename BinaryPredicate
  537. >
  538. ForwardIterator operator()(
  539. ForwardIterator first,ForwardIterator last,
  540. Size count,bool& carry,Size& remain,const T& x, /* note the &s */
  541. BinaryPredicate pred)const
  542. {
  543. for(;first!=last;++first){
  544. if(!pred(*first,x)){carry=false;remain=count;continue;}
  545. auto res=first;
  546. for(;;){
  547. if(--remain==0||++first==last)return res;
  548. if(!pred(*first,x)){carry=false;remain=count;break;}
  549. }
  550. }
  551. return last;
  552. }
  553. };
  554. template<
  555. typename... Ts,typename Iterator,
  556. typename Size,typename T,typename BinaryPredicate,
  557. enable_if_poly_collection_iterator<Iterator> =nullptr
  558. >
  559. Iterator search_n(
  560. const Iterator& first,const Iterator& last,
  561. Size count,const T& x,BinaryPredicate pred)
  562. {
  563. using traits=iterator_traits<Iterator>;
  564. using local_base_iterator=typename traits::local_base_iterator;
  565. if(count<=0)return first;
  566. bool carry=false;
  567. auto remain=count;
  568. auto alg=restitute_range<Ts...>(
  569. cast_return<local_base_iterator>(search_n_alg{}),
  570. count,carry,remain,x,pred);
  571. local_base_iterator prev;
  572. for(auto i:detail::segment_split(first,last)){
  573. auto it=alg(i);
  574. if(it!=i.end()){
  575. if(remain==0)
  576. return traits::iterator_from(
  577. carry?prev:it,
  578. traits::end_base_segment_info_iterator_from(last));
  579. else if(!carry){prev=it;carry=true;}
  580. }
  581. }
  582. return last;
  583. }
  584. template<
  585. typename... Ts,typename Iterator,
  586. typename Size,typename T,
  587. enable_if_poly_collection_iterator<Iterator> =nullptr
  588. >
  589. Iterator search_n(
  590. const Iterator& first,const Iterator& last,Size count,const T& x)
  591. {
  592. return algorithm::search_n<Ts...>(
  593. first,last,count,x,transparent_equal_to{});
  594. }
  595. template<
  596. typename Algorithm,typename... Ts,
  597. typename Iterator,typename OutputIterator,typename... Args,
  598. enable_if_poly_collection_iterator<Iterator> =nullptr
  599. >
  600. OutputIterator generic_copy(
  601. const Iterator& first,const Iterator& last,OutputIterator res,Args&&... args)
  602. {
  603. for(auto i:detail::segment_split(first,last)){
  604. auto alg=restitute_range<Ts...>(
  605. Algorithm{},res,std::forward<Args>(args)...);
  606. res=alg(i);
  607. }
  608. return res;
  609. }
  610. BOOST_POLY_COLLECTION_DEFINE_OVERLOAD_SET(std_copy,std::copy)
  611. template<
  612. typename... Ts,typename Iterator,typename OutputIterator,
  613. enable_if_poly_collection_iterator<Iterator> =nullptr
  614. >
  615. OutputIterator copy(
  616. const Iterator& first,const Iterator& last,OutputIterator res)
  617. {
  618. return generic_copy<std_copy,Ts...>(first,last,res);
  619. }
  620. BOOST_POLY_COLLECTION_DEFINE_OVERLOAD_SET(std_copy_n,std::copy_n)
  621. template<
  622. typename... Ts,typename Iterator,typename Size,typename OutputIterator,
  623. enable_if_poly_collection_iterator<Iterator> =nullptr
  624. >
  625. OutputIterator copy_n(const Iterator& first,Size count,OutputIterator res)
  626. {
  627. using traits=iterator_traits<Iterator>;
  628. if(count<=0)return res;
  629. auto lbit=traits::local_base_iterator_from(first);
  630. auto sit=traits::base_segment_info_iterator_from(first);
  631. for(;;){
  632. auto n=(std::min)(count,sit->end()-lbit);
  633. auto alg=restitute_iterator<Ts...>(std_copy_n{},n,res);
  634. res=alg(sit->type_info(),lbit);
  635. if((count-=n)==0)break;
  636. ++sit;
  637. lbit=sit->begin();
  638. }
  639. return res;
  640. }
  641. BOOST_POLY_COLLECTION_DEFINE_OVERLOAD_SET(std_copy_if,std::copy_if)
  642. template<
  643. typename... Ts,typename Iterator,typename OutputIterator,typename Predicate,
  644. enable_if_poly_collection_iterator<Iterator> =nullptr
  645. >
  646. OutputIterator copy_if(
  647. const Iterator& first,const Iterator& last,OutputIterator res,Predicate pred)
  648. {
  649. return generic_copy<std_copy_if,Ts...>(first,last,res,pred);
  650. }
  651. BOOST_POLY_COLLECTION_DEFINE_OVERLOAD_SET(std_move,std::move)
  652. template<
  653. typename... Ts,typename Iterator,typename OutputIterator,
  654. enable_if_poly_collection_iterator<Iterator> =nullptr
  655. >
  656. OutputIterator move(
  657. const Iterator& first,const Iterator& last,OutputIterator res)
  658. {
  659. return generic_copy<std_move,Ts...>(first,last,res);
  660. }
  661. BOOST_POLY_COLLECTION_DEFINE_OVERLOAD_SET(std_transform,std::transform)
  662. template<
  663. typename... Ts,typename Iterator,
  664. typename OutputIterator,typename UnaryOperation,
  665. enable_if_poly_collection_iterator<Iterator> =nullptr
  666. >
  667. OutputIterator transform(
  668. const Iterator& first,const Iterator& last,
  669. OutputIterator res,UnaryOperation op)
  670. {
  671. return generic_copy<std_transform,Ts...>(first,last,res,op);
  672. }
  673. struct transform2_alg
  674. {
  675. template<
  676. typename InputIterator1,typename InputIterator2,
  677. typename OutputIterator,typename BinaryOperation
  678. >
  679. OutputIterator operator()(
  680. InputIterator1 first1,InputIterator1 last1,
  681. OutputIterator res, /* third place for compatibility with generic_copy */
  682. InputIterator2& first2, BinaryOperation op)const /* note the & */
  683. {
  684. while(first1!=last1)*res++=op(*first1++,*first2++);
  685. return res;
  686. }
  687. };
  688. template<
  689. typename... Ts,typename Iterator,typename InputIterator,
  690. typename OutputIterator,typename BinaryOperation,
  691. enable_if_poly_collection_iterator<Iterator> =nullptr
  692. >
  693. OutputIterator transform(
  694. const Iterator& first1,const Iterator& last1,InputIterator first2,
  695. OutputIterator res,BinaryOperation op)
  696. {
  697. return generic_copy<transform2_alg,Ts...>(first1,last1,res,first2,op);
  698. }
  699. struct replace_copy_alg
  700. {
  701. /* std::replace_copy broken in VS2015, internal ticket VSO#279818
  702. * "<algorithm>: replace_copy() and replace_copy_if() shouldn't use the
  703. * conditional operator".
  704. */
  705. template<typename InputIterator,typename OutputIterator,typename T>
  706. OutputIterator operator()(
  707. InputIterator first,InputIterator last,OutputIterator res,
  708. const T& old_x,const T& new_x)
  709. {
  710. for(;first!=last;++first,++res){
  711. if(*first==old_x)*res=new_x;
  712. else *res=*first;
  713. }
  714. return res;
  715. }
  716. };
  717. template<
  718. typename... Ts,typename Iterator,typename OutputIterator,typename T,
  719. enable_if_poly_collection_iterator<Iterator> =nullptr
  720. >
  721. OutputIterator replace_copy(
  722. const Iterator& first,const Iterator& last,OutputIterator res,
  723. const T& old_x,const T& new_x)
  724. {
  725. return generic_copy<replace_copy_alg,Ts...>(first,last,res,old_x,new_x);
  726. }
  727. struct replace_copy_if_alg
  728. {
  729. /* std::replace_copy_if broken in VS2015, internal ticket VSO#279818
  730. * "<algorithm>: replace_copy() and replace_copy_if() shouldn't use the
  731. * conditional operator".
  732. */
  733. template<
  734. typename InputIterator,typename OutputIterator,
  735. typename Predicate,typename T
  736. >
  737. OutputIterator operator()(
  738. InputIterator first,InputIterator last,OutputIterator res,
  739. Predicate pred,const T& new_x)
  740. {
  741. for(;first!=last;++first,++res){
  742. if(pred(*first))*res=new_x;
  743. else *res=*first;
  744. }
  745. return res;
  746. }
  747. };
  748. template<
  749. typename... Ts,typename Iterator,typename OutputIterator,
  750. typename Predicate,typename T,
  751. enable_if_poly_collection_iterator<Iterator> =nullptr
  752. >
  753. OutputIterator replace_copy_if(
  754. const Iterator& first,const Iterator& last,OutputIterator res,
  755. Predicate pred,const T& new_x)
  756. {
  757. return generic_copy<replace_copy_if_alg,Ts...>(first,last,res,pred,new_x);
  758. }
  759. BOOST_POLY_COLLECTION_DEFINE_OVERLOAD_SET(std_remove_copy,std::remove_copy)
  760. template<
  761. typename... Ts,typename Iterator,typename OutputIterator,typename T,
  762. enable_if_poly_collection_iterator<Iterator> =nullptr
  763. >
  764. OutputIterator remove_copy(
  765. const Iterator& first,const Iterator& last,OutputIterator res,const T& x)
  766. {
  767. return generic_copy<std_remove_copy,Ts...>(first,last,res,x);
  768. }
  769. BOOST_POLY_COLLECTION_DEFINE_OVERLOAD_SET(
  770. std_remove_copy_if,std::remove_copy_if)
  771. template<
  772. typename... Ts,typename Iterator,typename OutputIterator,typename Predicate,
  773. enable_if_poly_collection_iterator<Iterator> =nullptr
  774. >
  775. OutputIterator remove_copy_if(
  776. const Iterator& first,const Iterator& last,OutputIterator res,Predicate pred)
  777. {
  778. return generic_copy<std_remove_copy_if,Ts...>(first,last,res,pred);
  779. }
  780. template<typename... Ts>
  781. struct unique_copy_alg
  782. {
  783. template<
  784. typename LocalIterator,typename OutputIterator,
  785. typename BinaryPredicate,typename LocalBaseIterator
  786. >
  787. OutputIterator operator()(
  788. LocalIterator first,LocalIterator last,
  789. OutputIterator res, BinaryPredicate pred,
  790. bool& carry,const std::type_info* prev_info, /* note the &s */
  791. LocalBaseIterator& prev)const
  792. {
  793. if(carry){
  794. auto p=restitute_iterator<Ts...>(deref_to(pred));
  795. for(;first!=last;++first)if(!p(*prev_info,prev,first))break;
  796. }
  797. if(first==last)return res;
  798. res=std::unique_copy(first,last,res,pred);
  799. carry=true;
  800. prev_info=&typeid(
  801. typename std::iterator_traits<LocalIterator>::value_type);
  802. prev=LocalBaseIterator{last-1};
  803. return res;
  804. }
  805. };
  806. template<
  807. typename... Ts,typename Iterator,
  808. typename OutputIterator,typename BinaryPredicate,
  809. enable_if_poly_collection_iterator<Iterator> =nullptr
  810. >
  811. OutputIterator unique_copy(
  812. const Iterator& first,const Iterator& last,
  813. OutputIterator res,BinaryPredicate pred)
  814. {
  815. using traits=iterator_traits<Iterator>;
  816. using local_base_iterator=typename traits::local_base_iterator;
  817. bool carry=false;
  818. const std::type_info* prev_info{&typeid(void)};
  819. local_base_iterator prev;
  820. return generic_copy<unique_copy_alg<Ts...>,Ts...>(
  821. first,last,res,pred,carry,prev_info,prev);
  822. }
  823. template<
  824. typename... Ts,typename Iterator,typename OutputIterator,
  825. enable_if_poly_collection_iterator<Iterator> =nullptr
  826. >
  827. OutputIterator unique_copy(
  828. const Iterator& first,const Iterator& last,OutputIterator res)
  829. {
  830. return algorithm::unique_copy<Ts...>(first,last,res,transparent_equal_to{});
  831. }
  832. template<
  833. typename... Ts,typename Iterator,typename OutputIterator,
  834. enable_if_poly_collection_iterator<Iterator> =nullptr
  835. >
  836. OutputIterator rotate_copy(
  837. const Iterator& first,const Iterator& middle,const Iterator& last,
  838. OutputIterator res)
  839. {
  840. res=algorithm::copy<Ts...>(middle,last,res);
  841. return algorithm::copy<Ts...>(first,middle,res);
  842. }
  843. template<
  844. typename... Ts,typename Iterator,typename Predicate,
  845. enable_if_poly_collection_iterator<Iterator> =nullptr
  846. >
  847. bool is_partitioned(const Iterator& first,const Iterator& last,Predicate pred)
  848. {
  849. auto it=algorithm::find_if_not<Ts...>(first,last,pred);
  850. if(it==last)return true;
  851. return algorithm::none_of<Ts...>(++it,last,pred);
  852. }
  853. BOOST_POLY_COLLECTION_DEFINE_OVERLOAD_SET(
  854. std_partition_copy,std::partition_copy)
  855. template<
  856. typename... Ts,typename Iterator,
  857. typename OutputIterator1,typename OutputIterator2,typename Predicate,
  858. enable_if_poly_collection_iterator<Iterator> =nullptr
  859. >
  860. std::pair<OutputIterator1,OutputIterator2> partition_copy(
  861. const Iterator& first,const Iterator& last,
  862. OutputIterator1 rest,OutputIterator2 resf,Predicate pred)
  863. {
  864. for(auto i:detail::segment_split(first,last)){
  865. auto alg=restitute_range<Ts...>(std_partition_copy{},rest,resf,pred);
  866. std::tie(rest,resf)=alg(i);
  867. }
  868. return {rest,resf};
  869. }
  870. template<typename Predicate,typename... Ts>
  871. struct partition_point_pred
  872. {
  873. partition_point_pred(const Predicate& pred):pred(pred){}
  874. template<typename Iterator>
  875. bool operator()(const Iterator& it)const
  876. {
  877. using traits=iterator_traits<Iterator>;
  878. auto p=restitute_iterator<Ts...>(deref_to(pred));
  879. return p(
  880. traits::base_segment_info_iterator_from(it)->type_info(),
  881. traits::local_base_iterator_from(it));
  882. }
  883. Predicate pred;
  884. };
  885. template<
  886. typename... Ts,typename Iterator,typename Predicate,
  887. enable_if_poly_collection_iterator<Iterator> =nullptr
  888. >
  889. Iterator partition_point(
  890. const Iterator& first,const Iterator& last,Predicate pred)
  891. {
  892. auto_iterator<Iterator> afirst{first},alast{last};
  893. partition_point_pred<Predicate,Ts...> p{pred};
  894. return *std::partition_point(afirst,alast,p);
  895. }
  896. } /* namespace poly_collection::detail::algorithm */
  897. } /* namespace poly_collection::detail */
  898. /* non-modifying sequence operations */
  899. using detail::algorithm::all_of;
  900. using detail::algorithm::any_of;
  901. using detail::algorithm::none_of;
  902. using detail::algorithm::for_each;
  903. using detail::algorithm::find;
  904. using detail::algorithm::find_if;
  905. using detail::algorithm::find_if_not;
  906. using detail::algorithm::find_end;
  907. using detail::algorithm::find_first_of;
  908. using detail::algorithm::adjacent_find;
  909. using detail::algorithm::count;
  910. using detail::algorithm::count_if;
  911. using detail::algorithm::mismatch;
  912. using detail::algorithm::equal;
  913. using detail::algorithm::is_permutation;
  914. using detail::algorithm::search;
  915. using detail::algorithm::search_n;
  916. /* modifying sequence operations */
  917. using detail::algorithm::copy;
  918. using detail::algorithm::copy_n;
  919. using detail::algorithm::copy_if;
  920. /* copy_backwards requires BidirectionalIterator */
  921. using detail::algorithm::move;
  922. /* move_backwards requires BidirectionalIterator */
  923. /* swap_ranges requires Swappable */
  924. /* iter_swap requires Swappable */
  925. using detail::algorithm::transform;
  926. /* replace requires Assignable */
  927. /* replace_if requires Assignable */
  928. using detail::algorithm::replace_copy;
  929. using detail::algorithm::replace_copy_if;
  930. /* fill requires Assignable */
  931. /* fill_n requires Assignable */
  932. /* generate requires Assignable */
  933. /* generate_n requires Assignable */
  934. /* remove requires MoveAssignable */
  935. /* remove_if requires MoveAssignable */
  936. using detail::algorithm::remove_copy;
  937. using detail::algorithm::remove_copy_if;
  938. /* unique requires MoveAssignable */
  939. using detail::algorithm::unique_copy;
  940. /* reverse requires BidirectionalIterator */
  941. /* reverse_copy requires BidirectionalIterator */
  942. /* rotate requires MoveAssignable */
  943. using detail::algorithm::rotate_copy;
  944. /* shuffle requires RandomAccessIterator */
  945. using detail::algorithm::is_partitioned;
  946. /* partition requires Swappable */
  947. /* stable_partition requires Swappable */
  948. using detail::algorithm::partition_copy;
  949. using detail::algorithm::partition_point;
  950. /* sorting and related operations not provided */
  951. } /* namespace poly_collection */
  952. } /* namespace boost */
  953. #endif