1 /* Copyright 2016-2017 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)
6 * See http://www.boost.org/libs/poly_collection for library home page.
9 #ifndef BOOST_POLY_COLLECTION_TEST_TEST_ALGORITHM_IMPL_HPP
10 #define BOOST_POLY_COLLECTION_TEST_TEST_ALGORITHM_IMPL_HPP
17 #include <boost/config.hpp>
18 #include <boost/core/lightweight_test.hpp>
19 #include <boost/detail/workaround.hpp>
20 #include <boost/function_output_iterator.hpp>
21 #include <boost/poly_collection/algorithm.hpp>
25 #include <type_traits>
28 #include "test_utilities.hpp"
30 using namespace test_utilities;
32 #if BOOST_WORKAROUND(BOOST_MSVC,>=1910)
33 /* https://lists.boost.org/Archives/boost/2017/06/235687.php */
35 #define DEFINE_ALGORITHM(name,f) \
36 template<typename... Ts> \
39 template<typename... Args> \
40 auto operator()(Args&&... args)const \
42 return f<Ts...>(std::forward<Args>(args)...); \
45 #elif BOOST_WORKAROUND(BOOST_GCC_VERSION,<50200)
46 /* problem here is with return type containing <Ts...> */
48 #define DEFINE_ALGORITHM(name,f) \
49 template<typename... Ts> \
52 template<typename... Args> \
53 auto operator()(Args&&... args)const-> \
54 decltype(f(std::forward<Args>(args)...)) \
56 return f<Ts...>(std::forward<Args>(args)...); \
60 #define DEFINE_ALGORITHM(name,f) \
61 template<typename... Ts> \
64 template<typename... Args> \
65 auto operator()(Args&&... args)const-> \
66 decltype(f<Ts...>(std::forward<Args>(args)...)) \
68 return f<Ts...>(std::forward<Args>(args)...); \
73 DEFINE_ALGORITHM(std_all_of,std::all_of)
74 DEFINE_ALGORITHM(poly_all_of,boost::poly_collection::all_of)
75 DEFINE_ALGORITHM(std_any_of,std::any_of)
76 DEFINE_ALGORITHM(poly_any_of,boost::poly_collection::any_of)
77 DEFINE_ALGORITHM(std_none_of,std::none_of)
78 DEFINE_ALGORITHM(poly_none_of,boost::poly_collection::none_of)
79 DEFINE_ALGORITHM(std_for_each,std::for_each)
80 DEFINE_ALGORITHM(poly_for_each,boost::poly_collection::for_each)
81 DEFINE_ALGORITHM(std_find,std::find)
82 DEFINE_ALGORITHM(poly_find,boost::poly_collection::find)
83 DEFINE_ALGORITHM(std_find_if,std::find_if)
84 DEFINE_ALGORITHM(poly_find_if,boost::poly_collection::find_if)
85 DEFINE_ALGORITHM(std_find_if_not,std::find_if_not)
86 DEFINE_ALGORITHM(poly_find_if_not,boost::poly_collection::find_if_not)
87 DEFINE_ALGORITHM(std_find_end,std::find_end)
88 DEFINE_ALGORITHM(poly_find_end,boost::poly_collection::find_end)
89 DEFINE_ALGORITHM(std_find_first_of,std::find_first_of)
90 DEFINE_ALGORITHM(poly_find_first_of,boost::poly_collection::find_first_of)
91 DEFINE_ALGORITHM(std_adjacent_find,std::adjacent_find)
92 DEFINE_ALGORITHM(poly_adjacent_find,boost::poly_collection::adjacent_find)
93 DEFINE_ALGORITHM(std_count,std::count)
94 DEFINE_ALGORITHM(poly_count,boost::poly_collection::count)
95 DEFINE_ALGORITHM(std_count_if,std::count_if)
96 DEFINE_ALGORITHM(poly_count_if,boost::poly_collection::count_if)
97 DEFINE_ALGORITHM(std_cpp11_mismatch,std::mismatch) /* note std_cpp11 prefix */
98 DEFINE_ALGORITHM(poly_mismatch,boost::poly_collection::mismatch)
99 DEFINE_ALGORITHM(std_cpp11_equal,std::equal) /* note std_cpp11 prefix */
100 DEFINE_ALGORITHM(poly_equal,boost::poly_collection::equal)
101 DEFINE_ALGORITHM(std_cpp11_is_permutation,std::is_permutation) /* std_cpp11 */
102 DEFINE_ALGORITHM(poly_is_permutation,boost::poly_collection::is_permutation)
103 DEFINE_ALGORITHM(std_search,std::search)
104 DEFINE_ALGORITHM(poly_search,boost::poly_collection::search)
105 DEFINE_ALGORITHM(std_search_n,std::search_n)
106 DEFINE_ALGORITHM(poly_search_n,boost::poly_collection::search_n)
107 DEFINE_ALGORITHM(std_copy,std::copy)
108 DEFINE_ALGORITHM(poly_copy,boost::poly_collection::copy)
109 DEFINE_ALGORITHM(std_copy_n,std::copy_n)
110 DEFINE_ALGORITHM(poly_copy_n,boost::poly_collection::copy_n)
111 DEFINE_ALGORITHM(std_copy_if,std::copy_if)
112 DEFINE_ALGORITHM(poly_copy_if,boost::poly_collection::copy_if)
113 DEFINE_ALGORITHM(std_move,std::move)
114 DEFINE_ALGORITHM(poly_move,boost::poly_collection::move)
115 DEFINE_ALGORITHM(std_transform,std::transform)
116 DEFINE_ALGORITHM(poly_transform,boost::poly_collection::transform)
117 DEFINE_ALGORITHM(std_replace_copy,std::replace_copy)
118 DEFINE_ALGORITHM(poly_replace_copy,boost::poly_collection::replace_copy)
119 DEFINE_ALGORITHM(std_replace_copy_if,std::replace_copy_if)
120 DEFINE_ALGORITHM(poly_replace_copy_if,boost::poly_collection::replace_copy_if)
121 DEFINE_ALGORITHM(std_remove_copy,std::remove_copy)
122 DEFINE_ALGORITHM(poly_remove_copy,boost::poly_collection::remove_copy)
123 DEFINE_ALGORITHM(std_remove_copy_if,std::remove_copy_if)
124 DEFINE_ALGORITHM(poly_remove_copy_if,boost::poly_collection::remove_copy_if)
125 DEFINE_ALGORITHM(std_unique_copy,std::unique_copy)
126 DEFINE_ALGORITHM(poly_unique_copy,boost::poly_collection::unique_copy)
127 DEFINE_ALGORITHM(std_rotate_copy,std::rotate_copy)
128 DEFINE_ALGORITHM(poly_rotate_copy,boost::poly_collection::rotate_copy)
129 DEFINE_ALGORITHM(std_is_partitioned,std::is_partitioned)
130 DEFINE_ALGORITHM(poly_is_partitioned,boost::poly_collection::is_partitioned)
131 DEFINE_ALGORITHM(std_partition_copy,std::partition_copy)
132 DEFINE_ALGORITHM(poly_partition_copy,boost::poly_collection::partition_copy)
133 DEFINE_ALGORITHM(std_partition_point,std::partition_point)
134 DEFINE_ALGORITHM(poly_partition_point,boost::poly_collection::partition_point)
136 template<typename... Ts>
137 struct std_mismatch:std_cpp11_mismatch<Ts...>
139 using std_cpp11_mismatch<Ts...>::operator();
143 template<typename InputIterator1,typename InputIterator2>
144 std::pair<InputIterator1,InputIterator2> operator()(
145 InputIterator1 first1,InputIterator1 last1,
146 InputIterator2 first2,InputIterator2 last2)const
148 while(first1!=last1&&first2!=last2&&*first1==*first2){
152 return {first1,first2};
155 template<typename InputIterator1,typename InputIterator2,typename Predicate>
156 std::pair<InputIterator1,InputIterator2> operator()(
157 InputIterator1 first1,InputIterator1 last1,
158 InputIterator2 first2,InputIterator2 last2,Predicate pred)const
160 while(first1!=last1&&first2!=last2&&pred(*first1,*first2)){
164 return {first1,first2};
168 template<typename... Ts>
169 struct std_equal:std_cpp11_equal<Ts...>
171 using std_cpp11_equal<Ts...>::operator();
175 template<typename InputIterator1,typename InputIterator2>
177 InputIterator1 first1,InputIterator1 last1,
178 InputIterator2 first2,InputIterator2 last2)const
180 for(;first1!=last1&&first2!=last2;++first1,++first2){
181 if(!(*first1==*first2))return false;
183 return first1==last1&&first2==last2;
186 template<typename InputIterator1,typename InputIterator2,typename Predicate>
188 InputIterator1 first1,InputIterator1 last1,
189 InputIterator2 first2,InputIterator2 last2,Predicate pred)const
191 for(;first1!=last1&&first2!=last2;++first1,++first2){
192 if(!pred(*first1,*first2))return false;
194 return first1==last1&&first2==last2;
198 template<typename... Ts>
199 struct std_is_permutation:std_cpp11_is_permutation<Ts...>
201 using std_cpp11_is_permutation<Ts...>::operator();
203 /* The implementation of predicate-based std::is_permutation in GCC<=4.8
204 * version of libstdc++-v3 incorrectly triggers the instantiation of
205 * ForwardIterator2::value_type, which fails when this is an abstract class.
206 * The implementation below ripped from libc++ source code.
210 typename ForwardIterator1,typename ForwardIterator2,typename Predicate
213 ForwardIterator1 first1,ForwardIterator1 last1,
214 ForwardIterator2 first2,Predicate pred)const
216 for(;first1!=last1;++first1,(void)++first2){
217 if(!pred(*first1,*first2))goto not_done;
222 using difference_type=
223 typename std::iterator_traits<ForwardIterator1>::difference_type;
225 difference_type l1=std::distance(first1,last1);
226 if(l1==difference_type(1))return false;
228 ForwardIterator2 last2=std::next(first2,l1);
229 for(ForwardIterator1 i=first1;i!= last1;++i){
230 for(ForwardIterator1 j=first1;j!=i;++j)if(pred(*j,*i))goto next_iter;
232 difference_type c2=0;
233 for(ForwardIterator2 j=first2;j!=last2;++j)if(pred(*i,*j))++c2;
234 if(c2==0)return false;
235 difference_type c1=1;
236 for(ForwardIterator1 j=std::next(i);j!=last1;++j)if(pred(*i,*j))++c1;
237 if(c1!=c2)return false;
246 template<typename ForwardIterator1,typename ForwardIterator2>
248 ForwardIterator1 first1,ForwardIterator1 last1,
249 ForwardIterator2 first2,ForwardIterator2 last2)const
251 if(std::distance(first1,last1)!=std::distance(first2,last2))return false;
252 return (*this)(first1,last1,first2);
256 typename ForwardIterator1,typename ForwardIterator2,typename Predicate
259 ForwardIterator1 first1,ForwardIterator1 last1,
260 ForwardIterator2 first2,ForwardIterator2 last2,Predicate pred)const
262 if(std::distance(first1,last1)!=std::distance(first2,last2))return false;
263 return (*this)(first1,last1,first2,pred);
268 typename ControlAlgorithm,typename Algorithm,
269 typename PolyCollection,typename... Args
271 void test_algorithm(PolyCollection& p,Args&&... args)
274 ControlAlgorithm control;
275 for(auto first=p.begin(),end=p.end();;++first){
276 for(auto last=first;last!=end;++last){
278 alg(first,last,std::forward<Args>(args)...)==
279 control(first,last,std::forward<Args>(args)...));
286 typename ControlAlgorithm,typename... Algorithms,
287 typename PolyCollection,typename... Args
289 void test_algorithms(PolyCollection& p,Args&&... args)
291 do_((test_algorithm<ControlAlgorithm,Algorithms>(
292 p,std::forward<Args>(args)...),0)...);
293 do_((test_algorithm<ControlAlgorithm,Algorithms>(
294 const_cast<const PolyCollection&>(p),std::forward<Args>(args)...),0)...);
298 typename ControlAlgorithm,typename... Algorithms,
299 typename PolyCollection,typename... Args
301 void test_algorithms_with_equality_impl(
302 std::true_type,PolyCollection& p,Args&&... args)
304 test_algorithms<ControlAlgorithm,Algorithms...>(
305 p,std::forward<Args>(args)...);
309 typename ControlAlgorithm,typename... Algorithm,
310 typename PolyCollection,typename... Args
312 void test_algorithms_with_equality_impl(
313 std::false_type,PolyCollection&,Args&&...)
318 typename ControlAlgorithm,typename... Algorithms,
319 typename PolyCollection,typename... Args
321 void test_algorithms_with_equality(PolyCollection& p,Args&&... args)
323 test_algorithms_with_equality_impl<ControlAlgorithm,Algorithms...>(
324 is_equality_comparable<typename PolyCollection::value_type>{},
325 p,std::forward<Args>(args)...);
329 typename ControlAlgorithm,typename Algorithm,
330 typename ToInt,typename PolyCollection,typename... Args
332 void test_copy_algorithm(ToInt to_int,PolyCollection& p,Args&&... args)
335 ControlAlgorithm control;
336 for(auto first=p.begin(),end=p.end();;++first){
337 for(auto last=first;last!=end;++last){
338 using vector=std::vector<int>;
341 auto insert1=compose(to_int,[&](int x){v1.push_back(x);});
342 auto insert2=compose(to_int,[&](int x){v2.push_back(x);});
343 auto out1=boost::make_function_output_iterator(std::ref(insert1));
344 auto out2=boost::make_function_output_iterator(std::ref(insert2));
346 out1=alg(first,last,out1,std::forward<Args>(args)...);
347 out2=control(first,last,out2,std::forward<Args>(args)...);
355 typename ControlAlgorithm,typename... Algorithms,
356 typename ToInt,typename PolyCollection,typename... Args
358 void test_copy_algorithms(ToInt to_int,PolyCollection& p,Args&&... args)
360 do_((test_copy_algorithm<ControlAlgorithm,Algorithms>(
361 to_int,p,std::forward<Args>(args)...),0)...);
362 do_((test_copy_algorithm<ControlAlgorithm,Algorithms>(
363 to_int,const_cast<const PolyCollection&>(p),
364 std::forward<Args>(args)...),0)...);
368 typename ControlAlgorithm,typename... Algorithms,
369 typename ToInt,typename PolyCollection,typename... Args
371 void test_copy_algorithms_with_equality_impl(
372 std::true_type,ToInt to_int,PolyCollection& p,Args&&... args)
374 test_copy_algorithms<ControlAlgorithm,Algorithms...>(
375 to_int,p,std::forward<Args>(args)...);
379 typename ControlAlgorithm,typename... Algorithm,
380 typename ToInt,typename PolyCollection,typename... Args
382 void test_copy_algorithms_with_equality_impl(
383 std::false_type,ToInt,PolyCollection&,Args&&...)
388 typename ControlAlgorithm,typename... Algorithms,
389 typename ToInt,typename PolyCollection,typename... Args
391 void test_copy_algorithms_with_equality(
392 ToInt to_int,PolyCollection& p,Args&&... args)
394 test_copy_algorithms_with_equality_impl<ControlAlgorithm,Algorithms...>(
395 is_equality_comparable<typename PolyCollection::value_type>{},
396 to_int,p,std::forward<Args>(args)...);
400 typename ControlAlgorithm,typename Algorithm,
401 typename ToInt,typename PolyCollection,typename... Args
403 void test_copy_n_algorithm(ToInt to_int,PolyCollection& p,Args&&... args)
406 ControlAlgorithm control;
407 for(auto first=p.begin(),end=p.end();;++first){
408 for(std::ptrdiff_t n=0,m=std::distance(first,end);n<=m;++n){
409 using vector=std::vector<int>;
412 auto insert1=compose(to_int,[&](int x){v1.push_back(x);});
413 auto insert2=compose(to_int,[&](int x){v2.push_back(x);});
414 auto out1=boost::make_function_output_iterator(std::ref(insert1));
415 auto out2=boost::make_function_output_iterator(std::ref(insert2));
417 alg(first,n,out1,std::forward<Args>(args)...);
418 control(first,n,out2,std::forward<Args>(args)...);
426 typename ControlAlgorithm,typename... Algorithms,
427 typename ToInt,typename PolyCollection,typename... Args
429 void test_copy_n_algorithms(ToInt to_int,PolyCollection& p,Args&&... args)
431 do_((test_copy_n_algorithm<ControlAlgorithm,Algorithms>(
432 to_int,p,std::forward<Args>(args)...),0)...);
433 do_((test_copy_n_algorithm<ControlAlgorithm,Algorithms>(
434 to_int,const_cast<const PolyCollection&>(p),
435 std::forward<Args>(args)...),0)...);
439 typename ControlAlgorithm,typename Algorithm,
440 typename ToInt,typename PolyCollection
442 void test_transform2_algorithm(ToInt to_int,PolyCollection& p)
445 ControlAlgorithm control;
446 for(auto first=p.begin(),end=p.end();;++first){
447 for(auto last=first;last!=end;++last){
448 using vector=std::vector<int>;
450 auto op=compose_all(to_int,[](int x,int y){return x+y;});
452 auto insert1=[&](int x){v1.push_back(x);};
453 auto insert2=[&](int x){v2.push_back(x);};
454 auto out1=boost::make_function_output_iterator(std::ref(insert1));
455 auto out2=boost::make_function_output_iterator(std::ref(insert2));
457 out1=alg(first,last,p.begin(),out1,op);
458 out2=control(first,last,p.begin(),out2,op);
466 typename ControlAlgorithm,typename... Algorithms,
467 typename ToInt,typename PolyCollection
469 void test_transform2_algorithms(ToInt to_int,PolyCollection& p)
471 do_((test_transform2_algorithm<ControlAlgorithm,Algorithms>(
473 do_((test_transform2_algorithm<ControlAlgorithm,Algorithms>(
474 to_int,const_cast<const PolyCollection&>(p)),0)...);
478 typename ControlAlgorithm,typename Algorithm,
479 typename ToInt,typename PolyCollection
481 void test_rotate_copy_algorithm(ToInt to_int,PolyCollection& p)
484 ControlAlgorithm control;
485 for(auto first=p.begin(),end=p.end();;++first){
486 for(auto last=first;last!=end;++last){
487 for(auto middle=first;;++middle){
488 using vector=std::vector<int>;
491 auto insert1=compose(to_int,[&](int x){v1.push_back(x);});
492 auto insert2=compose(to_int,[&](int x){v2.push_back(x);});
493 auto out1=boost::make_function_output_iterator(std::ref(insert1));
494 auto out2=boost::make_function_output_iterator(std::ref(insert2));
496 out1=alg(first,middle,last,out1);
497 out2=control(first,middle,last,out2);
500 if(middle==last)break;
508 typename ControlAlgorithm,typename... Algorithms,
509 typename ToInt,typename PolyCollection
511 void test_rotate_copy_algorithms(ToInt to_int,PolyCollection& p)
513 do_((test_rotate_copy_algorithm<ControlAlgorithm,Algorithms>(
515 do_((test_rotate_copy_algorithm<ControlAlgorithm,Algorithms>(
516 to_int,const_cast<const PolyCollection&>(p)),0)...);
520 typename ControlAlgorithm,typename Algorithm,
521 typename ToInt,typename PolyCollection,typename Predicate
523 void test_partition_copy_algorithm(
524 ToInt to_int,PolyCollection& p,Predicate pred)
527 ControlAlgorithm control;
528 for(auto first=p.begin(),end=p.end();;++first){
529 for(auto last=first;last!=end;++last){
530 using vector=std::vector<int>;
532 vector v11,v12,v21,v22;
533 auto insert11=compose(to_int,[&](int x){v11.push_back(x);});
534 auto insert12=compose(to_int,[&](int x){v12.push_back(x);});
535 auto insert21=compose(to_int,[&](int x){v21.push_back(x);});
536 auto insert22=compose(to_int,[&](int x){v22.push_back(x);});
537 auto out11=boost::make_function_output_iterator(std::ref(insert11));
538 auto out12=boost::make_function_output_iterator(std::ref(insert12));
539 auto out21=boost::make_function_output_iterator(std::ref(insert21));
540 auto out22=boost::make_function_output_iterator(std::ref(insert22));
542 std::tie(out11,out12)=alg(first,last,out11,out12,pred);
543 std::tie(out21,out22)=control(first,last,out21,out22,pred);
544 BOOST_TEST(v11==v21);
545 BOOST_TEST(v12==v22);
552 typename ControlAlgorithm,typename... Algorithms,
553 typename ToInt,typename PolyCollection,typename Predicate
555 void test_partition_copy_algorithms(
556 ToInt to_int,PolyCollection& p,Predicate pred)
558 do_((test_partition_copy_algorithm<ControlAlgorithm,Algorithms>(
559 to_int,p,pred),0)...);
560 do_((test_partition_copy_algorithm<ControlAlgorithm,Algorithms>(
561 to_int,const_cast<const PolyCollection&>(p),pred),0)...);
564 template<typename ToInt>
565 struct poly_accumulator_class
567 poly_accumulator_class(const ToInt& to_int):res{0},to_int(to_int){}
568 bool operator==(const poly_accumulator_class& x)const{return res==x.res;}
570 template<typename T> void operator()(const T& x){res+=to_int(x);}
576 template<typename ToInt>
577 poly_accumulator_class<ToInt> poly_accumulator(const ToInt& to_int)
583 typename PolyCollection,typename ValueFactory,typename ToInt,
586 void test_algorithm()
592 fill<constraints<>,Types...>(p,v,2);
595 auto always_true=compose(to_int,[](int){return true;});
596 auto always_false=compose(to_int,[](int){return false;});
597 auto pred=compose(to_int,[](int x){return x%2==0;});
599 test_algorithms<std_all_of<>,poly_all_of<>,poly_all_of<Types...>>(
601 test_algorithms<std_all_of<>,poly_all_of<>,poly_all_of<Types...>>(
603 test_algorithms<std_all_of<>,poly_all_of<>,poly_all_of<Types...>>(
606 test_algorithms<std_any_of<>,poly_any_of<>,poly_any_of<Types...>>(
608 test_algorithms<std_any_of<>,poly_any_of<>,poly_any_of<Types...>>(
610 test_algorithms<std_any_of<>,poly_any_of<>,poly_any_of<Types...>>(
613 test_algorithms<std_none_of<>,poly_none_of<>,poly_none_of<Types...>>(
615 test_algorithms<std_none_of<>,poly_none_of<>,poly_none_of<Types...>>(
617 test_algorithms<std_none_of<>,poly_none_of<>,poly_none_of<Types...>>(
621 test_algorithms<std_for_each<>,poly_for_each<>,poly_for_each<Types...>>(
622 p,poly_accumulator(to_int));
625 for(const auto& x:p){
626 test_algorithms_with_equality<
627 std_find<>,poly_find<>,only_eq_comparable<poly_find,Types...>
633 std::advance(it,p.size()/2);
635 auto pred=compose(to_int,[=](int x){return x==n;});
637 test_algorithms<std_find_if<>,poly_find_if<>,poly_find_if<Types...>>(
641 std_find_if_not<>,poly_find_if_not<>,poly_find_if_not<Types...>
645 auto first=p.begin(),end=first;
646 std::advance(end,+p.size()/2);
647 for(;first!=end;++first){
648 test_algorithms_with_equality<
649 std_find_end<>,poly_find_end<>,
650 only_eq_comparable<poly_find_end,Types...>
653 test_algorithms_with_equality<
654 std_search<>,poly_search<>,
655 only_eq_comparable<poly_search,Types...>
661 for(const auto& x:p)v.push_back(to_int(x));
662 v.erase(v.begin()+v.size()/2,v.end());
664 for(auto first=v.begin(),end=v.begin()+v.size()/2;first!=end;++first){
665 for(int i=1;i<4;++i){
666 auto pred=compose(to_int,[&](int x,int y){return x%i==y%i;});
669 std_find_end<>,poly_find_end<>,poly_find_end<Types...>
672 test_algorithms<std_search<>,poly_search<>,poly_search<Types...>>(
678 using value_type=typename PolyCollection::value_type;
679 using vector=std::vector<std::reference_wrapper<const value_type>>;
682 for(const auto& x:p){
684 case 0:v.push_back(x);break;
685 case 1:v.push_back(*p.begin());break;
690 for(auto first=v.begin(),end=v.end();first!=end;++first){
691 for(auto last=first;last!=end;++last){
692 test_algorithms_with_equality<
693 std_find_first_of<>,poly_find_first_of<>,
694 only_eq_comparable<poly_find_first_of,Types...>
701 for(const auto& x:p){
703 case 0:v.push_back(to_int(x));break;
704 case 1:v.push_back(-1);break;
709 for(auto first=v.begin(),end=v.end();first!=end;++first){
710 for(auto last=first;last!=end;++last){
712 std_find_first_of<>,poly_find_first_of<>,poly_find_first_of<Types...>
713 >(p,first,last,compose(to_int,std::equal_to<int>{}));
718 test_algorithms_with_equality<
719 std_adjacent_find<>,poly_adjacent_find<>,
720 only_eq_comparable<poly_adjacent_find,Types...>
725 for(const auto& x:p)v.push_back(to_int(x));
728 for(auto first=v.begin(),end=v.end()-1;first!=end;++first){
729 int n1=*first,n2=*(first+1);
731 std_adjacent_find<>,poly_adjacent_find<>,poly_adjacent_find<Types...>
732 >(p,compose_all(to_int,[=](int x,int y){return x==n1&&y==n2;}));
736 for(const auto& x:p){
737 test_algorithms_with_equality<
738 std_count<>,poly_count<>,only_eq_comparable<poly_count,Types...>
743 for(int i=1;i<4;++i){
744 test_algorithms<std_count_if<>,poly_count_if<>,poly_count_if<Types...>>(
745 p,compose(to_int,[&](int x){return x%i==0;}));
749 using value_type=typename PolyCollection::value_type;
750 using vector=std::vector<std::reference_wrapper<const value_type>>;
753 for(const auto& x:p)v.push_back(x);
756 v.insert(v.end(),w.begin(),w.end());
758 for(auto first=v.begin(),end=v.begin()+v.size()/2;first!=end;++first){
759 test_algorithms_with_equality<
760 std_mismatch<>,poly_mismatch<>,
761 only_eq_comparable<poly_mismatch,Types...>
764 test_algorithms_with_equality<
765 std_mismatch<>,poly_mismatch<>,
766 only_eq_comparable<poly_mismatch,Types...>
769 test_algorithms_with_equality<
770 std_equal<>,poly_equal<>,only_eq_comparable<poly_equal,Types...>
773 test_algorithms_with_equality<
774 std_equal<>,poly_equal<>,only_eq_comparable<poly_equal,Types...>
778 test_algorithms_with_equality<
779 std_mismatch<>,poly_mismatch<>,only_eq_comparable<poly_mismatch,Types...>
780 >(p,v.end(),v.end());
782 test_algorithms_with_equality<
783 std_equal<>,poly_equal<>,only_eq_comparable<poly_equal,Types...>
784 >(p,v.end(),v.end());
788 for(const auto& x:p)v.push_back(to_int(x));
791 v.insert(v.end(),w.begin(),w.end());
792 auto pred=compose(to_int,std::equal_to<int>{});
794 for(auto first=v.begin(),end=v.begin()+v.size()/2;first!=end;++first){
795 test_algorithms<std_mismatch<>,poly_mismatch<>,poly_mismatch<Types...>>(
798 test_algorithms<std_mismatch<>,poly_mismatch<>,poly_mismatch<Types...>>(
801 test_algorithms<std_equal<>,poly_equal<>,poly_equal<Types...>>(
804 test_algorithms<std_equal<>,poly_equal<>,poly_equal<Types...>>(
808 test_algorithms<std_mismatch<>,poly_mismatch<>,poly_mismatch<Types...>>(
809 p,v.end(),v.end(),pred);
811 test_algorithms<std_equal<>,poly_equal<>,poly_equal<Types...>>(
812 p,v.end(),v.end(),pred);
815 using value_type=typename PolyCollection::value_type;
816 using vector=std::vector<std::reference_wrapper<const value_type>>;
819 for(const auto& x:p)v.push_back(x);
821 std::mt19937 gen{73642};
822 std::shuffle(w.begin(),w.end(),gen);
823 v.insert(v.end(),w.begin(),w.end());
824 auto pred=compose_all(to_int,std::equal_to<int>{});
826 for(auto first=unwrap_iterator(v.begin()),
827 end=unwrap_iterator(v.begin()+v.size()/2);first!=end;++first){
828 test_algorithms_with_equality<
829 std_is_permutation<>,
830 poly_is_permutation<>,
831 only_eq_comparable<poly_is_permutation,Types...>
835 std_is_permutation<>,
836 poly_is_permutation<>,poly_is_permutation<Types...>
839 test_algorithms_with_equality<
840 std_is_permutation<>,
841 poly_is_permutation<>,
842 only_eq_comparable<poly_is_permutation,Types...>
846 std_is_permutation<>,
847 poly_is_permutation<>,poly_is_permutation<Types...>
851 test_algorithms_with_equality<
852 std_is_permutation<>,
853 poly_is_permutation<>,
854 only_eq_comparable<poly_is_permutation,Types...>
855 >(p,unwrap_iterator(v.end()),unwrap_iterator(v.end()));
858 std_is_permutation<>,
859 poly_is_permutation<>,poly_is_permutation<Types...>
860 >(p,unwrap_iterator(v.end()),unwrap_iterator(v.end()),pred);
863 /* search tested above */
866 for(const auto&x: p){
867 for(int n=0;n<3;++n){
868 test_algorithms_with_equality<
869 std_search_n<>,poly_search_n<>,
870 only_eq_comparable<poly_search_n,Types...>
876 for(int n=0;n<6;++n){
877 test_algorithms<std_search_n<>,poly_search_n<>,poly_search_n<Types...>>(
878 p,n,0,compose(to_int,[&](int x,int y){return x%(6-n)==y%(6-n);}));
882 test_copy_algorithms<std_copy<>,poly_copy<>,poly_copy<Types...>>(
886 test_copy_n_algorithms<std_copy_n<>,poly_copy_n<>,poly_copy_n<Types...>>(
890 auto always_true=compose(to_int,[](int){return true;});
891 auto always_false=compose(to_int,[](int){return false;});
892 auto pred=compose(to_int,[](int x){return x%2==0;});
894 test_copy_algorithms<std_copy_if<>,poly_copy_if<>,poly_copy_if<Types...>>(
895 to_int,p,always_true);
896 test_copy_algorithms<std_copy_if<>,poly_copy_if<>,poly_copy_if<Types...>>(
897 to_int,p,always_false);
898 test_copy_algorithms<std_copy_if<>,poly_copy_if<>,poly_copy_if<Types...>>(
902 test_copy_algorithms<std_move<>,poly_move<>,poly_move<Types...>>(
903 to_int,p); /* we're not checking std::move is properly used internally */
906 auto f=compose(to_int,[](int x){return -x;});
907 auto int_id=[](int x){return x;};
909 test_copy_algorithms<
910 std_transform<>,poly_transform<>,poly_transform<Types...>
914 test_transform2_algorithms<
915 std_transform<>,poly_transform<>,poly_transform<Types...>
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...>
926 test_copy_algorithms_with_equality<
927 std_remove_copy<>,poly_remove_copy<>,
928 only_eq_comparable<poly_remove_copy,Types...>
933 auto always_true=compose(to_int,[](int){return true;});
934 auto always_false=compose(to_int,[](int){return false;});
935 auto pred=compose(to_int,[](int x){return x%2==0;});
938 test_copy_algorithms<
939 std_replace_copy_if<>,
940 poly_replace_copy_if<>,poly_replace_copy_if<Types...>
941 >(to_int,p,always_true,x);
942 test_copy_algorithms<
943 std_replace_copy_if<>,
944 poly_replace_copy_if<>,poly_replace_copy_if<Types...>
945 >(to_int,p,always_false,x);
946 test_copy_algorithms<
947 std_replace_copy_if<>,
948 poly_replace_copy_if<>,poly_replace_copy_if<Types...>
951 test_copy_algorithms<
952 std_remove_copy_if<>,
953 poly_remove_copy_if<>,poly_remove_copy_if<Types...>
954 >(to_int,p,always_true);
955 test_copy_algorithms<
956 std_remove_copy_if<>,
957 poly_remove_copy_if<>,poly_remove_copy_if<Types...>
958 >(to_int,p,always_false);
959 test_copy_algorithms<
960 std_remove_copy_if<>,
961 poly_remove_copy_if<>,poly_remove_copy_if<Types...>
965 test_copy_algorithms_with_equality<
966 std_unique_copy<>,poly_unique_copy<>,
967 only_eq_comparable<poly_unique_copy,Types...>
971 for(int n=0;n<6;++n){
972 test_copy_algorithms<
973 std_unique_copy<>,poly_unique_copy<>,poly_unique_copy<Types...>
975 compose_all(to_int,[&](int x,int y){return x%(6-n)==y%(6-n);}));
979 test_rotate_copy_algorithms<
980 std_rotate_copy<>,poly_rotate_copy<>,poly_rotate_copy<Types...>
984 for(int n=0;n<6;++n){
985 auto pred=compose(to_int,[&](int x){return x%(6-n)<=(6-n)/2;});
988 std_is_partitioned<>,
989 poly_is_partitioned<>,poly_is_partitioned<Types...>
992 test_partition_copy_algorithms<
993 std_partition_copy<>,
994 poly_partition_copy<>,poly_partition_copy<Types...>
998 std_partition_point<>,
999 poly_partition_point<>,poly_partition_point<Types...>