1 // Copyright 2005 Daniel Wallin.
2 // Copyright 2005 Joel de Guzman.
3 // Copyright 2005 Dan Marsden.
4 // Copyright 2008 Hartmut Kaiser.
5 // Copyright 2015 John Fletcher.
6 //
7 // Use, modification and distribution is subject to the Boost Software
8 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
9 // http://www.boost.org/LICENSE_1_0.txt)
10 //
11 // Modeled after range_ex, Copyright 2004 Eric Niebler
12 
13 #ifndef BOOST_PHOENIX_ALGORITHM_QUERYING_HPP
14 #define BOOST_PHOENIX_ALGORITHM_QUERYING_HPP
15 
16 #include <algorithm>
17 
18 #include <boost/phoenix/core/limits.hpp>
19 #include <boost/phoenix/stl/algorithm/detail/has_find.hpp>
20 #include <boost/phoenix/stl/algorithm/detail/has_lower_bound.hpp>
21 #include <boost/phoenix/stl/algorithm/detail/has_upper_bound.hpp>
22 #include <boost/phoenix/stl/algorithm/detail/has_equal_range.hpp>
23 
24 #include <boost/phoenix/stl/algorithm/detail/begin.hpp>
25 #include <boost/phoenix/stl/algorithm/detail/end.hpp>
26 #include <boost/phoenix/stl/algorithm/detail/decay_array.hpp>
27 
28 #include <boost/phoenix/function/adapt_callable.hpp>
29 
30 //#include <boost/range/result_iterator.hpp> is deprecated
31 #include <boost/range/iterator.hpp>
32 #include <boost/range/difference_type.hpp>
33 
34 namespace boost { namespace phoenix {
35     namespace impl
36     {
37         struct find
38         {
39             template <typename Sig>
40             struct result;
41 
42             template <typename This, class R, class T>
43             struct result<This(R&, T&)>
44                 : range_iterator<R>
45             {};
46 
47             template<class R, class T>
48             typename range_iterator<R>::type
executeboost::phoenix::impl::find49             execute(R& r, T const& x, mpl::true_) const
50             {
51                 return r.find(x);
52             }
53 
54             template<class R, class T>
55             typename range_iterator<R>::type
executeboost::phoenix::impl::find56             execute(R& r, T const& x, mpl::false_) const
57             {
58                 return std::find(detail::begin_(r), detail::end_(r), x);
59             }
60 
61             template<class R, class T>
62             typename range_iterator<R>::type
operator ()boost::phoenix::impl::find63             operator()(R& r, T const& x) const
64             {
65                 return execute(r, x, has_find<R>());
66             }
67         };
68 
69         struct find_if
70         {
71             template <typename Sig>
72             struct result;
73 
74             template <typename This, class R, class P>
75             struct result<This(R&, P)>
76                 : range_iterator<R>
77             {};
78 
79             template<class R, class P>
80             typename range_iterator<R>::type
operator ()boost::phoenix::impl::find_if81             operator()(R& r, P p) const
82             {
83                 return std::find_if(detail::begin_(r), detail::end_(r), p);
84             }
85         };
86 
87         struct find_end
88         {
89             template <typename Sig>
90             struct result;
91 
92             template<typename This, class R, class R2>
93             struct result<This(R&, R2&)>
94                 : range_iterator<R>
95             {};
96 
97             template<typename This, class R, class R2, class P>
98             struct result<This(R&, R2&, P)>
99                 : range_iterator<R>
100             {};
101 
102             template<class R, class R2>
103             typename range_iterator<R>::type
operator ()boost::phoenix::impl::find_end104             operator()(R& r, R2& r2) const
105             {
106                 return std::find_end(
107                     detail::begin_(r)
108                     , detail::end_(r)
109                     , detail::begin_(r2)
110                     , detail::end_(r2)
111                     );
112             }
113 
114             template<class R, class R2, class P>
115             typename range_iterator<R>::type
operator ()boost::phoenix::impl::find_end116             operator()(R& r, R2& r2, P p) const
117             {
118                 return std::find_end(
119                     detail::begin_(r)
120                     , detail::end_(r)
121                     , detail::begin_(r2)
122                     , detail::end_(r2)
123                     , p
124                     );
125             }
126         };
127 
128         struct find_first_of
129         {
130             template <typename Sig>
131             struct result;
132 
133             template<typename This, class R, class R2>
134             struct result<This(R&, R2&)>
135                 : range_iterator<R>
136             {};
137 
138             template<typename This, class R, class R2, class P>
139             struct result<This(R&, R2&, P)>
140                 : range_iterator<R>
141             {};
142 
143             template<class R, class R2>
144             typename range_iterator<R>::type
operator ()boost::phoenix::impl::find_first_of145             operator()(R& r, R2& r2) const
146             {
147                 return std::find_first_of(
148                     detail::begin_(r)
149                     , detail::end_(r)
150                     , detail::begin_(r2)
151                     , detail::end_(r2)
152                     );
153             }
154 
155             template<class R, class R2, class P>
156             typename range_iterator<R>::type
operator ()boost::phoenix::impl::find_first_of157             operator()(R& r, R2& r2, P p) const
158             {
159                 return std::find_first_of(
160                     detail::begin_(r)
161                     , detail::end_(r)
162                     , detail::begin_(r2)
163                     , detail::end_(r2)
164                     , p
165                     );
166             }
167         };
168 
169         struct adjacent_find
170         {
171             template <typename Sig>
172             struct result;
173 
174             template <typename This, class R>
175             struct result<This(R&)>
176                 : range_iterator<R>
177             {};
178 
179             template <typename This, class R, class P>
180             struct result<This(R&, P)>
181                 : range_iterator<R>
182             {};
183 
184             template<class R>
185             typename range_iterator<R>::type
operator ()boost::phoenix::impl::adjacent_find186             operator()(R& r) const
187             {
188                 return std::adjacent_find(detail::begin_(r), detail::end_(r));
189             }
190 
191             template<class R, class P>
192             typename range_iterator<R>::type
operator ()boost::phoenix::impl::adjacent_find193             operator()(R& r, P p) const
194             {
195                 return std::adjacent_find(detail::begin_(r), detail::end_(r), p);
196             }
197         };
198 
199         struct count
200         {
201             template <typename Sig>
202             struct result;
203 
204             template <typename This, class R, class T>
205             struct result<This(R&, T&)>
206                 : range_difference<R>
207             {};
208 
209             template<class R, class T>
210             typename range_difference<R>::type
operator ()boost::phoenix::impl::count211             operator()(R& r, T const& x) const
212             {
213                 return std::count(detail::begin_(r), detail::end_(r), x);
214             }
215         };
216 
217         struct count_if
218         {
219             template <typename Sig>
220             struct result;
221 
222             template <typename This, class R, class P>
223             struct result<This(R&, P)>
224                 : range_difference<R>
225             {};
226 
227             template<class R, class P>
228             typename range_difference<R>::type
operator ()boost::phoenix::impl::count_if229             operator()(R& r, P p) const
230             {
231                 return std::count_if(detail::begin_(r), detail::end_(r), p);
232             }
233         };
234 
235         struct distance
236         {
237             template <typename Sig>
238             struct result;
239 
240             template <typename This, class R>
241             struct result<This(R&)>
242                 : range_difference<R>
243             {};
244 
245             template<class R>
246             typename range_difference<R>::type
operator ()boost::phoenix::impl::distance247             operator()(R& r) const
248             {
249                 return std::distance(detail::begin_(r), detail::end_(r));
250             }
251         };
252 
253         struct equal
254         {
255             typedef bool result_type;
256 
257             template<class R, class I>
operator ()boost::phoenix::impl::equal258             bool operator()(R& r, I i) const
259             {
260                 return std::equal(detail::begin_(r), detail::end_(r), i);
261             }
262 
263             template<class R, class I, class P>
operator ()boost::phoenix::impl::equal264             bool operator()(R& r, I i, P p) const
265             {
266                 return std::equal(detail::begin_(r), detail::end_(r), i, p);
267             }
268         };
269 
270         struct search
271         {
272             template <typename Sig>
273             struct result;
274 
275             template <typename This, class R, typename R2>
276             struct result<This(R&, R2&)>
277                 : range_iterator<R>
278             {};
279 
280             template <typename This, class R, typename R2, class P>
281             struct result<This(R&, R2&, P)>
282                 : range_iterator<R>
283             {};
284 
285             template<class R, class R2>
286             typename range_iterator<R>::type
operator ()boost::phoenix::impl::search287             operator()(R& r, R2& r2) const
288             {
289                 return std::search(
290                     detail::begin_(r)
291                     , detail::end_(r)
292                     , detail::begin_(r2)
293                     , detail::end_(r2)
294                     );
295             }
296 
297             template<class R, class R2, class P>
298             typename range_iterator<R>::type
operator ()boost::phoenix::impl::search299             operator()(R& r, R2& r2, P p) const
300             {
301                 return std::search(
302                     detail::begin_(r)
303                     , detail::end_(r)
304                     , detail::begin_(r2)
305                     , detail::end_(r2)
306                     , p
307                     );
308             }
309         };
310 
311         struct lower_bound
312         {
313             template <typename Sig>
314             struct result;
315 
316             template <typename This, class R, class T>
317             struct result<This(R&, T&)>
318                 : range_iterator<R>
319             {};
320 
321             template <typename This, class R, class T, class C>
322             struct result<This(R&, T&, C)>
323                 : range_iterator<R>
324             {};
325 
326             template<class R, class T>
327             typename range_iterator<R>::type
executeboost::phoenix::impl::lower_bound328             execute(R& r, T const& val, mpl::true_) const
329             {
330                 return r.lower_bound(val);
331             }
332 
333             template<class R, class T>
334             typename range_iterator<R>::type
executeboost::phoenix::impl::lower_bound335             execute(R& r, T const& val, mpl::false_) const
336             {
337                 return std::lower_bound(detail::begin_(r), detail::end_(r), val);
338             }
339 
340             template<class R, class T>
341             typename range_iterator<R>::type
operator ()boost::phoenix::impl::lower_bound342             operator()(R& r, T const& val) const
343             {
344                 return execute(r, val, has_lower_bound<R>());
345             }
346 
347             template<class R, class T, class C>
348             typename range_iterator<R>::type
operator ()boost::phoenix::impl::lower_bound349             operator()(R& r, T const& val, C c) const
350             {
351                 return std::lower_bound(detail::begin_(r), detail::end_(r), val, c);
352             }
353         };
354 
355         struct upper_bound
356         {
357             template <typename Sig>
358             struct result;
359 
360             template <typename This, class R, class T>
361             struct result<This(R&, T&)>
362                 : range_iterator<R>
363             {};
364 
365             template <typename This, class R, class T, class C>
366             struct result<This(R&, T&, C)>
367                 : range_iterator<R>
368             {};
369 
370             template<class R, class T>
371             typename range_iterator<R>::type
executeboost::phoenix::impl::upper_bound372             execute(R& r, T const& val, mpl::true_) const
373             {
374                 return r.upper_bound(val);
375             }
376 
377             template<class R, class T>
378             typename range_iterator<R>::type
executeboost::phoenix::impl::upper_bound379             execute(R& r, T const& val, mpl::false_) const
380             {
381                 return std::upper_bound(detail::begin_(r), detail::end_(r), val);
382             }
383 
384             template<class R, class T>
385             typename range_iterator<R>::type
operator ()boost::phoenix::impl::upper_bound386             operator()(R& r, T const& val) const
387             {
388                 return execute(r, val, has_upper_bound<R>());
389             }
390 
391             template<class R, class T, class C>
392             typename range_iterator<R>::type
operator ()boost::phoenix::impl::upper_bound393             operator()(R& r, T const& val, C c) const
394             {
395                 return std::upper_bound(detail::begin_(r), detail::end_(r), val, c);
396             }
397         };
398 
399         namespace result_of
400         {
401             template <typename R, typename T, typename C = void>
402             struct equal_range
403             {
404                 typedef std::pair<
405                     typename range_iterator<R>::type
406                     , typename range_iterator<R>::type
407                 > type;
408             };
409         }
410 
411         struct equal_range
412         {
413             template <typename Sig>
414             struct result;
415 
416             template <typename This, class R, class T>
417             struct result<This(R&, T&)>
418                 : result_of::equal_range<R,T>
419             {};
420 
421             template <typename This, class R, class T, class C>
422             struct result<This(R&, T&, C)>
423                 : result_of::equal_range<R,T, C>
424             {};
425 
426             template<class R, class T>
427             typename result_of::equal_range<R, T>::type
executeboost::phoenix::impl::equal_range428             execute(R& r, T const& val, mpl::true_) const
429             {
430                 return r.equal_range(val);
431             }
432 
433             template<class R, class T>
434             typename result_of::equal_range<R, T>::type
executeboost::phoenix::impl::equal_range435             execute(R& r, T const& val, mpl::false_) const
436             {
437                 return std::equal_range(detail::begin_(r), detail::end_(r), val);
438             }
439 
440             template<class R, class T>
441             typename result_of::equal_range<R, T>::type
operator ()boost::phoenix::impl::equal_range442             operator()(R& r, T const& val) const
443             {
444                 return execute(r, val, has_equal_range<R>());
445             }
446 
447             template<class R, class T, class C>
448             typename result_of::equal_range<R, T, C>::type
operator ()boost::phoenix::impl::equal_range449             operator()(R& r, T const& val, C c) const
450             {
451                 return std::equal_range(detail::begin_(r), detail::end_(r), val, c);
452             }
453         };
454 
455         namespace result_of
456         {
457             template <typename R, typename I, typename P = void>
458             struct mismatch
459             {
460                 typedef std::pair<
461                     typename range_iterator<R>::type
462                     , typename detail::decay_array<I>::type
463                 > type;
464             };
465         }
466 
467         struct mismatch
468         {
469             template <typename Sig>
470             struct result;
471 
472             template<typename This, class R, class I>
473             struct result<This(R&, I)>
474                 : result_of::mismatch<R, I>
475             {};
476 
477             template<typename This, class R, class I, class P>
478             struct result<This(R&, I, P)>
479                 : result_of::mismatch<R, I, P>
480             {};
481 
482             template<class R, class I>
483             typename result_of::mismatch<R, I>::type
operator ()boost::phoenix::impl::mismatch484             operator()(R& r, I i) const
485             {
486                 return std::mismatch(detail::begin_(r), detail::end_(r), i);
487             }
488 
489             template<class R, class I, class P>
490             typename result_of::mismatch<R, I, P>::type
operator ()boost::phoenix::impl::mismatch491             operator()(R& r, I i, P p) const
492             {
493                 return std::mismatch(detail::begin_(r), detail::end_(r), i, p);
494             }
495         };
496 
497         struct binary_search
498         {
499             typedef bool result_type;
500 
501             template<class R, class T>
operator ()boost::phoenix::impl::binary_search502             bool operator()(R& r, T const& val) const
503             {
504                 return std::binary_search(detail::begin_(r), detail::end_(r), val);
505             }
506 
507             template<class R, class T, class C>
operator ()boost::phoenix::impl::binary_search508             bool operator()(R& r, T const& val, C c) const
509             {
510                 return std::binary_search(detail::begin_(r), detail::end_(r), val, c);
511             }
512         };
513 
514         struct includes
515         {
516             typedef bool result_type;
517 
518             template<class R1, class R2>
operator ()boost::phoenix::impl::includes519             bool operator()(R1& r1, R2& r2) const
520             {
521                 return std::includes(
522                     detail::begin_(r1), detail::end_(r1)
523                     , detail::begin_(r2), detail::end_(r2)
524                     );
525             }
526 
527             template<class R1, class R2, class C>
operator ()boost::phoenix::impl::includes528             bool operator()(R1& r1, R2& r2, C c) const
529             {
530                 return std::includes(
531                     detail::begin_(r1), detail::end_(r1)
532                     , detail::begin_(r2), detail::end_(r2)
533                     , c
534                     );
535             }
536         };
537 
538         struct min_element
539         {
540             template <typename Sig>
541             struct result;
542 
543             template <typename This, class R>
544             struct result<This(R&)>
545                 : range_iterator<R>
546             {};
547 
548             template <typename This, class R, class P>
549             struct result<This(R&, P)>
550                 : range_iterator<R>
551             {};
552 
553             template<class R>
554             typename range_iterator<R>::type
operator ()boost::phoenix::impl::min_element555             operator()(R& r) const
556             {
557                 return std::min_element(detail::begin_(r), detail::end_(r));
558             }
559 
560             template<class R, class P>
561             typename range_iterator<R>::type
operator ()boost::phoenix::impl::min_element562             operator()(R& r, P p) const
563             {
564                 return std::min_element(detail::begin_(r), detail::end_(r), p);
565             }
566         };
567 
568         struct max_element
569         {
570             template <typename Sig>
571             struct result;
572 
573             template <typename This, class R>
574             struct result<This(R&)>
575                 : range_iterator<R>
576             {};
577 
578             template <typename This, class R, class P>
579             struct result<This(R&, P)>
580                 : range_iterator<R>
581             {};
582 
583             template<class R>
584             typename range_iterator<R>::type
operator ()boost::phoenix::impl::max_element585             operator()(R& r) const
586             {
587                 return std::max_element(detail::begin_(r), detail::end_(r));
588             }
589 
590             template<class R, class P>
591             typename range_iterator<R>::type
operator ()boost::phoenix::impl::max_element592             operator()(R& r, P p) const
593             {
594                 return std::max_element(detail::begin_(r), detail::end_(r), p);
595             }
596         };
597 
598         struct lexicographical_compare
599         {
600             typedef bool result_type;
601 
602             template<class R1, class R2>
operator ()boost::phoenix::impl::lexicographical_compare603             bool operator()(R1& r1, R2& r2) const
604             {
605                 return std::lexicographical_compare(
606                     detail::begin_(r1), detail::end_(r1)
607                     , detail::begin_(r2), detail::end_(r2)
608                     );
609             }
610 
611             template<class R1, class R2, class P>
operator ()boost::phoenix::impl::lexicographical_compare612             bool operator()(R1& r1, R2& r2, P p) const
613             {
614                 return std::lexicographical_compare(
615                     detail::begin_(r1), detail::end_(r1)
616                     , detail::begin_(r2), detail::end_(r2)
617                     , p
618                     );
619             }
620         };
621 
622     }
623 
624     BOOST_PHOENIX_ADAPT_CALLABLE(find, impl::find, 2)
625     BOOST_PHOENIX_ADAPT_CALLABLE(find_if, impl::find_if, 2)
626     BOOST_PHOENIX_ADAPT_CALLABLE(find_end, impl::find_end, 2)
627     BOOST_PHOENIX_ADAPT_CALLABLE(find_end, impl::find_end, 3)
628     BOOST_PHOENIX_ADAPT_CALLABLE(find_first_of, impl::find_first_of, 2)
629     BOOST_PHOENIX_ADAPT_CALLABLE(find_first_of, impl::find_first_of, 3)
630     BOOST_PHOENIX_ADAPT_CALLABLE(adjacent_find, impl::adjacent_find, 1)
631     BOOST_PHOENIX_ADAPT_CALLABLE(adjacent_find, impl::adjacent_find, 2)
632     BOOST_PHOENIX_ADAPT_CALLABLE(count, impl::count, 2)
633     BOOST_PHOENIX_ADAPT_CALLABLE(count_if, impl::count_if, 2)
634     BOOST_PHOENIX_ADAPT_CALLABLE(distance, impl::distance, 1)
635     BOOST_PHOENIX_ADAPT_CALLABLE(equal, impl::equal, 2)
636     BOOST_PHOENIX_ADAPT_CALLABLE(equal, impl::equal, 3)
637     BOOST_PHOENIX_ADAPT_CALLABLE(search, impl::search, 2)
638     BOOST_PHOENIX_ADAPT_CALLABLE(search, impl::search, 3)
639     BOOST_PHOENIX_ADAPT_CALLABLE(lower_bound, impl::lower_bound, 2)
640     BOOST_PHOENIX_ADAPT_CALLABLE(lower_bound, impl::lower_bound, 3)
641     BOOST_PHOENIX_ADAPT_CALLABLE(upper_bound, impl::upper_bound, 2)
642     BOOST_PHOENIX_ADAPT_CALLABLE(upper_bound, impl::upper_bound, 3)
643     BOOST_PHOENIX_ADAPT_CALLABLE(equal_range, impl::equal_range, 2)
644     BOOST_PHOENIX_ADAPT_CALLABLE(equal_range, impl::equal_range, 3)
645     BOOST_PHOENIX_ADAPT_CALLABLE(mismatch, impl::mismatch, 2)
646     BOOST_PHOENIX_ADAPT_CALLABLE(mismatch, impl::mismatch, 3)
647     BOOST_PHOENIX_ADAPT_CALLABLE(binary_search, impl::binary_search, 2)
648     BOOST_PHOENIX_ADAPT_CALLABLE(binary_search, impl::binary_search, 3)
649     BOOST_PHOENIX_ADAPT_CALLABLE(includes, impl::includes, 2)
650     BOOST_PHOENIX_ADAPT_CALLABLE(includes, impl::includes, 3)
651     BOOST_PHOENIX_ADAPT_CALLABLE(min_element, impl::min_element, 1)
652     BOOST_PHOENIX_ADAPT_CALLABLE(min_element, impl::min_element, 2)
653     BOOST_PHOENIX_ADAPT_CALLABLE(max_element, impl::max_element, 1)
654     BOOST_PHOENIX_ADAPT_CALLABLE(max_element, impl::max_element, 2)
655     BOOST_PHOENIX_ADAPT_CALLABLE(lexicographical_compare, impl::lexicographical_compare, 2)
656     BOOST_PHOENIX_ADAPT_CALLABLE(lexicographical_compare, impl::lexicographical_compare, 3)
657 
658 }}
659 
660 #endif
661