algorithm.hpp
Go to the documentation of this file.
1
14 #ifndef CORE_ALGORITHM_HPP
15 #define CORE_ALGORITHM_HPP
16
17 #include <algorithm>
18
19 #include "functional.hpp"
20 #include "utility.hpp"
21 #include "range.hpp"
22
23 namespace core {
24 inline namespace v2 {
25 namespace impl {
26
27 template <class InputIt1, class InputIt2, class Predicate>
28 bool equal (
29  range<InputIt1> r1,
30  range<InputIt2> r2,
31  Predicate&& p,
32  ::std::random_access_iterator_tag,
33  ::std::random_access_iterator_tag
34 ) {
35  if (r1.size() != r2.size()) { return false; }
37  begin(r1),
38  end(r1),
39  begin(r2),
40  ::core::forward<Predicate>(p)
41  );
42 }
43
44 template <class InputIt1, class InputIt2, class Predicate>
45 bool equal (
46  range<InputIt1> r1,
47  range<InputIt2> r2,
48  Predicate&& p,
49  ::std::input_iterator_tag,
50  ::std::input_iterator_tag
51 ) {
52  while (not r1.empty() and not r2.empty()) {
53  if (
55  ::core::forward<Predicate>(p),
56  r1.front(),
57  r2.front())
58  ) { return false; }
59  r1.pop_front();
60  r2.pop_front();
61  }
62  return r1.empty() and r2.empty();
63 }
64
65 } /* namespace impl */
66
67 /* non-range based algorithms */
68 template <class T>
69 constexpr T const& min (T const& lhs, T const& rhs) {
70  return (rhs < lhs) ? rhs : lhs;
71 }
72
73 template <class T, class Compare>
74 constexpr T const& min (T const& lhs, T const& rhs, Compare compare) {
75  return compare(rhs, lhs) ? rhs : lhs;
76 }
77
78 template <class T>
79 constexpr T const& max (T const& lhs, T const& rhs) {
80  return (lhs < rhs) ? rhs : lhs;
81 }
82
83 template <class T, class Compare>
84 constexpr T const& max (T const& lhs, T const& rhs, Compare compare) {
85  return compare(lhs, rhs) ? rhs : lhs;
86 }
87
88 /* extensions */
89 template <class T, class Compare=less<>>
90 constexpr T const& clamp (
91  T const& value,
92  T const& low,
93  T const& high,
94  Compare compare = Compare { }
95 ) {
96  return compare(value, low)
97  ? low
98  : compare(high, value)
99  ? high
100  : value;
101 }
102
103 /* N4318 (modified) */
104 template <
105  class T,
106  class Compare = ::core::less<>,
107  class Difference = ::core::minus<>
108 > constexpr auto abs_diff (
109  T const& a,
110  T const& b,
111  Compare compare = Compare { },
112  Difference diff = Difference { }
113 ) -> decltype(compare(a, b) ? diff(b, a) : diff(a, b)) {
114  return compare(a, b) ? diff(b, a) : diff(a, b);
115 }
116
117 /* non-modifying sequence algorithms */
118 template <class Range, class UnaryPredicate>
119 auto all_of (Range&& rng, UnaryPredicate&& p) -> meta::when<
121  bool
122 > {
123  auto range = make_range(::core::forward<Range>(rng));
124  static constexpr auto is_input = decltype(range)::is_input;
125  static_assert(is_input, "all_of requires InputIterators");
127  ::std::begin(range),
128  ::std::end(range),
129  ::core::forward<UnaryPredicate>(p)
130  );
131 }
132
133 template <class Range, class UnaryPredicate>
134 auto any_of (Range&& rng, UnaryPredicate&& p) -> enable_if_t<
135  is_range<Range>::value,
136  bool
137 > {
138  auto range = make_range(::core::forward<Range>(rng));
139  static constexpr auto is_input = decltype(range)::is_input;
140  static_assert(is_input, "any_of requires InputIterators");
142  ::std::begin(range),
143  ::std::end(range),
144  ::core::forward<UnaryPredicate>(p)
145  );
146 }
147
148 template <class Range, class UnaryPredicate>
149 auto none_of (Range&& rng, UnaryPredicate&& p) -> enable_if_t<
150  is_range<Range>::value,
151  bool
152 > {
153  auto range = make_range(::core::forward<Range>(rng));
154  static constexpr auto is_input = decltype(range)::is_input;
155  static_assert(is_input, "none_of requires InputIterators");
157  ::std::begin(range),
158  ::std::end(range),
159  ::core::forward<UnaryPredicate>(p)
160  );
161 }
162
163 template <class Range, class UnaryFunction>
164 auto for_each (Range&& rng, UnaryFunction&& f) -> enable_if_t<
165  is_range<Range>::value,
167 > {
168  auto range = make_range(::core::forward<Range>(rng));
169  static constexpr auto is_input = decltype(range)::is_input;
170  static_assert(is_input, "for_each requires InputIterators");
172  ::std::begin(range),
173  ::std::end(range),
174  ::core::forward<UnaryFunction>(f)
175  );
176 }
177
178 template <class Range, class UnaryFunction, class UnaryPredicate>
179 UnaryFunction for_each_if (Range&& r, UnaryFunction uf, UnaryPredicate up) {
180  auto range = make_range(::core::forward<Range>(r));
181  static constexpr auto is_input = decltype(range)::is_input;
182  static_assert(is_input, "for_each_if requires InputIterators");
183  while (not range.empty()) {
184  if (up(range.front())) { uf(range.front()); }
185  range.pop_front();
186  }
187  return uf;
188 }
189
190 template <class Range, class UnaryFunction, class UnaryPredicate>
192  Range&& r,
193  UnaryFunction f,
194  UnaryPredicate p
195 ) -> decltype(begin(make_range(::core::forward<Range>(r)))) {
196  auto range = make_range(::core::forward<Range>(r));
197  static constexpr auto is_input = decltype(range)::is_input;
198  static_assert(is_input, "for_each_while requires InputIterators");
199  while (not range.empty()) {
200  if (not p(range.front())) { break; }
201  f(range.front());
202  range.pop_front();
203  }
204  return range.begin();
205 }
206
207 template <class Range, class UnaryFunction, class T>
209  Range&& r,
210  UnaryFunction f,
211  T const& value
212 ) -> decltype(begin(make_range(::core::forward<Range>(r)))) {
213  auto range = make_range(::core::forward<Range>(r));
214  static constexpr auto is_input = decltype(range)::is_input;
215  static_assert(is_input, "for_each_until requires InputIterators");
216  while (not range.empty()) {
217  if (range.front() == value) { break; }
218  f(range.front());
219  range.pop_front();
220  }
221  return range.begin();
222 }
223
224 template <class Range, class T>
225 auto count (Range&& rng, T const& value) -> enable_if_t<
226  is_range<Range>::value,
227  decltype(
228  ::std::count(
229  ::std::begin(::core::forward<Range>(rng)),
230  ::std::end(::core::forward<Range>(rng)),
231  value
232  )
233  )
234 > {
235  auto range = make_range(::core::forward<Range>(rng));
236  static constexpr auto is_input = decltype(range)::is_input;
237  static_assert(is_input, "count requires InputIterators");
238  return ::std::count(::std::begin(range), ::std::end(range), value);
239 }
240
241 template <class Range, class UnaryPredicate>
242 auto count_if (Range&& rng, UnaryPredicate&& p) -> enable_if_t<
243  is_range<Range>::value,
244  decltype(
245  ::std::count_if(
246  ::std::begin(::core::forward<Range>(rng)),
247  ::std::end(::core::forward<Range>(rng)),
248  ::core::forward<UnaryPredicate>(p)
249  )
250  )
251 > {
252  auto range = make_range(::core::forward<Range>(rng));
253  static constexpr auto is_input = decltype(range)::is_input;
254  static_assert(is_input, "count_if requires InputIterators");
256  ::std::begin(range),
257  ::std::end(range),
258  ::core::forward<UnaryPredicate>(p)
259  );
260 }
261
262 template <class InputIt1, class InputIt2, class BinaryPredicate>
263 ::std::pair<InputIt1, InputIt2> mismatch (
264  InputIt1 first1,
265  InputIt1 last1,
266  InputIt2 first2,
267  InputIt2 last2,
268  BinaryPredicate predicate
269 ) {
270  auto r1 = make_range(first1, last1);
271  auto r2 = make_range(first2, last2);
272  while (not r1.empty() and not r2.empty()) {
273  if (not predicate(r1.front(), r2.front())) { break; }
274  r1.pop_front();
275  r2.pop_front();
276  }
277  return ::std::make_pair(r1.begin(), r2.begin());
278 }
279
280 template <class InputIt1, class InputIt2>
281 ::std::pair<InputIt1, InputIt2> mismatch (
282  InputIt1 first1,
283  InputIt1 last1,
284  InputIt2 first2,
285  InputIt2 last2
286 ) { return (mismatch)(first1, last1, first2, last2, equal_to<> { }); }
287
288 template <
289  class Range1,
290  class Range2,
291  class BinaryPred,
293  meta::all_of<meta::list<Range1, Range2>, is_range>()
294  > = __LINE__
295 > auto mismatch (Range1&& r1, Range2&& r2, BinaryPred&& bp) -> ::std::pair<
296  decltype(::std::begin(::core::forward<Range1>(r1))),
297  decltype(::std::begin(::core::forward<Range2>(r2)))
298 > {
299  auto range1 = make_range(::core::forward<Range1>(r1));
300  auto range2 = make_range(::core::forward<Range2>(r2));
301  static constexpr auto is_input1 = decltype(range1)::is_input;
302  static constexpr auto is_input2 = decltype(range2)::is_input;
303  static_assert(is_input1 and is_input2, "mismatch requires InputIterators");
304  return (mismatch)(
305  range1.begin(),
306  range1.end(),
307  range2.begin(),
308  range2.end(),
309  ::core::forward<BinaryPred>(bp));
310 }
311
312 template <
313  class Range,
314  class InputIt,
316  meta::all<is_range<Range>::value, meta::none<is_range<InputIt>::value>()>()
317  > = __LINE__
318 > auto mismatch(Range&& rng, InputIt&& it) -> ::std::pair<
319  decltype(make_range(::core::forward<Range>(rng)).begin()),
321 > {
322  auto range = make_range(::core::forward<Range>(rng));
323  static constexpr auto is_input = decltype(range)::is_input;
324  static_assert(is_input, "mismatch requires InputIterators");
326  ::std::begin(range),
327  ::std::end(range),
328  ::core::forward<InputIt>(it)
329  );
330 }
331
332 template <
333  class Range,
334  class InputIt,
335  class BinaryPredicate,
337  meta::all<is_range<Range>::value, meta::none<is_range<InputIt>>()>()
338  > = __LINE__
339 > auto mismatch(Range&& r, InputIt&& it, BinaryPredicate&& bp) -> ::std::pair<
340  decltype(core::make_range(::core::forward<Range>(r).begin())),
342 > {
343  auto range = make_range(::core::forward<Range>(r));
344  static constexpr auto is_input = decltype(range)::is_input;
345  static_assert(is_input, "mismatch requires InputIterators");
347  ::std::begin(range),
348  ::std::end(range),
349  ::core::forward<InputIt>(it),
350  ::core::forward<BinaryPredicate>(bp)
351  );
352 }
353
354 template <class InputIt1, class InputIt2, class BinaryPredicate>
355 bool equal (
356  InputIt1 first1,
357  InputIt1 last1,
358  InputIt2 first2,
359  InputIt2 last2,
360  BinaryPredicate bp
361 ) {
362  auto r1 = make_range(first1, last1);
363  auto r2 = make_range(first2, last2);
364  using tag1 = typename decltype(r1)::iterator_category;
365  using tag2 = typename decltype(r2)::iterator_category;
366  return impl::equal(r1, r2, bp, tag1 { }, tag2 { });
367 }
368
369 template <class InputIt1, class InputIt2>
370 bool equal (InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2) {
371  return equal(first1, last1, first2, last2, equal_to<> { });
372 }
373
374 template <
375  class Range1,
376  class Range2,
378  meta::all_of<meta::list<Range1, Range2>, is_range>()
379  > = __LINE__
380 > bool equal (Range1&& range1, Range2&& range2) {
381  auto r1 = make_range(::core::forward<Range1>(range1));
382  auto r2 = make_range(::core::forward<Range2>(range2));
383  static constexpr auto is_input1 = decltype(r1)::is_input;
384  static constexpr auto is_input2 = decltype(r2)::is_input;
385  static_assert(is_input1, "equal requires InputIterators");
386  static_assert(is_input2, "equal requires InputIterators");
387  return (equal)(r1.begin(), r1.end(), r2.begin(), r2.end());
388 }
389
390 template <
391  class Range1,
392  class Range2,
393  class BinaryPredicate,
395  meta::all_of<meta::list<Range1, Range2>, is_range>()
396  > = __LINE__
397 > bool equal (Range1&& range1, Range2&& range2, BinaryPredicate&& bp) {
398  auto r1 = make_range(::core::forward<Range1>(range1));
399  auto r2 = make_range(::core::forward<Range2>(range2));
400  static constexpr auto is_input1 = decltype(r1)::is_input;
401  static constexpr auto is_input2 = decltype(r2)::is_input;
402  static_assert(is_input1, "equal requires InputIterators");
403  static_assert(is_input2, "equal requires InputIterators");
404  return equal(
405  r1.begin(),
406  r1.end(),
407  r2.begin(),
408  r2.end(),
409  ::core::forward<BinaryPredicate>(bp)
410  );
411 }
412
413 template <
414  class Range,
415  class InputIt,
417  meta::all<is_range<Range>::value, meta::none<is_range<InputIt>::value>()>()
418  > = __LINE__
419 > bool equal (Range&& rng, InputIt&& it) {
420  auto range = make_range(::core::forward<Range>(rng));
421  static constexpr auto is_input = decltype(range)::is_input;
422  static_assert(is_input, "equal requires InputIterators");
424  ::std::begin(range),
425  ::std::end(range),
426  ::core::forward<InputIt>(it)
427  );
428 }
429
430 template <
431  class Range,
432  class InputIt,
433  class BinaryPredicate,
435  meta::all<is_range<Range>::value, meta::none<is_range<InputIt>>()>()
436  > = __LINE__
437 > bool equal (Range&& rng, InputIt&& it, BinaryPredicate&& bp) {
438  auto range = make_range(::core::forward<Range>(rng));
439  static constexpr auto is_input = decltype(range)::is_input;
440  static_assert(is_input, "equal requires InputIterators");
442  ::std::begin(range),
443  ::std::end(range),
444  ::core::forward<InputIt>(it),
445  ::core::forward<BinaryPredicate>(bp)
446  );
447 }
448
449 template <class Range, class T>
450 auto find (Range&& rng, T const& value) -> enable_if_t<
451  is_range<Range>::value,
452  decltype(::std::begin(::core::forward<Range>(rng)))
453 > {
454  auto range = make_range(::core::forward<Range>(rng));
455  static constexpr auto is_input = decltype(range)::is_input;
456  static_assert(is_input, "find requires InputIterators");
457  return ::std::find(::std::begin(range), ::std::end(range), value);
458 }
459
460 template <class Range, class UnaryPredicate>
461 auto find_if (Range&& rng, UnaryPredicate&& p) -> enable_if_t<
462  is_range<Range>::value,
463  decltype(::std::begin(::core::forward<Range>(rng)))
464 > {
465  auto range = make_range(::core::forward<Range>(rng));
466  static constexpr auto is_input = decltype(range)::is_input;
467  static_assert(is_input, "find_if requires InputIterators");
469  ::std::begin(range),
470  ::std::end(range),
471  ::core::forward<UnaryPredicate>(p)
472  );
473 }
474
475 template <class Range, class UnaryPredicate>
476 auto find_if_not (Range&& rng, UnaryPredicate&& p) -> enable_if_t<
477  is_range<Range>::value,
478  decltype(::std::begin(::core::forward<Range>(rng)))
479 > {
480  auto range = make_range(::core::forward<Range>(rng));
481  static constexpr auto is_input = decltype(range)::is_input;
482  static_assert(is_input, "find_if_not requires InputIterators");
484  ::std::begin(range),
485  ::std::end(range),
486  ::core::forward<UnaryPredicate>(p)
487  );
488 }
489
490 template <class Range1, class Range2>
491 auto find_end (Range1&& rng1, Range2&& rng2) -> meta::when<
492  meta::all_of<meta::list<Range1, Range2>, is_range>(),
493  decltype(::std::begin(::core::forward<Range1>(rng1)))
494 > {
495  auto range1 = make_range(::core::forward<Range1>(rng1));
496  auto range2 = make_range(::core::forward<Range2>(rng2));
497  static constexpr auto is_forward1 = decltype(range1)::is_forward;
498  static constexpr auto is_forward2 = decltype(range2)::is_forward;
499  static_assert(is_forward1, "find_end requires ForwardIterators");
500  static_assert(is_forward2, "find_end requires ForwardIterators");
502  ::std::begin(range1),
503  ::std::end(range1),
504  ::std::begin(range2),
505  ::std::end(range2)
506  );
507 }
508
509 template <class Range1, class Range2, class BinaryPred>
510 auto find_end (Range1&& rng1, Range2&& rng2, BinaryPred& bp) -> meta::when<
511  meta::all_of<meta::list<Range1, Range2>, is_range>(),
512  decltype(::std::begin(::core::forward<Range1>(rng1)))
513 > {
514  auto range1 = make_range(::core::forward<Range1>(rng1));
515  auto range2 = make_range(::core::forward<Range2>(rng2));
516  static constexpr auto is_forward1 = decltype(range1)::is_forward;
517  static constexpr auto is_forward2 = decltype(range2)::is_forward;
518  static_assert(is_forward1, "find_end requires ForwardIterators");
519  static_assert(is_forward2, "find_end requires ForwardIterators");
521  ::std::begin(range1),
522  ::std::end(range1),
523  ::std::begin(range2),
524  ::std::end(range2),
525  ::core::forward<BinaryPred>(bp)
526  );
527 }
528
529 template <class IRange, class FRange>
530 auto find_first_of (IRange&& irng, FRange&& frng) -> meta::when<
531  meta::all_of<meta::list<IRange, FRange>, is_range>(),
532  decltype(::std::begin(::core::forward<IRange>(irng)))
533 > {
534  auto irange = make_range(::core::forward<IRange>(irng));
535  auto frange = make_range(::core::forward<FRange>(frng));
536  static constexpr auto is_input = decltype(irange)::is_input;
537  static constexpr auto is_forward = decltype(frange)::is_forward;
538  static_assert(is_input, "find_first_of requires InputIterators");
539  static_assert(is_forward, "find_first_of requires ForwardIterators");
541  ::std::begin(irange),
542  ::std::end(irange),
543  ::std::begin(frange),
544  ::std::end(frange)
545  );
546 }
547
548 template <class IRange, class FRange, class BinaryPred>
550  IRange&& irng,
551  FRange&& frng,
552  BinaryPred&& bp
553 ) -> meta::when<
554  meta::all_of<meta::list<IRange, FRange>, is_range>(),
555  decltype(::std::begin(::core::forward<IRange>(irng)))
556 > {
557  auto irange = make_range(::core::forward<IRange>(irng));
558  auto frange = make_range(::core::forward<FRange>(frng));
559  static constexpr auto is_input = decltype(irange)::is_input;
560  static constexpr auto is_forward = decltype(frange)::is_forward;
561  static_assert(is_input, "find_first_of requires InputIterators");
562  static_assert(is_forward, "find_first_of requires ForwardIterators");
564  ::std::begin(irange),
565  ::std::end(irange),
566  ::std::begin(frange),
567  ::std::end(frange),
568  ::core::forward<BinaryPred>(bp)
569  );
570 }
571
572 template <class Range>
574  is_range<Range>::value,
575  decltype(::std::begin(::core::forward<Range>(rng)))
576 > {
577  auto range = make_range(::core::forward<Range>(rng));
578  static constexpr auto is_forward = decltype(range)::is_forward;
581 }
582
583 template <class Range, class BinaryPredicate>
584 auto adjacent_find (Range&& rng, BinaryPredicate&& bp) -> meta::when<
585  is_range<Range>::value,
586  decltype(::std::begin(::core::forward<Range>(rng)))
587 > {
588  auto range = make_range(::core::forward<Range>(rng));
589  static constexpr auto is_forward = decltype(range)::is_forward;
592  ::std::begin(range),
593  ::std::end(range),
594  ::core::forward<BinaryPredicate>(bp)
595  );
596 }
597
598 template <class Range1, class Range2>
599 auto search (Range1&& rng1, Range2&& rng2) -> meta::when<
600  meta::all_of<meta::list<Range1, Range2>, is_range>(),
601  decltype(::std::begin(::core::forward<Range1>(rng1)))
602 > {
603  auto range1 = make_range(::core::forward<Range1>(rng1));
604  auto range2 = make_range(::core::forward<Range2>(rng2));
605  static constexpr auto is_forward1 = decltype(range1)::is_forward;
606  static constexpr auto is_forward2 = decltype(range2)::is_forward;
607  static_assert(is_forward1, "search requires ForwardIterators");
608  static_assert(is_forward2, "search requires ForwardIterators");
610  ::std::begin(range1),
611  ::std::end(range1),
612  ::std::begin(range2),
613  ::std::end(range2)
614  );
615 }
616
617 template <class Range1, class Range2, class BinaryPred>
618 auto search (Range1&& rng1, Range2&& rng2, BinaryPred&& bp) -> enable_if_t<
619  meta::all_of<meta::list<Range1, Range2>, is_range>(),
620  decltype(::std::begin(::core::forward<Range1>(rng1)))
621 > {
622  auto range1 = make_range(::core::forward<Range1>(rng1));
623  auto range2 = make_range(::core::forward<Range2>(rng2));
624  static constexpr auto is_forward1 = decltype(range1)::is_forward;
625  static constexpr auto is_forward2 = decltype(range2)::is_forward;
626  static_assert(is_forward1, "search requires ForwardIterators");
627  static_assert(is_forward2, "search requires ForwardIterators");
629  ::std::begin(range1),
630  ::std::end(range1),
631  ::std::begin(range2),
632  ::std::end(range2),
633  ::core::forward<BinaryPred>(bp)
634  );
635 }
636
637 template <class Range, class Size, class T>
638 auto search_n (Range&& rng, Size&& count, T const& value) -> enable_if_t<
639  is_range<Range>::value,
640  decltype(::std::begin(::core::forward<Range>(rng)))
641 > {
642  auto range = make_range(::core::forward<Range>(rng));
643  static constexpr auto is_forward = decltype(range)::is_forward;
644  static_assert(is_forward, "search_n requires ForwardIterators");
646  ::std::begin(range),
647  ::std::end(range),
648  ::core::forward<Size>(count),
649  value
650  );
651 }
652
653 template <class Range, class Size, class T, class BinaryPred>
654 auto search_n (
655  Range&& rng,
656  Size&& count,
657  T const& value,
658  BinaryPred&& bp
659 ) -> meta::when<
660  is_range<Range>::value,
661  decltype(::std::begin(::core::forward<Range>(rng)))
662 > {
663  auto range = make_range(::core::forward<Range>(rng));
664  static constexpr auto is_forward = decltype(range)::is_forward;
665  static_assert(is_forward, "search_n requires ForwardIterators");
667  ::std::begin(range),
668  ::std::end(range),
669  ::core::forward<Size>(count),
670  value,
671  ::core::forward<BinaryPred>(bp)
672  );
673 }
674
675 /* modifying sequence algorithms */
676 template <class Range, class OutputIt>
677 auto copy (Range&& rng, OutputIt&& it) -> enable_if_t<
678  is_range<Range>::value,
680 > {
681  auto range = make_range(::core::forward<Range>(rng));
682  static constexpr auto is_input = decltype(range)::is_input;
683  static_assert(is_input, "copy requires InputIterators");
685  ::std::begin(range),
686  ::std::end(range),
687  ::core::forward<OutputIt>(it)
688  );
689 }
690
691 template <class Range, class OutputIt, class UnaryPredicate>
692 auto copy_if (Range&& rng, OutputIt&& it, UnaryPredicate&& up) -> enable_if_t<
693  is_range<Range>::value,
695 > {
696  auto range = make_range(::core::forward<Range>(rng));
697  static constexpr auto is_input = decltype(range)::is_input;
698  static_assert(is_input, "copy_if requires InputIterators");
700  ::std::begin(range),
701  ::std::end(range),
702  ::core::forward<OutputIt>(it),
703  ::core::forward<UnaryPredicate>(up)
704  );
705 }
706
707 template <class Range, class OutputIt, class T>
708 OutputIt copy_until (Range&& r, OutputIt it, T const& value) {
709  auto range = make_range(::core::forward<Range>(r));
710  static constexpr auto is_input = decltype(range)::is_input;
711  static_assert(is_input, "copy_until requires InputIterators");
712  while (not range.empty()) {
713  if (range.front() == value) { break; }
714  *it++ = range.front();
715  range.pop_front();
716  }
717  return it;
718 }
719
720 template <class Range, class BidirIt>
721 auto copy_backward (Range&& rng, BidirIt&& it) -> enable_if_t<
722  is_range<Range>::value,
724 > {
725  auto range = make_range(::core::forward<Range>(rng));
726  static constexpr auto is_bidir = decltype(range)::is_bidirectional;
727  static_assert(is_bidir, "copy_backward requires BidirectionalIterators");
729  ::std::begin(range),
730  ::std::end(range),
731  ::core::forward<BidirIt>(it)
732  );
733 }
734
735 template <class Range, class OutputIt>
736 auto move (Range&& rng, OutputIt&& it) -> enable_if_t<
737  is_range<Range>::value,
739 > {
740  auto range = make_range(::core::forward<Range>(rng));
741  static constexpr auto is_input = decltype(range)::is_input;
742  static_assert(is_input, "move requires InputIterators");
744  ::std::begin(range),
745  ::std::end(range),
746  ::core::forward<OutputIt>(it)
747  );
748 }
749
750 template <class Range, class BidirIt>
751 auto move_backward (Range&& rng, BidirIt&& it) -> enable_if_t<
752  is_range<Range>::value,
754 > {
755  auto range = make_range(::core::forward<Range>(rng));
756  static constexpr auto is_bidir = decltype(range)::is_bidirectional;
757  static_assert(is_bidir, "move_backward requires BidirectionalIterators");
759  ::std::begin(range),
760  ::std::end(range),
761  ::core::forward<BidirIt>(it)
762  );
763 }
764
765 template <class Range, class T>
766 auto fill (Range&& rng, T const& value) -> enable_if_t<
767  is_range<Range>::value
768 > {
769  auto range = make_range(::core::forward<Range>(rng));
770  static constexpr auto is_forward = decltype(range)::is_forward;
771  static_assert(is_forward, "fill requires ForwardIterators");
772  return ::std::fill(::std::begin(range), ::std::end(range), value);
773 }
774
775 template <class Range, class OutputIt, class UnaryOperation>
776 auto transform (
777  Range&& rng,
778  OutputIt&& it,
779  UnaryOperation&& op
780 ) -> enable_if_t<
781  is_range<Range>::value,
783 > {
784  auto range = make_range(::core::forward<Range>(rng));
785  static constexpr auto is_input = decltype(range)::is_input;
786  static_assert(is_input, "transform requires InputIterators");
788  ::std::begin(range),
789  ::std::end(range),
790  ::core::forward<OutputIt>(it),
791  ::core::forward<UnaryOperation>(op)
792  );
793 }
794
795 template <class Range, class OutputIt, class UnaryOperation, class UnaryPred>
797  Range&& rng,
798  OutputIt it,
799  UnaryOperation op,
800  UnaryPred up
801 ) -> enable_if_t<
802  is_range<Range>::value,
803  OutputIt
804 > {
805  auto range = make_range(::core::forward<Range>(rng));
806  static constexpr auto is_forward = decltype(range)::is_forward;
807  static_assert(is_forward, "transform_if requires ForwardIterators");
808  while (not range.empty()) {
809  if (invoke(up, range.front())) {
810  *it = invoke(op, range.front());
811  ++it;
812  }
813  range.pop_front();
814  }
815  return it;
816 }
817
818 template <class InputIt, class Size, class OutputIt, class UnaryOp>
819 OutputIt transform_n (InputIt in, Size count, OutputIt out, UnaryOp op) {
820  while (count > 0) {
821  *out = invoke(op, *in);
822  ++out;
823  ++in;
824  --count;
825  }
826  return out;
827 }
828
829 template <
830  class InputIt1,
831  class InputIt2,
832  class Size,
833  class OutputIt,
834  class UnaryOp
835 > OutputIt transform_n (
836  InputIt1 in1,
837  InputIt2 in2,
838  Size count,
839  OutputIt out,
840  UnaryOp op
841 ) {
842  while (count > 0) {
843  *out = invoke(op, *in1, *in2);
844  ++out;
845  ++in1;
846  ++in2;
847  --count;
848  }
849  return out;
850 }
851
852
853 template <
854  class Range,
855  class InputIt,
856  class OutputIt,
857  class BinaryOperation,
859  meta::all<is_range<Range>::value, meta::none<is_range<InputIt>::value>()>()
860  > = __LINE__
862  Range&& r,
863  InputIt&& in,
864  OutputIt&& out,
865  BinaryOperation&& op
866 ) {
867  auto range = make_range(::core::forward<Range>(r));
868  static constexpr auto is_input = decltype(range)::is_input;
869  static_assert(is_input, "transform requires InputIterators");
871  range.begin(),
872  range.end(),
873  ::core::forward<InputIt>(in),
874  ::core::forward<OutputIt>(out),
875  ::core::forward<BinaryOperation>(op));
876 }
877
878 template <
879  class Range1,
880  class Range2,
881  class OutputIt,
882  class BinaryOperation,
884  meta::all_of<meta::list<Range1, Range2>, is_range>()
885  > = __LINE__
887  Range1&& rng1,
888  Range2&& rng2,
889  OutputIt&& it,
890  BinaryOperation&& op
891 ) {
892  auto range1 = make_range(::core::forward<Range1>(rng1));
893  auto range2 = make_range(::core::forward<Range2>(rng2));
894  static constexpr auto is_input1 = decltype(range1)::is_input;
895  static constexpr auto is_input2 = decltype(range2)::is_input;
896  static_assert(is_input1, "transform requires InputIterators");
897  static_assert(is_input2, "transform requires InputIterators");
899  ::std::begin(range1),
900  ::std::end(range1),
901  ::std::begin(range2),
902  ::core::forward<OutputIt>(it),
903  ::core::forward<BinaryOperation>(op)
904  );
905 }
906
907 template <
908  class Range1,
909  class Range2,
910  class OutputIt,
911  class BinaryOperation,
912  class BinaryPredicate
913 > auto transform_if (
914  Range1&& rng1,
915  Range2&& rng2,
916  OutputIt it,
917  BinaryOperation op,
918  BinaryPredicate bp
919 ) -> meta::when<
920  meta::all_of<meta::list<Range1, Range2>, is_range>(),
921  OutputIt
922 > {
923  auto range1 = make_range(::core::forward<Range1>(rng1));
924  auto range2 = make_range(::core::forward<Range2>(rng2));
925  static constexpr auto is_forward1 = decltype(range1)::is_forward;
926  static constexpr auto is_forward2 = decltype(range2)::is_forward;
927  static_assert(is_forward1, "transform_if requires ForwardIterators");
928  static_assert(is_forward2, "transform_if requires ForwardIterators");
929  while (not range1.empty()) {
930  if (bp(range1.front(), range2.front())) {
931  *it = op(range1.front(), range2.front());
932  ++it;
933  }
934  range1.pop_front();
935  range2.pop_front();
936  }
937  return it;
938 }
939
940 template <class Range, class T>
941 auto remove (Range&& rng, T const& value) -> enable_if_t<
942  is_range<Range>::value,
943  decltype(::std::begin(::core::forward<Range>(rng)))
944 > {
945  auto range = make_range(::core::forward<Range>(rng));
946  static constexpr auto is_forward = decltype(range)::is_forward;
947  static_assert(is_forward, "remove requires ForwardIterators");
948  return ::std::remove(::std::begin(range), ::std::end(range), value);
949 }
950
951 template <class Range, class UnaryPredicate>
952 auto remove_if (Range&& rng, UnaryPredicate&& up) -> enable_if_t<
953  is_range<Range>::value,
954  decltype(::std::begin(::core::forward<Range>(rng)))
955 > {
956  auto range = make_range(::core::forward<Range>(rng));
957  static constexpr auto is_forward = decltype(range)::is_forward;
958  static_assert(is_forward, "remove_if requires ForwardIterators");
960  ::std::begin(range),
961  ::std::end(range),
962  ::core::forward<UnaryPredicate>(up)
963  );
964 }
965
966 template <class Range, class OutputIt, class T>
967 auto remove_copy (Range&& rng, OutputIt&& it, T const& value) -> enable_if_t<
968  is_range<Range>::value,
970 > {
971  auto range = make_range(::core::forward<Range>(rng));
972  static constexpr auto is_input = decltype(range)::is_input;
973  static_assert(is_input, "remove_copy requires InputIterators");
975  ::std::begin(range),
976  ::std::end(range),
977  ::core::forward<OutputIt>(it),
978  value
979  );
980 }
981
982 template <class Range, class OutputIt, class UnaryPred>
983 auto remove_copy_if (Range&& rng, OutputIt&& it, UnaryPred&& up) -> enable_if_t<
984  is_range<Range>::value,
986 > {
987  auto range = make_range(::core::forward<Range>(rng));
988  static constexpr auto is_input = decltype(range)::is_input;
989  static_assert(is_input, "remove_copy_if requires InputIterators");
991  ::std::begin(range),
992  ::std::end(range),
993  ::core::forward<OutputIt>(it),
994  ::core::forward<UnaryPred>(up)
995  );
996 }
997
998 template <class Range, class T>
999 auto remove_erase (Range&& rng, T const& val) -> enable_if_t<
1000  is_range<Range>::value
1001 > {
1002  ::core::forward<Range>(rng).erase(
1003  remove(::core::forward<Range>(rng), val),
1004  ::std::end(::core::forward<Range>(rng))
1005  );
1006 }
1007
1008 template <class Range, class UnaryPred>
1009 auto remove_erase_if (Range&& rng, UnaryPred&& up) -> enable_if_t<
1010  is_range<Range>::value
1011 > {
1012  ::core::forward<Range>(rng).erase(
1013  remove_if(
1014  ::core::forward<Range>(rng),
1015  ::core::forward<UnaryPred>(up)
1016  ),
1017  ::std::end(::core::forward<Range>(rng))
1018  );
1019 }
1020
1021 template <class Range, class T>
1022 auto replace (Range&& rng, T const& old, T const& value) -> enable_if_t<
1023  is_range<Range>::value
1024 > {
1025  auto range = make_range(::core::forward<Range>(rng));
1026  static constexpr auto is_forward = decltype(range)::is_input;
1027  static_assert(is_forward, "replace requires ForwardIterators");
1029  ::std::begin(range),
1030  ::std::end(range),
1031  old,
1032  value
1033  );
1034 }
1035
1036 template <class Range, class UnaryPred, class T>
1037 auto replace_if (Range&& rng, UnaryPred&& up, T const& value) -> enable_if_t<
1038  is_range<Range>::value
1039 > {
1040  auto range = make_range(::core::forward<Range>(rng));
1041  static constexpr auto is_forward = decltype(range)::is_forward;
1042  static_assert(is_forward, "replace_if requires ForwardIterators");
1044  ::std::begin(range),
1045  ::std::end(range),
1046  ::core::forward<UnaryPred>(up),
1047  value
1048  );
1049 }
1050
1051 template <class Range, class OutputIt, class T>
1053  Range&& rng,
1054  OutputIt&& it,
1055  T const& old,
1056  T const& value
1057 ) -> enable_if_t<
1058  is_range<Range>::value,
1060 > {
1061  auto range = make_range(::core::forward<Range>(rng));
1062  static constexpr auto is_input = decltype(range)::is_input;
1063  static_assert(is_input, "replace_copy requires InputIterators");
1065  ::std::begin(range),
1066  ::std::end(range),
1067  ::core::forward<OutputIt>(it),
1068  old,
1069  value
1070  );
1071 }
1072
1073 template <class Range, class OutputIt, class UnaryPred, class T>
1075  Range&& rng,
1076  OutputIt&& it,
1077  UnaryPred&& up,
1078  T const& value
1079 ) -> enable_if_t<
1080  is_range<Range>::value,
1082 > {
1083  auto range = make_range(::core::forward<Range>(rng));
1084  static constexpr auto is_input = decltype(range)::is_input;
1085  static_assert(is_input, "replace_copy_if requires InputIterators");
1087  ::std::begin(range),
1088  ::std::end(range),
1089  ::core::forward<OutputIt>(it),
1090  ::core::forward<UnaryPred>(up),
1091  value
1092  );
1093 }
1094
1095 template <class Range, class ForwardIt>
1096 auto swap_ranges (Range&& rng, ForwardIt&& it) -> enable_if_t<
1097  is_range<Range>::value,
1099 > {
1100  auto range = make_range(::core::forward<Range>(rng));
1101  static constexpr auto is_forward = decltype(range)::is_forward;
1102  static_assert(is_forward, "swap_ranges requires ForwardIterators");
1104  ::std::begin(range),
1105  ::std::end(range),
1106  ::core::forward<ForwardIt>(it)
1107  );
1108 }
1109
1110 template <class Range>
1112  auto range = make_range(::core::forward<Range>(rng));
1113  static constexpr auto is_bidir = decltype(range)::is_bidirectional;
1114  static_assert(is_bidir, "reverse requires BidirectionalIterators");
1115  return ::std::reverse(::std::begin(range), ::std::end(range));
1116 }
1117
1118 template <class Range, class OutputIt>
1119 auto reverse_copy (Range&& rng, OutputIt&& it) -> enable_if_t<
1120  is_range<Range>::value,
1122 > {
1123  auto range = make_range(::core::forward<Range>(rng));
1124  static constexpr auto is_bidir = decltype(range)::is_bidirectional;
1125  static_assert(is_bidir, "reverse_copy requires BidirectionalIterators");
1127  ::std::begin(range),
1128  ::std::end(range),
1129  ::core::forward<OutputIt>(it)
1130  );
1131 }
1132
1133 template <class Range, class ForwardIt>
1134 auto rotate (Range&& rng, ForwardIt&& it) -> enable_if_t<
1135  is_range<Range>::value
1136 > {
1137  auto range = make_range(::core::forward<Range>(rng));
1138  static constexpr auto is_forward = decltype(range)::is_forward;
1139  static_assert(is_forward, "rotate requires ForwardIterators");
1140  ::std::rotate(
1141  ::std::begin(range),
1142  ::core::forward<ForwardIt>(it),
1143  ::std::end(range)
1144  );
1145 }
1146
1147 template <class Range, class ForwardIt, class OutputIt>
1148 auto rotate_copy (Range&& rng, ForwardIt&& it, OutputIt&& ot) -> enable_if_t<
1149  is_range<Range>::value,
1151 > {
1152  auto range = make_range(::core::forward<Range>(rng));
1153  static constexpr auto is_forward = decltype(range)::is_forward;
1154  static_assert(is_forward, "rotate_copy requires ForwardIterators");
1156  ::std::begin(range),
1157  ::core::forward<ForwardIt>(it),
1158  ::std::end(range),
1159  ::core::forward<OutputIt>(ot)
1160  );
1161 }
1162
1163 template <class Range, class URNG>
1164 auto shuffle (Range&& rng, URNG&& g) -> enable_if_t<
1165  is_range<Range>::value
1166 > {
1167  auto range = make_range(::core::forward<Range>(rng));
1168  static constexpr auto is_random = decltype(range)::is_random_access;
1169  static_assert(is_random, "shuffle requires RandomAccessIterators");
1171  ::std::begin(range),
1172  ::std::end(range),
1173  ::core::forward<URNG>(g)
1174  );
1175 }
1176
1177 template <class Range>
1178 auto unique (Range&& rng) -> enable_if_t<
1179  is_range<Range>::value,
1180  decltype(::std::begin(::core::forward<Range>(rng)))
1181 > {
1182  auto range = make_range(::core::forward<Range>(rng));
1183  static constexpr auto is_forward = decltype(range)::is_forward;
1184  static_assert(is_forward, "unique requires ForwardIterators");
1185  return ::std::unique(::std::begin(range), ::std::end(range));
1186 }
1187
1188 template <class Range, class BinaryPredicate>
1189 auto unique (Range&& rng, BinaryPredicate&& bp) -> enable_if_t<
1190  is_range<Range>::value,
1191  decltype(::std::begin(::core::forward<Range>(rng)))
1192 > {
1193  auto range = make_range(::core::forward<Range>(rng));
1194  static constexpr auto is_forward = decltype(range)::is_forward;
1195  static_assert(is_forward, "unique requires ForwardIterators");
1197  ::std::begin(range),
1198  ::std::end(range),
1199  ::core::forward<BinaryPredicate>(bp)
1200  );
1201 }
1202
1203 template <class Range, class OutputIt>
1204 auto unique_copy (Range&& rng, OutputIt&& it) -> enable_if_t<
1205  is_range<Range>::value,
1207 > {
1208  auto range = make_range(::core::forward<Range>(rng));
1209  static constexpr auto is_input = decltype(range)::is_input;
1210  static_assert(is_input, "unique_copy requires InputIterators");
1212  ::std::begin(range),
1213  ::std::end(range),
1214  ::core::forward<OutputIt>(it)
1215  );
1216 }
1217
1218 template <class Range, class OutputIt, class BinaryPred>
1219 auto unique_copy (Range&& rng, OutputIt&& it, BinaryPred&& bp) -> enable_if_t<
1220  is_range<Range>::value,
1222 > {
1223  auto range = make_range(::core::forward<Range>(rng));
1224  static constexpr auto is_input = decltype(range)::is_input;
1225  static_assert(is_input, "unique_copy requires InputIterators");
1227  ::std::begin(range),
1228  ::std::end(range),
1229  ::core::forward<OutputIt>(it),
1230  ::core::forward<BinaryPred>(bp)
1231  );
1232 }
1233
1234 /* partitioning operations */
1235 template <class Range, class UnaryPredicate>
1236 auto is_partitioned (Range&& rng, UnaryPredicate&& up) -> enable_if_t<
1237  is_range<Range>::value,
1238  bool
1239 > {
1240  auto range = make_range(::core::forward<Range>(rng));
1241  static constexpr auto is_input = decltype(range)::is_input;
1242  static_assert(is_input, "is_partitioned requires InputIterators");
1244  ::std::begin(range),
1245  ::std::end(range),
1246  ::core::forward<UnaryPredicate>(up)
1247  );
1248 }
1249
1250 template <class Range, class UnaryPredicate>
1251 auto partition (Range&& rng, UnaryPredicate&& up) -> enable_if_t<
1252  is_range<Range>::value,
1253  decltype(::std::begin(::core::forward<Range>(rng)))
1254 > {
1255  auto range = make_range(::core::forward<Range>(rng));
1256  static constexpr auto is_forward = decltype(range)::is_forward;
1257  static_assert(is_forward, "partition requires ForwardIterators");
1259  ::std::begin(range),
1260  ::std::end(range),
1261  ::core::forward<UnaryPredicate>(up)
1262  );
1263 }
1264
1265 template <class Range, class OutputTrue, class OutputFalse, class UnaryPred>
1267  Range&& rng,
1268  OutputTrue&& ot,
1269  OutputFalse&& of,
1270  UnaryPred&& up
1271 ) -> enable_if_t<
1272  is_range<Range>::value,
1273  ::std::pair<decay_t<OutputTrue>, decay_t<OutputFalse>>
1274 > {
1275  auto range = make_range(::core::forward<Range>(rng));
1276  static constexpr auto is_input = decltype(range)::is_input;
1277  static_assert(is_input, "partition_copy requires InputIterators");
1279  ::std::begin(range),
1280  ::std::end(range),
1281  ::core::forward<OutputTrue>(ot),
1282  ::core::forward<OutputFalse>(of),
1283  ::core::forward<UnaryPred>(up)
1284  );
1285 }
1286
1287 template <class Range, class UnaryPredicate>
1288 auto stable_partition (Range&& rng, UnaryPredicate&& up) -> enable_if_t<
1289  is_range<Range>::value,
1290  decltype(::std::begin(::core::forward<Range>(rng)))
1291 > {
1292  auto range = make_range(::core::forward<Range>(rng));
1293  static constexpr auto is_bidir = decltype(range)::is_bidirectional;
1294  static_assert(is_bidir, "stable_partition requires BidirectionalIterators");
1296  ::std::begin(range),
1297  ::std::end(range),
1298  ::core::forward<UnaryPredicate>(up)
1299  );
1300 }
1301
1302 template <class Range, class UnaryPredicate>
1303 auto partition_point (Range&& rng, UnaryPredicate&& up) -> enable_if_t<
1304  is_range<Range>::value,
1305  decltype(::std::begin(::core::forward<Range>(rng)))
1306 > {
1307  auto range = make_range(::core::forward<Range>(rng));
1308  static constexpr auto is_forward = decltype(range)::is_forward;
1309  static_assert(is_forward, "partition_point requires ForwardIterators");
1311  ::std::begin(range),
1312  ::std::end(range),
1313  ::core::forward<UnaryPredicate>(up)
1314  );
1315 }
1316
1317 /* sorting operations */
1318
1319 template <class Range>
1321  auto range = make_range(::core::forward<Range>(rng));
1322  static constexpr auto is_forward = decltype(range)::is_forward;
1323  static_assert(is_forward, "is_sorted requires ForwardIterators");
1324  return ::std::is_sorted(::std::begin(range), ::std::end(range));
1325 }
1326
1327 template <class Range, class Compare>
1328 auto is_sorted (Range&& rng, Compare&& compare) -> enable_if_t<
1329  is_range<Range>::value,
1330  bool
1331 > {
1332  auto range = make_range(::core::forward<Range>(rng));
1333  static constexpr auto is_forward = decltype(range)::is_forward;
1334  static_assert(is_forward, "is_sorted requires ForwardIterators");
1336  ::std::begin(range),
1337  ::std::end(range),
1338  ::core::forward<Compare>(compare)
1339  );
1340 }
1341
1342 template <class Range>
1344  is_range<Range>::value,
1345  decltype(::std::begin(::core::forward<Range>(rng)))
1346 > {
1347  auto range = make_range(::core::forward<Range>(rng));
1348  static constexpr auto is_forward = decltype(range)::is_forward;
1349  static_assert(is_forward, "is_sorted_until requires ForwardIterators");
1350  return ::std::is_sorted_until(::std::begin(range), ::std::end(range));
1351 }
1352
1353 template <class Range, class Compare>
1354 auto is_sorted_until (Range&& rng, Compare&& compare) -> enable_if_t<
1355  is_range<Range>::value,
1356  decltype(::std::begin(::core::forward<Range>(rng)))
1357 > {
1358  auto range = make_range(::core::forward<Range>(rng));
1359  static constexpr auto is_forward = decltype(range)::is_forward;
1360  static_assert(is_forward, "is_sorted_until requires ForwardIterators");
1362  ::std::begin(range),
1363  ::std::end(range),
1364  ::core::forward<Compare>(compare)
1365  );
1366 }
1367
1368 template <class Range>
1370  auto range = make_range(::core::forward<Range>(rng));
1371  static constexpr auto is_random = decltype(range)::is_random_access;
1372  static_assert(is_random, "sort requires RandomAccessIterators");
1373  return ::std::sort(::std::begin(range), ::std::end(range));
1374 }
1375
1376 template <class Range, class Compare>
1377 auto sort (Range&& rng, Compare&& cmp) -> enable_if_t<is_range<Range>::value> {
1378  auto range = make_range(::core::forward<Range>(rng));
1379  static constexpr auto is_random = decltype(range)::is_random_access;
1380  static_assert(is_random, "sort requires RandomAccessIterators");
1382  ::std::begin(range),
1383  ::std::end(range),
1384  ::core::forward<Compare>(cmp)
1385  );
1386 }
1387
1388 template <class Range, class RandomIt>
1389 auto partial_sort (Range&& rng, RandomIt&& it) -> enable_if_t<
1390  is_range<Range>::value
1391 > {
1392  auto range = make_range(::core::forward<Range>(rng));
1393  static constexpr auto is_random = decltype(range)::is_random_access;
1394  static_assert(is_random, "partial_sort requires RandomAccessIterators");
1396  ::std::begin(range),
1397  ::core::forward<RandomIt>(it),
1398  ::std::end(range)
1399  );
1400 }
1401
1402 template <class Range, class RandomIt, class Compare>
1403 auto partial_sort (Range&& rng, RandomIt&& it, Compare&& cmp) -> enable_if_t<
1404  is_range<Range>::value
1405 > {
1406  auto range = make_range(::core::forward<Range>(rng));
1407  static constexpr auto is_random = decltype(range)::is_random_access;
1408  static_assert(is_random, "partial_sort requires RandomAccessIterators");
1410  ::std::begin(range),
1411  ::core::forward<RandomIt>(it),
1412  ::std::end(range),
1413  ::core::forward<Compare>(cmp)
1414  );
1415 }
1416
1417 template <class IRange, class RRange>
1418 auto partial_sort_copy (IRange&& irng, RRange&& rrng) -> meta::when<
1419  meta::all_of<meta::list<IRange, RRange>, is_range>(),
1420  decltype(::std::begin(::core::forward<RRange>(rrng)))
1421 > {
1422  auto irange = make_range(::core::forward<IRange>(irng));
1423  auto rrange = make_range(::core::forward<RRange>(rrng));
1424  static constexpr auto is_input = decltype(irange)::is_input;
1425  static constexpr auto is_random = decltype(rrange)::is_random_access;
1426  static_assert(is_input, "partial_sort_copy requires InputIterators");
1427  static_assert(is_random, "partial_sort_copy requires RandomAccessIterators");
1429  ::std::begin(irange),
1430  ::std::end(irange),
1431  ::std::begin(rrange),
1432  ::std::end(rrange)
1433  );
1434 }
1435
1436 template <class IRange, class RRange, class Compare>
1438  IRange&& irng,
1439  RRange&& rrng,
1440  Compare&& cmp
1441 ) -> meta::when<
1442  meta::all_of<meta::list<IRange, RRange>, is_range>(),
1443  decltype(::std::begin(::core::forward<RRange>(rrng)))
1444 > {
1445  auto irange = make_range(::core::forward<IRange>(irng));
1446  auto rrange = make_range(::core::forward<RRange>(rrng));
1447  static constexpr auto is_input = decltype(irange)::is_input;
1448  static constexpr auto is_random = decltype(rrange)::is_random_access;
1449  static_assert(is_input, "partial_sort_copy requires InputIterators");
1450  static_assert(is_random, "partial_sort_copy requires RandomAccessIterators");
1452  ::std::begin(irange),
1453  ::std::end(irange),
1454  ::std::begin(rrange),
1455  ::std::end(rrange),
1456  ::core::forward<Compare>(cmp)
1457  );
1458 }
1459
1460 template <class Range>
1462  auto range = make_range(::core::forward<Range>(rng));
1463  static constexpr auto is_random = decltype(range)::is_random_access;
1464  static_assert(is_random, "stable_sort requires RandomAccessIterators");
1465  return ::std::stable_sort(::std::begin(range), ::std::end(range));
1466 }
1467
1468 template <class Range, class Compare>
1469 auto stable_sort (Range&& rng, Compare&& cmp) -> enable_if_t<
1470  is_range<Range>::value
1471 > {
1472  auto range = make_range(::core::forward<Range>(rng));
1473  static constexpr auto is_random = decltype(range)::is_random_access;
1474  static_assert(is_random, "stable_sort requires RandomAccessIterators");
1476  ::std::begin(range),
1477  ::std::end(range),
1478  ::core::forward<Compare>(cmp)
1479  );
1480 }
1481
1482 template <class Range, class RandomIt>
1483 auto nth_element (Range&& rng, RandomIt&& it) -> enable_if_t<
1484  is_range<Range>::value
1485 > {
1486  auto range = make_range(::core::forward<Range>(rng));
1487  static constexpr auto is_random = decltype(range)::is_random_access;
1488  static_assert(is_random, "nth_element requires RandomAccessIterators");
1490  ::std::begin(range),
1491  ::core::forward<RandomIt>(it),
1492  ::std::end(range)
1493  );
1494 }
1495
1496 template <class Range, class RandomIt, class Compare>
1497 auto nth_element (Range&& rng, RandomIt&& it, Compare&& cmp) -> enable_if_t<
1498  is_range<Range>::value
1499 > {
1500  auto range = make_range(::core::forward<Range>(rng));
1501  static constexpr auto is_random = decltype(range)::is_random_access;
1502  static_assert(is_random, "nth_element requires RandomAccessIterators");
1504  ::std::begin(range),
1505  ::core::forward<RandomIt>(it),
1506  ::std::end(range),
1507  ::core::forward<Compare>(cmp)
1508  );
1509 }
1510
1511 /* binary search operations (on sorted ranges) */
1512 template <class Range, class T>
1513 auto lower_bound (Range&& rng, T const& value) -> enable_if_t<
1514  is_range<Range>::value,
1515  decltype(::std::begin(::core::forward<Range>(rng)))
1516 > {
1517  auto range = make_range(::core::forward<Range>(rng));
1518  static constexpr auto is_forward = decltype(range)::is_forward;
1519  static_assert(is_forward, "lower_bound requires ForwardIterators");
1520  return ::std::lower_bound(::std::begin(range), ::std::end(range), value);
1521 }
1522
1523 template <class Range, class T, class Compare>
1524 auto lower_bound (Range&& rng, T const& value, Compare&& cmp) -> enable_if_t<
1525  is_range<Range>::value,
1526  decltype(::std::begin(::core::forward<Range>(rng)))
1527 > {
1528  auto range = make_range(::core::forward<Range>(rng));
1529  static constexpr auto is_forward = decltype(range)::is_forward;
1530  static_assert(is_forward, "lower_bound requires ForwardIterators");
1532  ::std::begin(range),
1533  ::std::end(range),
1534  value,
1535  ::core::forward<Compare>(cmp)
1536  );
1537 }
1538
1539 template <class Range, class T>
1540 auto upper_bound (Range&& rng, T const& value) -> enable_if_t<
1541  is_range<Range>::value,
1542  decltype(::std::begin(::core::forward<Range>(rng)))
1543 > {
1544  auto range = make_range(::core::forward<Range>(rng));
1545  static constexpr auto is_forward = decltype(range)::is_forward;
1546  static_assert(is_forward, "upper_bound requires ForwardIterators");
1547  return ::std::upper_bound(::std::begin(range), ::std::end(range), value);
1548 }
1549
1550 template <class Range, class T, class Compare>
1551 auto upper_bound (Range&& rng, T const& value, Compare&& cmp) -> enable_if_t<
1552  is_range<Range>::value,
1553  decltype(::std::begin(::core::forward<Range>(rng)))
1554 > {
1555  auto range = make_range(::core::forward<Range>(rng));
1556  static constexpr auto is_forward = decltype(range)::is_forward;
1557  static_assert(is_forward, "upper_bound requires ForwardIterators");
1559  ::std::begin(range),
1560  ::std::end(range),
1561  value,
1562  ::core::forward<Compare>(cmp)
1563  );
1564 }
1565
1566 template <class Range, class T>
1567 auto binary_search (Range&& rng, T const& value) -> enable_if_t<
1568  is_range<Range>::value,
1569  bool
1570 > {
1571  auto range = make_range(::core::forward<Range>(rng));
1572  static constexpr auto is_forward = decltype(range)::is_forward;
1573  static_assert(is_forward, "binary_search requires ForwardIterators");
1574  return ::std::binary_search(::std::begin(range), ::std::end(range), value);
1575 }
1576
1577 template <class Range, class T, class Compare>
1578 auto binary_search (Range&& rng, T const& value, Compare&& cmp) -> enable_if_t<
1579  is_range<Range>::value,
1580  bool
1581 > {
1582  auto range = make_range(::core::forward<Range>(rng));
1583  static constexpr auto is_forward = decltype(range)::is_forward;
1584  static_assert(is_forward, "binary_search requires ForwardIterators");
1586  ::std::begin(range),
1587  ::std::end(range),
1588  value,
1589  ::core::forward<Compare>(cmp)
1590  );
1591 }
1592
1593 template <class Range, class T>
1594 auto equal_range (Range&& rng, T const& value) -> enable_if_t<
1595  is_range<Range>::value,
1597 > {
1598  auto range = make_range(::core::forward<Range>(rng));
1599  static constexpr auto is_forward = decltype(range)::is_forward;
1600  static_assert(is_forward, "equal_range requires ForwardIterators");
1601  return ::std::equal_range(::std::begin(range), ::std::end(range), value);
1602 }
1603
1604 template <class Range, class T, class Compare>
1605 auto equal_range (Range&& rng, T const& value, Compare&& cmp) -> enable_if_t<
1606  is_range<Range>::value,
1608 > {
1609  auto range = make_range(::core::forward<Range>(rng));
1610  static constexpr auto is_forward = decltype(range)::is_forward;
1611  static_assert(is_forward, "equal_range requires ForwardIterators");
1613  ::std::begin(range),
1614  ::std::end(range),
1615  value,
1616  ::core::forward<Compare>(cmp)
1617  );
1618 }
1619
1620 /* set operations (on sorted ranges) */
1621 template <class Range1, class Range2, class OutputIt>
1622 auto merge (Range1&& rng1, Range2&& rng2, OutputIt&& it) -> meta::when<
1623  meta::all_of<meta::list<Range1, Range2>, is_range>(),
1625 > {
1626  auto range1 = make_range(::core::forward<Range1>(rng1));
1627  auto range2 = make_range(::core::forward<Range2>(rng2));
1628  static constexpr auto is_input1 = decltype(range1)::is_input;
1629  static constexpr auto is_input2 = decltype(range2)::is_input;
1630  static_assert(is_input1, "merge requires InputIterators");
1631  static_assert(is_input2, "merge requires InputIterators");
1633  ::std::begin(range1),
1634  ::std::end(range1),
1635  ::std::begin(range2),
1636  ::std::end(range2),
1637  ::core::forward<OutputIt>(it)
1638  );
1639 }
1640
1641 template <class Range1, class Range2, class OutputIt, class Compare>
1642 auto merge (
1643  Range1&& rng1,
1644  Range2&& rng2,
1645  OutputIt&& it,
1646  Compare&& cmp
1647 ) -> enable_if_t<
1648  meta::all_of<meta::list<Range1, Range2>, is_range>(),
1650 > {
1651  auto range1 = make_range(::core::forward<Range1>(rng1));
1652  auto range2 = make_range(::core::forward<Range2>(rng2));
1653  static constexpr auto is_input1 = decltype(range1)::is_input;
1654  static constexpr auto is_input2 = decltype(range2)::is_input;
1655  static_assert(is_input1, "merge requires InputIterators");
1656  static_assert(is_input2, "merge requires InputIterators");
1658  ::std::begin(range1),
1659  ::std::end(range1),
1660  ::std::begin(range2),
1661  ::std::end(range2),
1662  ::core::forward<OutputIt>(it),
1663  ::core::forward<Compare>(cmp)
1664  );
1665 }
1666
1667 template <class Range, class BidirIt>
1668 auto inplace_merge (Range&& rng, BidirIt&& it) -> meta::when<
1669  is_range<Range>::value
1670 > {
1671  auto range = make_range(::core::forward<Range>(rng));
1672  static constexpr auto is_bidir = decltype(range)::is_bidirectional;
1673  static_assert(is_bidir, "inplace_merge requires BidirectionalIterators");
1675  ::std::begin(range),
1676  ::core::forward<BidirIt>(it),
1677  ::std::end(range)
1678  );
1679 }
1680
1681 template <class Range, class BidirIt, class Compare>
1682 auto inplace_merge (Range&& rng, BidirIt&& it, Compare&& cmp) -> meta::when<
1683  is_range<Range>::value
1684 > {
1685  auto range = make_range(::core::forward<Range>(rng));
1686  static constexpr auto is_bidir = decltype(range)::is_bidirectional;
1687  static_assert(is_bidir, "inplace_merge requires BidirectionalIterators");
1689  ::std::begin(range),
1690  ::core::forward<BidirIt>(it),
1691  ::std::end(range),
1692  ::core::forward<Compare>(cmp)
1693  );
1694 }
1695
1696 template <class Range1, class Range2>
1697 auto includes (Range1&& rng1, Range2&& rng2) -> meta::when<
1698  meta::all_of<meta::list<Range1, Range2>, is_range>(),
1699  bool
1700 > {
1701  auto range1 = make_range(::core::forward<Range1>(rng1));
1702  auto range2 = make_range(::core::forward<Range2>(rng2));
1703  static constexpr auto is_input1 = decltype(range1)::is_input;
1704  static constexpr auto is_input2 = decltype(range2)::is_input;
1705  static_assert(is_input1, "includes requires InputIterators");
1706  static_assert(is_input2, "includes requires InputIterators");
1708  ::std::begin(range1),
1709  ::std::end(range1),
1710  ::std::begin(range2),
1711  ::std::end(range2)
1712  );
1713 }
1714
1715 template <class Range1, class Range2, class Compare>
1716 auto includes (Range1&& rng1, Range2&& rng2, Compare&& cmp) -> meta::when<
1717  meta::all_of<meta::list<Range1, Range2>, is_range>(),
1718  bool
1719 > {
1720  auto range1 = make_range(::core::forward<Range1>(rng1));
1721  auto range2 = make_range(::core::forward<Range2>(rng2));
1722  static constexpr auto is_input1 = decltype(range1)::is_input;
1723  static constexpr auto is_input2 = decltype(range2)::is_input;
1724  static_assert(is_input1, "includes requires InputIterators");
1725  static_assert(is_input2, "includes requires InputIterators");
1727  ::std::begin(range1),
1728  ::std::end(range1),
1729  ::std::begin(range2),
1730  ::std::end(range2),
1731  ::core::forward<Compare>(cmp)
1732  );
1733 }
1734
1735 template <class Range1, class Range2, class OutputIt>
1736 auto set_difference (Range1&& rng1, Range2&& rng2, OutputIt&& it) -> meta::when<
1737  meta::all_of<meta::list<Range1, Range2>, is_range>(),
1739 > {
1740  auto range1 = make_range(::core::forward<Range1>(rng1));
1741  auto range2 = make_range(::core::forward<Range2>(rng2));
1742  static constexpr auto is_input1 = decltype(range1)::is_input;
1743  static constexpr auto is_input2 = decltype(range2)::is_input;
1744  static_assert(is_input1, "set_difference requires InputIterators");
1745  static_assert(is_input2, "set_difference requires InputIterators");
1747  ::std::begin(range1),
1748  ::std::end(range1),
1749  ::std::begin(range2),
1750  ::std::end(range2),
1751  ::core::forward<OutputIt>(it)
1752  );
1753 }
1754
1755 template <class Range1, class Range2, class OutputIt, class Compare>
1757  Range1&& rng1,
1758  Range2&& rng2,
1759  OutputIt&& it,
1760  Compare&& cmp
1761 ) -> meta::when<
1762  meta::all_of<meta::list<Range1, Range2>, is_range>(),
1764 > {
1765  auto range1 = make_range(::core::forward<Range1>(rng1));
1766  auto range2 = make_range(::core::forward<Range2>(rng2));
1767  static constexpr auto is_input1 = decltype(range1)::is_input;
1768  static constexpr auto is_input2 = decltype(range2)::is_input;
1769  static_assert(is_input1, "set_difference requires InputIterators");
1770  static_assert(is_input2, "set_difference requires InputIterators");
1772  ::std::begin(range1),
1773  ::std::end(range1),
1774  ::std::begin(range2),
1775  ::std::end(range2),
1776  ::core::forward<OutputIt>(it),
1777  ::core::forward<Compare>(cmp)
1778  );
1779 }
1780
1781 template <class Range1, class Range2, class OutputIt>
1782 auto set_intersection (Range1&& rng1, Range2&& rng2, OutputIt&& it) -> meta::when<
1783  meta::all_of<meta::list<Range1, Range2>, is_range>(),
1785 > {
1786  auto range1 = make_range(::core::forward<Range1>(rng1));
1787  auto range2 = make_range(::core::forward<Range2>(rng2));
1788  static constexpr auto is_input1 = decltype(range1)::is_input;
1789  static constexpr auto is_input2 = decltype(range2)::is_input;
1790  static_assert(is_input1, "set_intersection requires InputIterators");
1791  static_assert(is_input2, "set_intersection requires InputIterators");
1793  ::std::begin(range1),
1794  ::std::end(range1),
1795  ::std::begin(range2),
1796  ::std::end(range2),
1797  ::core::forward<OutputIt>(it)
1798  );
1799 }
1800
1801 template <class Range1, class Range2, class OutputIt, class Compare>
1803  Range1&& rng1,
1804  Range2&& rng2,
1805  OutputIt&& it,
1806  Compare&& cmp
1807 ) -> enable_if_t<
1808  meta::all_of<meta::list<Range1, Range2>, is_range>(),
1810 > {
1811  auto range1 = make_range(::core::forward<Range1>(rng1));
1812  auto range2 = make_range(::core::forward<Range2>(rng2));
1813  static constexpr auto is_input1 = decltype(range1)::is_input;
1814  static constexpr auto is_input2 = decltype(range2)::is_input;
1815  static_assert(is_input1, "set_intersection requires InputIterators");
1816  static_assert(is_input2, "set_intersection requires InputIterators");
1818  ::std::begin(range1),
1819  ::std::end(range1),
1820  ::std::begin(range2),
1821  ::std::end(range2),
1822  ::core::forward<OutputIt>(it),
1823  ::core::forward<Compare>(cmp)
1824  );
1825 }
1826
1827 template <class Range1, class Range2, class OutputIt>
1828 auto set_symmetric_difference (Range1&& rng1, Range2&& rng2, OutputIt&& it) -> enable_if_t<
1829  meta::all_of<meta::list<Range1, Range2>, is_range>(),
1831 > {
1832  auto range1 = make_range(::core::forward<Range1>(rng1));
1833  auto range2 = make_range(::core::forward<Range2>(rng2));
1834  static constexpr auto is_input1 = decltype(range1)::is_input;
1835  static constexpr auto is_input2 = decltype(range2)::is_input;
1836  static_assert(is_input1, "set_symmetric_difference requires InputIterators");
1837  static_assert(is_input2, "set_symmetric_difference requires InputIterators");
1839  ::std::begin(range1),
1840  ::std::end(range1),
1841  ::std::begin(range2),
1842  ::std::end(range2),
1843  ::core::forward<OutputIt>(it)
1844  );
1845 }
1846
1847 template <class Range1, class Range2, class OutputIt, class Compare>
1849  Range1&& rng1,
1850  Range2&& rng2,
1851  OutputIt&& it,
1852  Compare&& cmp
1853 ) -> enable_if_t<
1854  meta::all_of<meta::list<Range1, Range2>, is_range>(),
1856 > {
1857  auto range1 = make_range(::core::forward<Range1>(rng1));
1858  auto range2 = make_range(::core::forward<Range2>(rng2));
1859  static constexpr auto is_input1 = decltype(range1)::is_input;
1860  static constexpr auto is_input2 = decltype(range2)::is_input;
1861  static_assert(is_input1, "set_symmetric_difference requires InputIterators");
1862  static_assert(is_input2, "set_symmetric_difference requires InputIterators");
1864  ::std::begin(range1),
1865  ::std::end(range1),
1866  ::std::begin(range2),
1867  ::std::end(range2),
1868  ::core::forward<OutputIt>(it),
1869  ::core::forward<Compare>(cmp)
1870  );
1871 }
1872
1873 template <class Range1, class Range2, class OutputIt>
1874 auto set_union (Range1&& rng1, Range2&& rng2, OutputIt&& it) -> enable_if_t<
1875  meta::all_of<meta::list<Range1, Range2>, is_range>(),
1877 > {
1878  auto range1 = make_range(::core::forward<Range1>(rng1));
1879  auto range2 = make_range(::core::forward<Range2>(rng2));
1880  static constexpr auto is_input1 = decltype(range1)::is_input;
1881  static constexpr auto is_input2 = decltype(range2)::is_input;
1882  static_assert(is_input1, "set_union requires InputIterators");
1883  static_assert(is_input2, "set_union requires InputIterators");
1885  ::std::begin(range1),
1886  ::std::end(range1),
1887  ::std::begin(range2),
1888  ::std::end(range2),
1889  ::core::forward<OutputIt>(it)
1890  );
1891 }
1892
1893 template <class Range1, class Range2, class OutputIt, class Compare>
1895  Range1&& rng1,
1896  Range2&& rng2,
1897  OutputIt&& it,
1898  Compare&& cmp
1899 ) -> enable_if_t<
1900  meta::all_of<meta::list<Range1, Range2>, is_range>(),
1902 > {
1903  auto range1 = make_range(::core::forward<Range1>(rng1));
1904  auto range2 = make_range(::core::forward<Range2>(rng2));
1905  static constexpr auto is_input1 = decltype(range1)::is_input;
1906  static constexpr auto is_input2 = decltype(range2)::is_input;
1907  static_assert(is_input1, "set_union requires InputIterators");
1908  static_assert(is_input2, "set_union requires InputIterators");
1910  ::std::begin(range1),
1911  ::std::end(range1),
1912  ::std::begin(range2),
1913  ::std::end(range2),
1914  ::core::forward<OutputIt>(it),
1915  ::core::forward<Compare>(cmp)
1916  );
1917 }
1918
1919 /* heap operations */
1920 template <class Range>
1922  auto range = make_range(::core::forward<Range>(rng));
1923  static constexpr auto is_random = decltype(range)::is_random_access;
1924  static_assert(is_random, "is_heap requires RandomAccessIterators");
1925  return ::std::is_heap(::std::begin(range), ::std::end(range));
1926 }
1927
1928 template <class Range, class Compare>
1929 auto is_heap (Range&& rng, Compare&& cmp) -> enable_if_t<
1930  is_range<Range>::value,
1931  bool
1932 > {
1933  auto range = make_range(::core::forward<Range>(rng));
1934  static constexpr auto is_random = decltype(range)::is_random_access;
1935  static_assert(is_random, "is_heap requires RandomAccessIterators");
1937  ::std::begin(range),
1938  ::std::end(range),
1939  ::core::forward<Compare>(cmp)
1940  );
1941 }
1942
1943 template <class Range>
1945  is_range<Range>::value,
1946  decltype(::std::begin(::core::forward<Range>(rng)))
1947 > {
1948  auto range = make_range(::core::forward<Range>(rng));
1949  static constexpr auto is_random = decltype(range)::is_random_access;
1950  static_assert(is_random, "is_heap_until requires RandomAccessIterators");
1951  return ::std::is_heap_until(::std::begin(range), ::std::end(range));
1952 }
1953
1954 template <class Range, class Compare>
1955 auto is_heap_until (Range&& rng, Compare&& cmp) -> enable_if_t<
1956  is_range<Range>::value,
1957  decltype(::std::begin(::core::forward<Range>(rng)))
1958 > {
1959  auto range = make_range(::core::forward<Range>(rng));
1960  static constexpr auto is_random = decltype(range)::is_random_access;
1961  static_assert(is_random, "is_heap_until requires RandomAccessIterators");
1963  ::std::begin(range),
1964  ::std::end(range),
1965  ::core::forward<Compare>(cmp)
1966  );
1967 }
1968
1969 template <class Range>
1971  auto range = make_range(::core::forward<Range>(rng));
1972  static constexpr auto is_random = decltype(range)::is_random_access;
1973  static_assert(is_random, "make_heap requires RandomAccessIterators");
1974  return ::std::make_heap(::std::begin(range), ::std::end(range));
1975 }
1976
1977 template <class Range, class Compare>
1978 auto make_heap (Range&& rng, Compare&& cmp) -> enable_if_t<
1979  is_range<Range>::value
1980 > {
1981  auto range = make_range(::core::forward<Range>(rng));
1982  static constexpr auto is_random = decltype(range)::is_random_access;
1983  static_assert(is_random, "make_heap requires RandomAccessIterators");
1985  ::std::begin(range),
1986  ::std::end(range),
1987  ::core::forward<Compare>(cmp)
1988  );
1989 }
1990
1991 template <class Range>
1993  auto range = make_range(::core::forward<Range>(rng));
1994  static constexpr auto is_random = decltype(range)::is_random_access;
1995  static_assert(is_random, "push_heap requires RandomAccessIterators");
1996  return ::std::push_heap(::std::begin(range), ::std::end(range));
1997 }
1998
1999 template <class Range, class Compare>
2000 auto push_heap (Range&& rng, Compare&& cmp) -> enable_if_t<
2001  is_range<Range>::value
2002 > {
2003  auto range = make_range(::core::forward<Range>(rng));
2004  static constexpr auto is_random = decltype(range)::is_random_access;
2005  static_assert(is_random, "push_heap requires RandomAccessIterators");
2007  ::std::begin(range),
2008  ::std::end(range),
2009  ::core::forward<Compare>(cmp)
2010  );
2011 }
2012
2013 template <class Range>
2015  auto range = make_range(::core::forward<Range>(rng));
2016  static constexpr auto is_random = decltype(range)::is_random_access;
2017  static_assert(is_random, "pop_heap requires RandomAccessIterators");
2018  return ::std::pop_heap(::std::begin(range), ::std::end(range));
2019 }
2020
2021 template <class Range, class Compare>
2022 auto pop_heap (Range&& rng, Compare&& cmp) -> enable_if_t<
2023  is_range<Range>::value
2024 > {
2025  auto range = make_range(::core::forward<Range>(rng));
2026  static constexpr auto is_random = decltype(range)::is_random_access;
2027  static_assert(is_random, "pop_heap requires RandomAccessIterators");
2029  ::std::begin(range),
2030  ::std::end(range),
2031  ::core::forward<Compare>(cmp)
2032  );
2033 }
2034
2035 template <class Range>
2037  auto range = make_range(::core::forward<Range>(rng));
2038  static constexpr auto is_random = decltype(range)::is_random_access;
2039  static_assert(is_random, "sort_heap requires RandomAccessIterators");
2040  return ::std::sort_heap(::std::begin(range), ::std::end(range));
2041 }
2042
2043 template <class Range, class Compare>
2044 auto sort_heap (Range&& rng, Compare&& cmp) -> enable_if_t<
2045  is_range<Range>::value
2046 > {
2047  auto range = make_range(::core::forward<Range>(rng));
2048  static constexpr auto is_random = decltype(range)::is_random_access;
2049  static_assert(is_random, "sort_heap requires RandomAccessIterators");
2051  ::std::begin(range),
2052  ::std::end(range),
2053  ::core::forward<Compare>(cmp)
2054  );
2055 }
2056
2057 /* min/max operations */
2058 template <class Range>
2060  is_range<Range>::value,
2061  decltype(::std::begin(::core::forward<Range>(rng)))
2062 > {
2063  auto range = make_range(::core::forward<Range>(rng));
2064  static constexpr auto is_forward = decltype(range)::is_forward;
2065  static_assert(is_forward, "max_element requires ForwardIterators");
2066  return ::std::max_element(::std::begin(range), ::std::end(range));
2067 }
2068
2069 template <class Range, class Compare>
2070 auto max_element (Range&& rng, Compare&& cmp) -> enable_if_t<
2071  is_range<Range>::value,
2072  decltype(::std::begin(::core::forward<Range>(rng)))
2073 > {
2074  auto range = make_range(::core::forward<Range>(rng));
2075  static constexpr auto is_forward = decltype(range)::is_forward;
2076  static_assert(is_forward, "max_element requires ForwardIterators");
2078  ::std::begin(range),
2079  ::std::end(range),
2080  ::core::forward<Compare>(cmp)
2081  );
2082 }
2083
2084 template <class Range>
2086  is_range<Range>::value,
2087  decltype(::std::begin(::core::forward<Range>(rng)))
2088 > {
2089  auto range = make_range(::core::forward<Range>(rng));
2090  static constexpr auto is_forward = decltype(range)::is_forward;
2091  static_assert(is_forward, "min_element requires ForwardIterators");
2092  return ::std::min_element(::std::begin(range), ::std::end(range));
2093 }
2094
2095 template <class Range, class Compare>
2096 auto min_element (Range&& rng, Compare&& cmp) -> enable_if_t<
2097  is_range<Range>::value,
2098  decltype(::std::begin(::core::forward<Range>(rng)))
2099 > {
2100  auto range = make_range(::core::forward<Range>(rng));
2101  static constexpr auto is_forward = decltype(range)::is_forward;
2102  static_assert(is_forward, "min_element requires ForwardIterators");
2104  ::std::begin(range),
2105  ::std::end(range),
2106  ::core::forward<Compare>(cmp)
2107  );
2108 }
2109
2110 template <class Range>
2112  is_range<Range>::value,
2113  ::std::pair<
2114  decltype(::std::begin(::core::forward<Range>(rng))),
2115  decltype(::std::end(::core::forward<Range>(rng)))
2116  >
2117 > {
2118  auto range = make_range(::core::forward<Range>(rng));
2119  static constexpr auto is_forward = decltype(range)::is_forward;
2120  static_assert(is_forward, "minmax_element requires ForwardIterators");
2121  return ::std::minmax_element(::std::begin(range), ::std::end(range));
2122 }
2123
2124 template <class Range, class Compare>
2125 auto minmax_element (Range&& rng, Compare&& cmp) -> enable_if_t<
2126  is_range<Range>::value,
2127  ::std::pair<
2129  range<decltype(::std::end(::core::forward<Range>(rng)))>
2130  >
2131 > {
2132  auto range = make_range(::core::forward<Range>(rng));
2133  static constexpr auto is_forward = decltype(range)::is_forward;
2134  static_assert(is_forward, "minmax_element requires ForwardIterators");
2136  ::std::begin(range),
2137  ::std::end(range),
2138  ::core::forward<Compare>(cmp)
2139  );
2140 }
2141
2142 template <class Range1, class Range2>
2143 auto lexicographical_compare (Range1&& rng1, Range2&& rng2) -> enable_if_t<
2144  meta::all_of<meta::list<Range1, Range2>, is_range>(),
2145  bool
2146 > {
2147  auto range1 = make_range(::core::forward<Range1>(rng1));
2148  auto range2 = make_range(::core::forward<Range2>(rng2));
2149  static constexpr auto is_input1 = decltype(range1)::is_input;
2150  static constexpr auto is_input2 = decltype(range2)::is_input;
2151  static_assert(is_input1, "lexicographical_compare requires InputIterators");
2152  static_assert(is_input2, "lexicographical_compare requires InputIterators");
2154  ::std::begin(range1),
2155  ::std::end(range1),
2156  ::std::begin(range2),
2157  ::std::end(range2)
2158  );
2159 }
2160
2161 template <class Range1, class Range2, class Compare>
2163  Range1&& rng1,
2164  Range2&& rng2,
2165  Compare&& cmp
2166 ) -> enable_if_t<
2167  meta::all_of<meta::list<Range1, Range2>, is_range>(),
2168  bool
2169 > {
2170  auto range1 = make_range(::core::forward<Range1>(rng1));
2171  auto range2 = make_range(::core::forward<Range2>(rng2));
2172  static constexpr auto is_input1 = decltype(range1)::is_input;
2173  static constexpr auto is_input2 = decltype(range2)::is_input;
2174  static_assert(is_input1, "lexicographical_compare requires InputIterators");
2175  static_assert(is_input2, "lexicographical_compare requires InputIterators");
2177  ::std::begin(range1),
2178  ::std::end(range1),
2179  ::std::begin(range2),
2180  ::std::end(range2),
2181  ::core::forward<Compare>(cmp)
2182  );
2183 }
2184
2185 template <class Range1, class Range2>
2186 auto is_permutation (Range1&& rng1, Range2&& rng2) -> enable_if_t<
2187  meta::all_of<meta::list<Range1, Range2>, is_range>(),
2188  bool
2189 > {
2190  auto range1 = make_range(::core::forward<Range1>(rng1));
2191  auto range2 = make_range(::core::forward<Range2>(rng2));
2192  static constexpr auto is_forward1 = decltype(range1)::is_forward;
2193  static constexpr auto is_forward2 = decltype(range2)::is_forward;
2194  static_assert(is_forward1, "is_permutation requires ForwardIterators");
2195  static_assert(is_forward2, "is_permutation requires ForwardIterators");
2197  ::std::begin(range1),
2198  ::std::end(range1),
2199  ::std::begin(range2)
2200  );
2201 }
2202
2203 template <class Range1, class Range2, class BinaryPredicate>
2205  Range1&& rng1,
2206  Range2&& rng2,
2207  BinaryPredicate&& bp
2208 ) -> meta::when<
2209  meta::all_of<meta::list<Range1, Range2>, is_range>(),
2210  bool
2211 > {
2212  auto range1 = make_range(::core::forward<Range1>(rng1));
2213  auto range2 = make_range(::core::forward<Range2>(rng2));
2214  static constexpr auto is_forward1 = decltype(range1)::is_forward;
2215  static constexpr auto is_forward2 = decltype(range2)::is_forward;
2216  static_assert(is_forward1, "is_permutation requires ForwardIterators");
2217  static_assert(is_forward2, "is_permutation requires ForwardIterators");
2219  ::std::begin(range1),
2220  ::std::end(range1),
2221  ::std::begin(range2),
2222  ::core::forward<BinaryPredicate>(bp)
2223  );
2224 }
2225
2226 template <class Range>
2228  is_range<Range>::value,
2229  bool
2230 > {
2231  auto range = make_range(::core::forward<Range>(rng));
2232  static constexpr auto is_bidir = decltype(range)::is_bidirectional;
2233  static_assert(is_bidir, "next_permutation requires BidirectionalIterators");
2234  return ::std::next_permutation(::std::begin(range), ::std::end(range));
2235 }
2236
2237 template <class Range, class Compare>
2238 auto next_permutation (Range&& rng, Compare&& cmp) -> enable_if_t<
2239  is_range<Range>::value,
2240  bool
2241 > {
2242  auto range = make_range(::core::forward<Range>(rng));
2243  static constexpr auto is_bidir = decltype(range)::is_bidirectional;
2244  static_assert(is_bidir, "next_permutation requires BidirectionalIterators");
2246  ::std::begin(range),
2247  ::std::end(range),
2248  ::core::forward<Compare>(cmp)
2249  );
2250 }
2251
2252 template <class Range>
2254  is_range<Range>::value,
2255  bool
2256 > {
2257  auto range = make_range(::core::forward<Range>(rng));
2258  static constexpr auto is_bidir = decltype(range)::is_bidirectional;
2259  static_assert(is_bidir, "prev_permutation requires BidirectionalIterators");
2260  return ::std::prev_permutation(::std::begin(range), ::std::end(range));
2261 }
2262
2263 template <class Range, class Compare>
2264 auto prev_permutation (Range&& rng, Compare&& cmp) -> enable_if_t<
2265  is_range<Range>::value,
2266  bool
2267 > {
2268  auto range = make_range(::core::forward<Range>(rng));
2269  static constexpr auto is_bidir = decltype(range)::is_bidirectional;
2270  static_assert(is_bidir, "prev_permutation requires BidirectionalIterators");
2272  ::std::begin(range),
2273  ::std::end(range),
2274  ::core::forward<Compare>(cmp)
2275  );
2276 }
2277
2278 }} /* namespace core::v2 */
2279
2280 #endif /* CORE_ALGORITHM_HPP */
bool empty() const
Definition: range.hpp:155
auto make_heap(Range &&rng, Compare &&cmp) -> enable_if_t< is_range< Range >::value >
Definition: algorithm.hpp:1978
auto is_sorted_until(Range &&rng) -> enable_if_t< is_range< Range >::value, decltype(::std::begin(::core::forward< Range >(rng))) >
Definition: algorithm.hpp:1343
auto replace(Range &&rng, T const &old, T const &value) -> enable_if_t< is_range< Range >::value >
Definition: algorithm.hpp:1022
auto adjacent_find(Range &&rng, BinaryPredicate &&bp) -> meta::when< is_range< Range >::value, decltype(::std::begin(::core::forward< Range >(rng))) >
Definition: algorithm.hpp:584
auto lexicographical_compare(Range1 &&rng1, Range2 &&rng2) -> enable_if_t< meta::all_of< meta::list< Range1, Range2 >, is_range >(), bool >
Definition: algorithm.hpp:2143
auto unique(Range &&rng) -> enable_if_t< is_range< Range >::value, decltype(::std::begin(::core::forward< Range >(rng))) >
Definition: algorithm.hpp:1178
auto rotate(Range &&rng, ForwardIt &&it) -> enable_if_t< is_range< Range >::value >
Definition: algorithm.hpp:1134
auto for_each(Range &&rng, UnaryFunction &&f) -> enable_if_t< is_range< Range >::value, decay_t< UnaryFunction > >
Definition: algorithm.hpp:164
auto merge(Range1 &&rng1, Range2 &&rng2, OutputIt &&it, Compare &&cmp) -> enable_if_t< meta::all_of< meta::list< Range1, Range2 >, is_range >(), decay_t< OutputIt > >
Definition: algorithm.hpp:1642
iterator end() const
Definition: range.hpp:147
auto set_union(Range1 &&rng1, Range2 &&rng2, OutputIt &&it, Compare &&cmp) -> enable_if_t< meta::all_of< meta::list< Range1, Range2 >, is_range >(), decay_t< OutputIt > >
Definition: algorithm.hpp:1894
auto all_of(Range &&rng, UnaryPredicate &&p) -> meta::when< is_range< Range >::value, bool >
Definition: algorithm.hpp:119
auto remove_copy(Range &&rng, OutputIt &&it, T const &value) -> enable_if_t< is_range< Range >::value, decay_t< OutputIt > >
Definition: algorithm.hpp:967
auto remove_if(Range &&rng, UnaryPredicate &&up) -> enable_if_t< is_range< Range >::value, decltype(::std::begin(::core::forward< Range >(rng))) >
Definition: algorithm.hpp:952
void pop_front(difference_type n)
Definition: range.hpp:246
auto prev_permutation(Range &&rng, Compare &&cmp) -> enable_if_t< is_range< Range >::value, bool >
Definition: algorithm.hpp:2264
::std::pair< InputIt1, InputIt2 > mismatch(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2, BinaryPredicate predicate)
Definition: algorithm.hpp:263
auto make_range(T *ptr, ::std::size_t n) -> range< T *>
Definition: range.hpp:288
auto stable_sort(Range &&rng, Compare &&cmp) -> enable_if_t< is_range< Range >::value >
Definition: algorithm.hpp:1469
auto stable_sort(Range &&rng) -> enable_if_t< is_range< Range >::value >
Definition: algorithm.hpp:1461
auto find_if(Range &&rng, UnaryPredicate &&p) -> enable_if_t< is_range< Range >::value, decltype(::std::begin(::core::forward< Range >(rng))) >
Definition: algorithm.hpp:461
auto replace_copy(Range &&rng, OutputIt &&it, T const &old, T const &value) -> enable_if_t< is_range< Range >::value, decay_t< OutputIt > >
Definition: algorithm.hpp:1052
Definition: algorithm.hpp:23
auto nth_element(Range &&rng, RandomIt &&it) -> enable_if_t< is_range< Range >::value >
Definition: algorithm.hpp:1483
auto unique_copy(Range &&rng, OutputIt &&it, BinaryPred &&bp) -> enable_if_t< is_range< Range >::value, decay_t< OutputIt > >
Definition: algorithm.hpp:1219
auto inplace_merge(Range &&rng, BidirIt &&it, Compare &&cmp) -> meta::when< is_range< Range >::value >
Definition: algorithm.hpp:1682
iterator begin() const
Definition: range.hpp:146
auto inplace_merge(Range &&rng, BidirIt &&it) -> meta::when< is_range< Range >::value >
Definition: algorithm.hpp:1668
auto search_n(Range &&rng, Size &&count, T const &value) -> enable_if_t< is_range< Range >::value, decltype(::std::begin(::core::forward< Range >(rng))) >
Definition: algorithm.hpp:638
auto invoke(Functor &&f, Args &&... args) -> enable_if_t< ::std::is_member_pointer< decay_t< Functor >>::value, result_of_t< Functor &&(Args &&...)> >
Definition: functional.hpp:80
constexpr auto abs_diff(T const &a, T const &b, Compare compare=Compare { }, Difference diff=Difference { }) -> decltype(compare(a, b) ? diff(b, a) :diff(a, b))
Definition: algorithm.hpp:108
auto is_heap(Range &&rng, Compare &&cmp) -> enable_if_t< is_range< Range >::value, bool >
Definition: algorithm.hpp:1929
auto find_if_not(Range &&rng, UnaryPredicate &&p) -> enable_if_t< is_range< Range >::value, decltype(::std::begin(::core::forward< Range >(rng))) >
Definition: algorithm.hpp:476
auto max_element(Range &&rng) -> enable_if_t< is_range< Range >::value, decltype(::std::begin(::core::forward< Range >(rng))) >
Definition: algorithm.hpp:2059
auto find_end(Range1 &&rng1, Range2 &&rng2) -> meta::when< meta::all_of< meta::list< Range1, Range2 >, is_range >(), decltype(::std::begin(::core::forward< Range1 >(rng1))) >
Definition: algorithm.hpp:491
auto move_backward(Range &&rng, BidirIt &&it) -> enable_if_t< is_range< Range >::value, decay_t< BidirIt > >
Definition: algorithm.hpp:751
auto any_of(Range &&rng, UnaryPredicate &&p) -> enable_if_t< is_range< Range >::value, bool >
Definition: algorithm.hpp:134
auto pop_heap(Range &&rng) -> enable_if_t< is_range< Range >::value >
Definition: algorithm.hpp:2014
auto adjacent_find(Range &&rng) -> meta::when< is_range< Range >::value, decltype(::std::begin(::core::forward< Range >(rng))) >
Definition: algorithm.hpp:573
auto search(Range1 &&rng1, Range2 &&rng2, BinaryPred &&bp) -> enable_if_t< meta::all_of< meta::list< Range1, Range2 >, is_range >(), decltype(::std::begin(::core::forward< Range1 >(rng1))) >
Definition: algorithm.hpp:618
auto sort(Range &&rng, Compare &&cmp) -> enable_if_t< is_range< Range >::value >
Definition: algorithm.hpp:1377
constexpr T const & max(T const &lhs, T const &rhs)
Definition: algorithm.hpp:79
auto max_element(Range &&rng, Compare &&cmp) -> enable_if_t< is_range< Range >::value, decltype(::std::begin(::core::forward< Range >(rng))) >
Definition: algorithm.hpp:2070
UnaryFunction for_each_if(Range &&r, UnaryFunction uf, UnaryPredicate up)
Definition: algorithm.hpp:179
auto sort_heap(Range &&rng, Compare &&cmp) -> enable_if_t< is_range< Range >::value >
Definition: algorithm.hpp:2044
auto fill(Range &&rng, T const &value) -> enable_if_t< is_range< Range >::value >
Definition: algorithm.hpp:766
auto find_first_of(IRange &&irng, FRange &&frng, BinaryPred &&bp) -> meta::when< meta::all_of< meta::list< IRange, FRange >, is_range >(), decltype(::std::begin(::core::forward< IRange >(irng))) >
Definition: algorithm.hpp:549
auto prev_permutation(Range &&rng) -> enable_if_t< is_range< Range >::value, bool >
Definition: algorithm.hpp:2253
RangeType< double > Range
3.0.0 TODO: break reverse-compatibility by changing RangeType to Range.
Definition: range.hpp:19
auto next_permutation(Range &&rng, Compare &&cmp) -> enable_if_t< is_range< Range >::value, bool >
Definition: algorithm.hpp:2238
auto includes(Range1 &&rng1, Range2 &&rng2, Compare &&cmp) -> meta::when< meta::all_of< meta::list< Range1, Range2 >, is_range >(), bool >
Definition: algorithm.hpp:1716
auto transform(Range &&rng, OutputIt &&it, UnaryOperation &&op) -> enable_if_t< is_range< Range >::value, decay_t< OutputIt > >
Definition: algorithm.hpp:776
auto replace_if(Range &&rng, UnaryPred &&up, T const &value) -> enable_if_t< is_range< Range >::value >
Definition: algorithm.hpp:1037
auto set_symmetric_difference(Range1 &&rng1, Range2 &&rng2, OutputIt &&it) -> enable_if_t< meta::all_of< meta::list< Range1, Range2 >, is_range >(), decay_t< OutputIt > >
Definition: algorithm.hpp:1828
bool equal(Range &&rng, InputIt &&it, BinaryPredicate &&bp)
Definition: algorithm.hpp:437
auto binary_search(Range &&rng, T const &value, Compare &&cmp) -> enable_if_t< is_range< Range >::value, bool >
Definition: algorithm.hpp:1578
auto min_element(Range &&rng) -> enable_if_t< is_range< Range >::value, decltype(::std::begin(::core::forward< Range >(rng))) >
Definition: algorithm.hpp:2085
auto reverse(Range &&rng) -> enable_if_t< is_range< Range >::value >
Definition: algorithm.hpp:1111
auto lower_bound(Range &&rng, T const &value, Compare &&cmp) -> enable_if_t< is_range< Range >::value, decltype(::std::begin(::core::forward< Range >(rng))) >
Definition: algorithm.hpp:1524
auto remove_erase(Range &&rng, T const &val) -> enable_if_t< is_range< Range >::value >
Definition: algorithm.hpp:999
auto partial_sort(Range &&rng, RandomIt &&it) -> enable_if_t< is_range< Range >::value >
Definition: algorithm.hpp:1389
auto find_end(Range1 &&rng1, Range2 &&rng2, BinaryPred &bp) -> meta::when< meta::all_of< meta::list< Range1, Range2 >, is_range >(), decltype(::std::begin(::core::forward< Range1 >(rng1))) >
Definition: algorithm.hpp:510
auto sort(Range &&rng) -> enable_if_t< is_range< Range >::value >
Definition: algorithm.hpp:1369
auto count_if(Range &&rng, UnaryPredicate &&p) -> enable_if_t< is_range< Range >::value, decltype(::std::count_if(::std::begin(::core::forward< Range >(rng)), ::std::end(::core::forward< Range >(rng)), ::core::forward< UnaryPredicate >(p))) >
Definition: algorithm.hpp:242
auto unique_copy(Range &&rng, OutputIt &&it) -> enable_if_t< is_range< Range >::value, decay_t< OutputIt > >
Definition: algorithm.hpp:1204
auto set_symmetric_difference(Range1 &&rng1, Range2 &&rng2, OutputIt &&it, Compare &&cmp) -> enable_if_t< meta::all_of< meta::list< Range1, Range2 >, is_range >(), decay_t< OutputIt > >
Definition: algorithm.hpp:1848
auto for_each_until(Range &&r, UnaryFunction f, T const &value) -> decltype(begin(make_range(::core::forward< Range >(r))))
Definition: algorithm.hpp:208
auto set_intersection(Range1 &&rng1, Range2 &&rng2, OutputIt &&it) -> meta::when< meta::all_of< meta::list< Range1, Range2 >, is_range >(), decay_t< OutputIt > >
Definition: algorithm.hpp:1782
OutputIt copy_until(Range &&r, OutputIt it, T const &value)
Definition: algorithm.hpp:708
auto transform_if(Range &&rng, OutputIt it, UnaryOperation op, UnaryPred up) -> enable_if_t< is_range< Range >::value, OutputIt >
Definition: algorithm.hpp:796
auto lexicographical_compare(Range1 &&rng1, Range2 &&rng2, Compare &&cmp) -> enable_if_t< meta::all_of< meta::list< Range1, Range2 >, is_range >(), bool >
Definition: algorithm.hpp:2162
auto binary_search(Range &&rng, T const &value) -> enable_if_t< is_range< Range >::value, bool >
Definition: algorithm.hpp:1567
auto is_partitioned(Range &&rng, UnaryPredicate &&up) -> enable_if_t< is_range< Range >::value, bool >
Definition: algorithm.hpp:1236
auto set_intersection(Range1 &&rng1, Range2 &&rng2, OutputIt &&it, Compare &&cmp) -> enable_if_t< meta::all_of< meta::list< Range1, Range2 >, is_range >(), decay_t< OutputIt > >
Definition: algorithm.hpp:1802
typename ::std::enable_if< B, T >::type when
Definition: meta.hpp:193
auto next_permutation(Range &&rng) -> enable_if_t< is_range< Range >::value, bool >
Definition: algorithm.hpp:2227
auto remove(Range &&rng, T const &value) -> enable_if_t< is_range< Range >::value, decltype(::std::begin(::core::forward< Range >(rng))) >
Definition: algorithm.hpp:941
auto search(Range1 &&rng1, Range2 &&rng2) -> meta::when< meta::all_of< meta::list< Range1, Range2 >, is_range >(), decltype(::std::begin(::core::forward< Range1 >(rng1))) >
Definition: algorithm.hpp:599
auto is_heap_until(Range &&rng) -> enable_if_t< is_range< Range >::value, decltype(::std::begin(::core::forward< Range >(rng))) >
Definition: algorithm.hpp:1944
auto find(Range &&rng, T const &value) -> enable_if_t< is_range< Range >::value, decltype(::std::begin(::core::forward< Range >(rng))) >
Definition: algorithm.hpp:450
difference_type size() const
Definition: range.hpp:157
auto is_sorted_until(Range &&rng, Compare &&compare) -> enable_if_t< is_range< Range >::value, decltype(::std::begin(::core::forward< Range >(rng))) >
Definition: algorithm.hpp:1354
auto nth_element(Range &&rng, RandomIt &&it, Compare &&cmp) -> enable_if_t< is_range< Range >::value >
Definition: algorithm.hpp:1497
auto equal_range(Range &&rng, T const &value, Compare &&cmp) -> enable_if_t< is_range< Range >::value, range< decltype(::std::begin(::core::forward< Range >(rng)))> >
Definition: algorithm.hpp:1605
auto remove_erase_if(Range &&rng, UnaryPred &&up) -> enable_if_t< is_range< Range >::value >
Definition: algorithm.hpp:1009
auto partition_copy(Range &&rng, OutputTrue &&ot, OutputFalse &&of, UnaryPred &&up) -> enable_if_t< is_range< Range >::value, ::std::pair< decay_t< OutputTrue >, decay_t< OutputFalse >> >
Definition: algorithm.hpp:1266
auto copy(Range &&rng, OutputIt &&it) -> enable_if_t< is_range< Range >::value, decay_t< OutputIt > >
Definition: algorithm.hpp:677
auto make_heap(Range &&rng) -> enable_if_t< is_range< Range >::value >
Definition: algorithm.hpp:1970
bool equal(range< InputIt1 > r1, range< InputIt2 > r2, Predicate &&p, ::std::random_access_iterator_tag, ::std::random_access_iterator_tag)
Definition: algorithm.hpp:28
when< B, ::std::size_t > require
Definition: meta.hpp:196
auto pop_heap(Range &&rng, Compare &&cmp) -> enable_if_t< is_range< Range >::value >
Definition: algorithm.hpp:2022
auto minmax_element(Range &&rng) -> enable_if_t< is_range< Range >::value, ::std::pair< decltype(::std::begin(::core::forward< Range >(rng))), decltype(::std::end(::core::forward< Range >(rng))) > >
Definition: algorithm.hpp:2111
auto is_heap(Range &&rng) -> enable_if_t< is_range< Range >::value, bool >
Definition: algorithm.hpp:1921
auto is_sorted(Range &&rng, Compare &&compare) -> enable_if_t< is_range< Range >::value, bool >
Definition: algorithm.hpp:1328
auto set_difference(Range1 &&rng1, Range2 &&rng2, OutputIt &&it, Compare &&cmp) -> meta::when< meta::all_of< meta::list< Range1, Range2 >, is_range >(), decay_t< OutputIt > >
Definition: algorithm.hpp:1756
decay_t< OutputIt > transform(Range1 &&rng1, Range2 &&rng2, OutputIt &&it, BinaryOperation &&op)
Definition: algorithm.hpp:886
auto rotate_copy(Range &&rng, ForwardIt &&it, OutputIt &&ot) -> enable_if_t< is_range< Range >::value, decay_t< OutputIt > >
Definition: algorithm.hpp:1148
auto reverse_copy(Range &&rng, OutputIt &&it) -> enable_if_t< is_range< Range >::value, decay_t< OutputIt > >
Definition: algorithm.hpp:1119
auto upper_bound(Range &&rng, T const &value, Compare &&cmp) -> enable_if_t< is_range< Range >::value, decltype(::std::begin(::core::forward< Range >(rng))) >
Definition: algorithm.hpp:1551
auto partition(Range &&rng, UnaryPredicate &&up) -> enable_if_t< is_range< Range >::value, decltype(::std::begin(::core::forward< Range >(rng))) >
Definition: algorithm.hpp:1251
auto find_first_of(IRange &&irng, FRange &&frng) -> meta::when< meta::all_of< meta::list< IRange, FRange >, is_range >(), decltype(::std::begin(::core::forward< IRange >(irng))) >
Definition: algorithm.hpp:530
auto is_permutation(Range1 &&rng1, Range2 &&rng2, BinaryPredicate &&bp) -> meta::when< meta::all_of< meta::list< Range1, Range2 >, is_range >(), bool >
Definition: algorithm.hpp:2204
auto mismatch(Range &&r, InputIt &&it, BinaryPredicate &&bp) -> ::std::pair< decltype(core::make_range(::core::forward< Range >(r).begin())), decay_t< InputIt > >
Definition: algorithm.hpp:339
auto min_element(Range &&rng, Compare &&cmp) -> enable_if_t< is_range< Range >::value, decltype(::std::begin(::core::forward< Range >(rng))) >
Definition: algorithm.hpp:2096
auto remove_copy_if(Range &&rng, OutputIt &&it, UnaryPred &&up) -> enable_if_t< is_range< Range >::value, decay_t< OutputIt > >
Definition: algorithm.hpp:983
auto partial_sort(Range &&rng, RandomIt &&it, Compare &&cmp) -> enable_if_t< is_range< Range >::value >
Definition: algorithm.hpp:1403
auto shuffle(Range &&rng, URNG &&g) -> enable_if_t< is_range< Range >::value >
Definition: algorithm.hpp:1164
auto count(Range &&rng, T const &value) -> enable_if_t< is_range< Range >::value, decltype(::std::count(::std::begin(::core::forward< Range >(rng)), ::std::end(::core::forward< Range >(rng)), value)) >
Definition: algorithm.hpp:225
auto copy_if(Range &&rng, OutputIt &&it, UnaryPredicate &&up) -> enable_if_t< is_range< Range >::value, decay_t< OutputIt > >
Definition: algorithm.hpp:692
constexpr T const & clamp(T const &value, T const &low, T const &high, Compare compare=Compare { })
Definition: algorithm.hpp:90
impl::decay_t< T > decay_t
constexpr T const & min(T const &lhs, T const &rhs)
Definition: algorithm.hpp:69
auto includes(Range1 &&rng1, Range2 &&rng2) -> meta::when< meta::all_of< meta::list< Range1, Range2 >, is_range >(), bool >
Definition: algorithm.hpp:1697
typename ::std::enable_if< B, T >::type enable_if_t
auto set_union(Range1 &&rng1, Range2 &&rng2, OutputIt &&it) -> enable_if_t< meta::all_of< meta::list< Range1, Range2 >, is_range >(), decay_t< OutputIt > >
Definition: algorithm.hpp:1874
OutputIt transform_n(InputIt in, Size count, OutputIt out, UnaryOp op)
Definition: algorithm.hpp:819
auto equal_range(Range &&rng, T const &value) -> enable_if_t< is_range< Range >::value, range< decltype(::std::begin(::core::forward< Range >(rng)))> >
Definition: algorithm.hpp:1594
auto set_difference(Range1 &&rng1, Range2 &&rng2, OutputIt &&it) -> meta::when< meta::all_of< meta::list< Range1, Range2 >, is_range >(), decay_t< OutputIt > >
Definition: algorithm.hpp:1736
auto search_n(Range &&rng, Size &&count, T const &value, BinaryPred &&bp) -> meta::when< is_range< Range >::value, decltype(::std::begin(::core::forward< Range >(rng))) >
Definition: algorithm.hpp:654
auto replace_copy_if(Range &&rng, OutputIt &&it, UnaryPred &&up, T const &value) -> enable_if_t< is_range< Range >::value, decay_t< OutputIt > >
Definition: algorithm.hpp:1074
auto push_heap(Range &&rng) -> enable_if_t< is_range< Range >::value >
Definition: algorithm.hpp:1992
auto is_sorted(Range &&rng) -> enable_if_t< is_range< Range >::value, bool >
Definition: algorithm.hpp:1320
auto move(Range &&rng, OutputIt &&it) -> enable_if_t< is_range< Range >::value, decay_t< OutputIt > >
Definition: algorithm.hpp:736
auto sort_heap(Range &&rng) -> enable_if_t< is_range< Range >::value >
Definition: algorithm.hpp:2036
auto is_permutation(Range1 &&rng1, Range2 &&rng2) -> enable_if_t< meta::all_of< meta::list< Range1, Range2 >, is_range >(), bool >
Definition: algorithm.hpp:2186
reference front() const
Definition: range.hpp:149
auto is_heap_until(Range &&rng, Compare &&cmp) -> enable_if_t< is_range< Range >::value, decltype(::std::begin(::core::forward< Range >(rng))) >
Definition: algorithm.hpp:1955
auto merge(Range1 &&rng1, Range2 &&rng2, OutputIt &&it) -> meta::when< meta::all_of< meta::list< Range1, Range2 >, is_range >(), decay_t< OutputIt > >
Definition: algorithm.hpp:1622
auto partial_sort_copy(IRange &&irng, RRange &&rrng, Compare &&cmp) -> meta::when< meta::all_of< meta::list< IRange, RRange >, is_range >(), decltype(::std::begin(::core::forward< RRange >(rrng))) >
Definition: algorithm.hpp:1437
auto unique(Range &&rng, BinaryPredicate &&bp) -> enable_if_t< is_range< Range >::value, decltype(::std::begin(::core::forward< Range >(rng))) >
Definition: algorithm.hpp:1189
auto lower_bound(Range &&rng, T const &value) -> enable_if_t< is_range< Range >::value, decltype(::std::begin(::core::forward< Range >(rng))) >
Definition: algorithm.hpp:1513
auto partial_sort_copy(IRange &&irng, RRange &&rrng) -> meta::when< meta::all_of< meta::list< IRange, RRange >, is_range >(), decltype(::std::begin(::core::forward< RRange >(rrng))) >
Definition: algorithm.hpp:1418
auto stable_partition(Range &&rng, UnaryPredicate &&up) -> enable_if_t< is_range< Range >::value, decltype(::std::begin(::core::forward< Range >(rng))) >
Definition: algorithm.hpp:1288
auto none_of(Range &&rng, UnaryPredicate &&p) -> enable_if_t< is_range< Range >::value, bool >
Definition: algorithm.hpp:149
auto swap_ranges(Range &&rng, ForwardIt &&it) -> enable_if_t< is_range< Range >::value, decay_t< ForwardIt > >
Definition: algorithm.hpp:1096
auto upper_bound(Range &&rng, T const &value) -> enable_if_t< is_range< Range >::value, decltype(::std::begin(::core::forward< Range >(rng))) >
Definition: algorithm.hpp:1540
auto for_each_while(Range &&r, UnaryFunction f, UnaryPredicate p) -> decltype(begin(make_range(::core::forward< Range >(r))))
Definition: algorithm.hpp:191
auto push_heap(Range &&rng, Compare &&cmp) -> enable_if_t< is_range< Range >::value >
Definition: algorithm.hpp:2000
auto copy_backward(Range &&rng, BidirIt &&it) -> enable_if_t< is_range< Range >::value, decay_t< BidirIt > >
Definition: algorithm.hpp:721
auto minmax_element(Range &&rng, Compare &&cmp) -> enable_if_t< is_range< Range >::value, ::std::pair< range< decltype(::std::begin(::core::forward< Range >(rng)))>, range< decltype(::std::end(::core::forward< Range >(rng)))> > >
Definition: algorithm.hpp:2125
auto partition_point(Range &&rng, UnaryPredicate &&up) -> enable_if_t< is_range< Range >::value, decltype(::std::begin(::core::forward< Range >(rng))) >
Definition: algorithm.hpp:1303