libstdc++
ranges_util.h
Go to the documentation of this file.
1// Utilities for representing and manipulating ranges -*- C++ -*-
2
3// Copyright (C) 2019-2023 Free Software Foundation, Inc.
4//
5// This file is part of the GNU ISO C++ Library. This library is free
6// software; you can redistribute it and/or modify it under the
7// terms of the GNU General Public License as published by the
8// Free Software Foundation; either version 3, or (at your option)
9// any later version.
10
11// This library is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15
16// Under Section 7 of GPL version 3, you are granted additional
17// permissions described in the GCC Runtime Library Exception, version
18// 3.1, as published by the Free Software Foundation.
19
20// You should have received a copy of the GNU General Public License and
21// a copy of the GCC Runtime Library Exception along with this program;
22// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23// <http://www.gnu.org/licenses/>.
24
25/** @file bits/ranges_util.h
26 * This is an internal header file, included by other library headers.
27 * Do not attempt to use it directly. @headername{ranges}
28 */
29
30#ifndef _RANGES_UTIL_H
31#define _RANGES_UTIL_H 1
32
33#if __cplusplus > 201703L
34# include <bits/ranges_base.h>
35# include <bits/utility.h>
36
37#ifdef __cpp_lib_ranges
38namespace std _GLIBCXX_VISIBILITY(default)
39{
40_GLIBCXX_BEGIN_NAMESPACE_VERSION
41namespace ranges
42{
43 // C++20 24.5 [range.utility] Range utilities
44
45 namespace __detail
46 {
47 template<typename _Range>
48 concept __simple_view = view<_Range> && range<const _Range>
49 && same_as<iterator_t<_Range>, iterator_t<const _Range>>
50 && same_as<sentinel_t<_Range>, sentinel_t<const _Range>>;
51
52 template<typename _It>
53 concept __has_arrow = input_iterator<_It>
54 && (is_pointer_v<_It> || requires(_It __it) { __it.operator->(); });
55
56 using std::__detail::__different_from;
57 } // namespace __detail
58
59 /// The ranges::view_interface class template
60 template<typename _Derived>
61 requires is_class_v<_Derived> && same_as<_Derived, remove_cv_t<_Derived>>
63 {
64 private:
65 constexpr _Derived& _M_derived() noexcept
66 {
68 static_assert(view<_Derived>);
69 return static_cast<_Derived&>(*this);
70 }
71
72 constexpr const _Derived& _M_derived() const noexcept
73 {
75 static_assert(view<_Derived>);
76 return static_cast<const _Derived&>(*this);
77 }
78
79 static constexpr bool
80 _S_bool(bool) noexcept; // not defined
81
82 template<typename _Tp>
83 static constexpr bool
84 _S_empty(_Tp& __t)
85 noexcept(noexcept(_S_bool(ranges::begin(__t) == ranges::end(__t))))
86 { return ranges::begin(__t) == ranges::end(__t); }
87
88 template<typename _Tp>
89 static constexpr auto
90 _S_size(_Tp& __t)
91 noexcept(noexcept(ranges::end(__t) - ranges::begin(__t)))
92 { return ranges::end(__t) - ranges::begin(__t); }
93
94 public:
95 constexpr bool
96 empty()
97 noexcept(noexcept(_S_empty(_M_derived())))
99 { return _S_empty(_M_derived()); }
100
101 constexpr bool
102 empty()
103 noexcept(noexcept(ranges::size(_M_derived()) == 0))
104 requires sized_range<_Derived>
105 { return ranges::size(_M_derived()) == 0; }
106
107 constexpr bool
108 empty() const
109 noexcept(noexcept(_S_empty(_M_derived())))
111 { return _S_empty(_M_derived()); }
112
113 constexpr bool
114 empty() const
115 noexcept(noexcept(ranges::size(_M_derived()) == 0))
117 { return ranges::size(_M_derived()) == 0; }
118
119 constexpr explicit
120 operator bool() noexcept(noexcept(ranges::empty(_M_derived())))
121 requires requires { ranges::empty(_M_derived()); }
122 { return !ranges::empty(_M_derived()); }
123
124 constexpr explicit
125 operator bool() const noexcept(noexcept(ranges::empty(_M_derived())))
126 requires requires { ranges::empty(_M_derived()); }
127 { return !ranges::empty(_M_derived()); }
128
129 constexpr auto
130 data() noexcept(noexcept(ranges::begin(_M_derived())))
131 requires contiguous_iterator<iterator_t<_Derived>>
132 { return std::to_address(ranges::begin(_M_derived())); }
133
134 constexpr auto
135 data() const noexcept(noexcept(ranges::begin(_M_derived())))
136 requires range<const _Derived>
137 && contiguous_iterator<iterator_t<const _Derived>>
138 { return std::to_address(ranges::begin(_M_derived())); }
139
140 constexpr auto
141 size() noexcept(noexcept(_S_size(_M_derived())))
143 && sized_sentinel_for<sentinel_t<_Derived>, iterator_t<_Derived>>
144 { return _S_size(_M_derived()); }
145
146 constexpr auto
147 size() const noexcept(noexcept(_S_size(_M_derived())))
149 && sized_sentinel_for<sentinel_t<const _Derived>,
150 iterator_t<const _Derived>>
151 { return _S_size(_M_derived()); }
152
153 constexpr decltype(auto)
154 front() requires forward_range<_Derived>
155 {
156 __glibcxx_assert(!empty());
157 return *ranges::begin(_M_derived());
158 }
159
160 constexpr decltype(auto)
161 front() const requires forward_range<const _Derived>
162 {
163 __glibcxx_assert(!empty());
164 return *ranges::begin(_M_derived());
165 }
166
167 constexpr decltype(auto)
168 back()
170 {
171 __glibcxx_assert(!empty());
172 return *ranges::prev(ranges::end(_M_derived()));
173 }
174
175 constexpr decltype(auto)
176 back() const
179 {
180 __glibcxx_assert(!empty());
181 return *ranges::prev(ranges::end(_M_derived()));
182 }
183
184 template<random_access_range _Range = _Derived>
185 constexpr decltype(auto)
186 operator[](range_difference_t<_Range> __n)
187 { return ranges::begin(_M_derived())[__n]; }
188
189 template<random_access_range _Range = const _Derived>
190 constexpr decltype(auto)
191 operator[](range_difference_t<_Range> __n) const
192 { return ranges::begin(_M_derived())[__n]; }
193
194#if __cplusplus > 202002L
195 constexpr auto
197 { return ranges::cbegin(_M_derived()); }
198
199 constexpr auto
200 cbegin() const requires input_range<const _Derived>
201 { return ranges::cbegin(_M_derived()); }
202
203 constexpr auto
204 cend() requires input_range<_Derived>
205 { return ranges::cend(_M_derived()); }
206
207 constexpr auto
208 cend() const requires input_range<const _Derived>
209 { return ranges::cend(_M_derived()); }
210#endif
211 };
212
213 namespace __detail
214 {
215 template<typename _From, typename _To>
216 concept __uses_nonqualification_pointer_conversion
217 = is_pointer_v<_From> && is_pointer_v<_To>
220
221 template<typename _From, typename _To>
222 concept __convertible_to_non_slicing = convertible_to<_From, _To>
223 && !__uses_nonqualification_pointer_conversion<decay_t<_From>,
225
226 template<typename _Tp>
227 concept __pair_like
228 = !is_reference_v<_Tp> && requires(_Tp __t)
229 {
230 typename tuple_size<_Tp>::type;
232 typename tuple_element_t<0, remove_const_t<_Tp>>;
233 typename tuple_element_t<1, remove_const_t<_Tp>>;
235 { get<1>(__t) } -> convertible_to<const tuple_element_t<1, _Tp>&>;
236 };
237
238 template<typename _Tp, typename _Up, typename _Vp>
239 concept __pair_like_convertible_from
240 = !range<_Tp> && __pair_like<_Tp>
241 && constructible_from<_Tp, _Up, _Vp>
242 && __convertible_to_non_slicing<_Up, tuple_element_t<0, _Tp>>
243 && convertible_to<_Vp, tuple_element_t<1, _Tp>>;
244
245 } // namespace __detail
246
247 namespace views { struct _Drop; } // defined in <ranges>
248
249 enum class subrange_kind : bool { unsized, sized };
250
251 /// The ranges::subrange class template
252 template<input_or_output_iterator _It, sentinel_for<_It> _Sent = _It,
253 subrange_kind _Kind = sized_sentinel_for<_Sent, _It>
254 ? subrange_kind::sized : subrange_kind::unsized>
255 requires (_Kind == subrange_kind::sized || !sized_sentinel_for<_Sent, _It>)
256 class subrange : public view_interface<subrange<_It, _Sent, _Kind>>
257 {
258 private:
259 static constexpr bool _S_store_size
260 = _Kind == subrange_kind::sized && !sized_sentinel_for<_Sent, _It>;
261
262 friend struct views::_Drop; // Needs to inspect _S_store_size.
263
264 _It _M_begin = _It();
265 [[no_unique_address]] _Sent _M_end = _Sent();
266
267 using __size_type
268 = __detail::__make_unsigned_like_t<iter_difference_t<_It>>;
269
270 template<typename, bool = _S_store_size>
271 struct _Size
272 { };
273
274 template<typename _Tp>
275 struct _Size<_Tp, true>
276 { _Tp _M_size; };
277
278 [[no_unique_address]] _Size<__size_type> _M_size = {};
279
280 public:
281 subrange() requires default_initializable<_It> = default;
282
283 constexpr
284 subrange(__detail::__convertible_to_non_slicing<_It> auto __i, _Sent __s)
285 noexcept(is_nothrow_constructible_v<_It, decltype(__i)>
286 && is_nothrow_constructible_v<_Sent, _Sent&>)
287 requires (!_S_store_size)
288 : _M_begin(std::move(__i)), _M_end(__s)
289 { }
290
291 constexpr
292 subrange(__detail::__convertible_to_non_slicing<_It> auto __i, _Sent __s,
293 __size_type __n)
294 noexcept(is_nothrow_constructible_v<_It, decltype(__i)>
295 && is_nothrow_constructible_v<_Sent, _Sent&>)
296 requires (_Kind == subrange_kind::sized)
297 : _M_begin(std::move(__i)), _M_end(__s)
298 {
299 if constexpr (_S_store_size)
300 _M_size._M_size = __n;
301 }
302
303 template<__detail::__different_from<subrange> _Rng>
304 requires borrowed_range<_Rng>
305 && __detail::__convertible_to_non_slicing<iterator_t<_Rng>, _It>
307 constexpr
308 subrange(_Rng&& __r)
309 noexcept(noexcept(subrange(__r, ranges::size(__r))))
310 requires _S_store_size && sized_range<_Rng>
311 : subrange(__r, ranges::size(__r))
312 { }
313
314 template<__detail::__different_from<subrange> _Rng>
315 requires borrowed_range<_Rng>
316 && __detail::__convertible_to_non_slicing<iterator_t<_Rng>, _It>
318 constexpr
319 subrange(_Rng&& __r)
320 noexcept(noexcept(subrange(ranges::begin(__r), ranges::end(__r))))
321 requires (!_S_store_size)
322 : subrange(ranges::begin(__r), ranges::end(__r))
323 { }
324
325 template<borrowed_range _Rng>
326 requires __detail::__convertible_to_non_slicing<iterator_t<_Rng>, _It>
328 constexpr
329 subrange(_Rng&& __r, __size_type __n)
330 noexcept(noexcept(subrange(ranges::begin(__r), ranges::end(__r), __n)))
331 requires (_Kind == subrange_kind::sized)
332 : subrange{ranges::begin(__r), ranges::end(__r), __n}
333 { }
334
335 template<__detail::__different_from<subrange> _PairLike>
336 requires __detail::__pair_like_convertible_from<_PairLike, const _It&,
337 const _Sent&>
338 constexpr
339 operator _PairLike() const
340 { return _PairLike(_M_begin, _M_end); }
341
342 constexpr _It
343 begin() const requires copyable<_It>
344 { return _M_begin; }
345
346 [[nodiscard]] constexpr _It
347 begin() requires (!copyable<_It>)
348 { return std::move(_M_begin); }
349
350 constexpr _Sent end() const { return _M_end; }
351
352 constexpr bool empty() const { return _M_begin == _M_end; }
353
354 constexpr __size_type
355 size() const requires (_Kind == subrange_kind::sized)
356 {
357 if constexpr (_S_store_size)
358 return _M_size._M_size;
359 else
360 return __detail::__to_unsigned_like(_M_end - _M_begin);
361 }
362
363 [[nodiscard]] constexpr subrange
364 next(iter_difference_t<_It> __n = 1) const &
365 requires forward_iterator<_It>
366 {
367 auto __tmp = *this;
368 __tmp.advance(__n);
369 return __tmp;
370 }
371
372 [[nodiscard]] constexpr subrange
373 next(iter_difference_t<_It> __n = 1) &&
374 {
375 advance(__n);
376 return std::move(*this);
377 }
378
379 [[nodiscard]] constexpr subrange
380 prev(iter_difference_t<_It> __n = 1) const
381 requires bidirectional_iterator<_It>
382 {
383 auto __tmp = *this;
384 __tmp.advance(-__n);
385 return __tmp;
386 }
387
388 constexpr subrange&
389 advance(iter_difference_t<_It> __n)
390 {
391 // _GLIBCXX_RESOLVE_LIB_DEFECTS
392 // 3433. subrange::advance(n) has UB when n < 0
393 if constexpr (bidirectional_iterator<_It>)
394 if (__n < 0)
395 {
396 ranges::advance(_M_begin, __n);
397 if constexpr (_S_store_size)
398 _M_size._M_size += __detail::__to_unsigned_like(-__n);
399 return *this;
400 }
401
402 __glibcxx_assert(__n >= 0);
403 auto __d = __n - ranges::advance(_M_begin, __n, _M_end);
404 if constexpr (_S_store_size)
405 _M_size._M_size -= __detail::__to_unsigned_like(__d);
406 return *this;
407 }
408 };
409
410 template<input_or_output_iterator _It, sentinel_for<_It> _Sent>
411 subrange(_It, _Sent) -> subrange<_It, _Sent>;
412
413 template<input_or_output_iterator _It, sentinel_for<_It> _Sent>
414 subrange(_It, _Sent,
415 __detail::__make_unsigned_like_t<iter_difference_t<_It>>)
417
418 template<borrowed_range _Rng>
419 subrange(_Rng&&)
420 -> subrange<iterator_t<_Rng>, sentinel_t<_Rng>,
422 || sized_sentinel_for<sentinel_t<_Rng>, iterator_t<_Rng>>)
423 ? subrange_kind::sized : subrange_kind::unsized>;
424
425 template<borrowed_range _Rng>
426 subrange(_Rng&&,
427 __detail::__make_unsigned_like_t<range_difference_t<_Rng>>)
428 -> subrange<iterator_t<_Rng>, sentinel_t<_Rng>, subrange_kind::sized>;
429
430 template<size_t _Num, class _It, class _Sent, subrange_kind _Kind>
431 requires (_Num < 2)
432 constexpr auto
433 get(const subrange<_It, _Sent, _Kind>& __r)
434 {
435 if constexpr (_Num == 0)
436 return __r.begin();
437 else
438 return __r.end();
439 }
440
441 template<size_t _Num, class _It, class _Sent, subrange_kind _Kind>
442 requires (_Num < 2)
443 constexpr auto
444 get(subrange<_It, _Sent, _Kind>&& __r)
445 {
446 if constexpr (_Num == 0)
447 return __r.begin();
448 else
449 return __r.end();
450 }
451
452 template<typename _It, typename _Sent, subrange_kind _Kind>
453 inline constexpr bool
454 enable_borrowed_range<subrange<_It, _Sent, _Kind>> = true;
455
456 template<range _Range>
457 using borrowed_subrange_t = __conditional_t<borrowed_range<_Range>,
458 subrange<iterator_t<_Range>>,
459 dangling>;
460} // namespace ranges
461
462// The following ranges algorithms are used by <ranges>, and are defined here
463// so that <ranges> can avoid including all of <bits/ranges_algo.h>.
464namespace ranges
465{
466 struct __find_fn
467 {
468 template<input_iterator _Iter, sentinel_for<_Iter> _Sent, typename _Tp,
469 typename _Proj = identity>
470 requires indirect_binary_predicate<ranges::equal_to,
471 projected<_Iter, _Proj>, const _Tp*>
472 constexpr _Iter
473 operator()(_Iter __first, _Sent __last,
474 const _Tp& __value, _Proj __proj = {}) const
475 {
476 while (__first != __last
477 && !(std::__invoke(__proj, *__first) == __value))
478 ++__first;
479 return __first;
480 }
481
482 template<input_range _Range, typename _Tp, typename _Proj = identity>
483 requires indirect_binary_predicate<ranges::equal_to,
484 projected<iterator_t<_Range>, _Proj>,
485 const _Tp*>
486 constexpr borrowed_iterator_t<_Range>
487 operator()(_Range&& __r, const _Tp& __value, _Proj __proj = {}) const
488 {
489 return (*this)(ranges::begin(__r), ranges::end(__r),
490 __value, std::move(__proj));
491 }
492 };
493
494 inline constexpr __find_fn find{};
495
496 struct __find_if_fn
497 {
498 template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
499 typename _Proj = identity,
500 indirect_unary_predicate<projected<_Iter, _Proj>> _Pred>
501 constexpr _Iter
502 operator()(_Iter __first, _Sent __last,
503 _Pred __pred, _Proj __proj = {}) const
504 {
505 while (__first != __last
506 && !(bool)std::__invoke(__pred, std::__invoke(__proj, *__first)))
507 ++__first;
508 return __first;
509 }
510
511 template<input_range _Range, typename _Proj = identity,
512 indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>>
513 _Pred>
514 constexpr borrowed_iterator_t<_Range>
515 operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const
516 {
517 return (*this)(ranges::begin(__r), ranges::end(__r),
518 std::move(__pred), std::move(__proj));
519 }
520 };
521
522 inline constexpr __find_if_fn find_if{};
523
524 struct __find_if_not_fn
525 {
526 template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
527 typename _Proj = identity,
528 indirect_unary_predicate<projected<_Iter, _Proj>> _Pred>
529 constexpr _Iter
530 operator()(_Iter __first, _Sent __last,
531 _Pred __pred, _Proj __proj = {}) const
532 {
533 while (__first != __last
534 && (bool)std::__invoke(__pred, std::__invoke(__proj, *__first)))
535 ++__first;
536 return __first;
537 }
538
539 template<input_range _Range, typename _Proj = identity,
540 indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>>
541 _Pred>
542 constexpr borrowed_iterator_t<_Range>
543 operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const
544 {
545 return (*this)(ranges::begin(__r), ranges::end(__r),
546 std::move(__pred), std::move(__proj));
547 }
548 };
549
550 inline constexpr __find_if_not_fn find_if_not{};
551
552 template<typename _Iter1, typename _Iter2>
553 struct in_in_result
554 {
555 [[no_unique_address]] _Iter1 in1;
556 [[no_unique_address]] _Iter2 in2;
557
558 template<typename _IIter1, typename _IIter2>
559 requires convertible_to<const _Iter1&, _IIter1>
560 && convertible_to<const _Iter2&, _IIter2>
561 constexpr
562 operator in_in_result<_IIter1, _IIter2>() const &
563 { return {in1, in2}; }
564
565 template<typename _IIter1, typename _IIter2>
566 requires convertible_to<_Iter1, _IIter1>
567 && convertible_to<_Iter2, _IIter2>
568 constexpr
569 operator in_in_result<_IIter1, _IIter2>() &&
570 { return {std::move(in1), std::move(in2)}; }
571 };
572
573 template<typename _Iter1, typename _Iter2>
574 using mismatch_result = in_in_result<_Iter1, _Iter2>;
575
576 struct __mismatch_fn
577 {
578 template<input_iterator _Iter1, sentinel_for<_Iter1> _Sent1,
579 input_iterator _Iter2, sentinel_for<_Iter2> _Sent2,
580 typename _Pred = ranges::equal_to,
581 typename _Proj1 = identity, typename _Proj2 = identity>
582 requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2>
583 constexpr mismatch_result<_Iter1, _Iter2>
584 operator()(_Iter1 __first1, _Sent1 __last1,
585 _Iter2 __first2, _Sent2 __last2, _Pred __pred = {},
586 _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const
587 {
588 while (__first1 != __last1 && __first2 != __last2
589 && (bool)std::__invoke(__pred,
590 std::__invoke(__proj1, *__first1),
591 std::__invoke(__proj2, *__first2)))
592 {
593 ++__first1;
594 ++__first2;
595 }
596 return { std::move(__first1), std::move(__first2) };
597 }
598
599 template<input_range _Range1, input_range _Range2,
600 typename _Pred = ranges::equal_to,
601 typename _Proj1 = identity, typename _Proj2 = identity>
602 requires indirectly_comparable<iterator_t<_Range1>, iterator_t<_Range2>,
603 _Pred, _Proj1, _Proj2>
604 constexpr mismatch_result<iterator_t<_Range1>, iterator_t<_Range2>>
605 operator()(_Range1&& __r1, _Range2&& __r2, _Pred __pred = {},
606 _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const
607 {
608 return (*this)(ranges::begin(__r1), ranges::end(__r1),
609 ranges::begin(__r2), ranges::end(__r2),
610 std::move(__pred),
611 std::move(__proj1), std::move(__proj2));
612 }
613 };
614
615 inline constexpr __mismatch_fn mismatch{};
616
617 struct __search_fn
618 {
619 template<forward_iterator _Iter1, sentinel_for<_Iter1> _Sent1,
620 forward_iterator _Iter2, sentinel_for<_Iter2> _Sent2,
621 typename _Pred = ranges::equal_to,
622 typename _Proj1 = identity, typename _Proj2 = identity>
623 requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2>
624 constexpr subrange<_Iter1>
625 operator()(_Iter1 __first1, _Sent1 __last1,
626 _Iter2 __first2, _Sent2 __last2, _Pred __pred = {},
627 _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const
628 {
629 if (__first1 == __last1 || __first2 == __last2)
630 return {__first1, __first1};
631
632 for (;;)
633 {
634 for (;;)
635 {
636 if (__first1 == __last1)
637 return {__first1, __first1};
638 if (std::__invoke(__pred,
639 std::__invoke(__proj1, *__first1),
640 std::__invoke(__proj2, *__first2)))
641 break;
642 ++__first1;
643 }
644 auto __cur1 = __first1;
645 auto __cur2 = __first2;
646 for (;;)
647 {
648 if (++__cur2 == __last2)
649 return {__first1, ++__cur1};
650 if (++__cur1 == __last1)
651 return {__cur1, __cur1};
652 if (!(bool)std::__invoke(__pred,
653 std::__invoke(__proj1, *__cur1),
654 std::__invoke(__proj2, *__cur2)))
655 {
656 ++__first1;
657 break;
658 }
659 }
660 }
661 }
662
663 template<forward_range _Range1, forward_range _Range2,
664 typename _Pred = ranges::equal_to,
665 typename _Proj1 = identity, typename _Proj2 = identity>
666 requires indirectly_comparable<iterator_t<_Range1>, iterator_t<_Range2>,
667 _Pred, _Proj1, _Proj2>
668 constexpr borrowed_subrange_t<_Range1>
669 operator()(_Range1&& __r1, _Range2&& __r2, _Pred __pred = {},
670 _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const
671 {
672 return (*this)(ranges::begin(__r1), ranges::end(__r1),
673 ranges::begin(__r2), ranges::end(__r2),
674 std::move(__pred),
675 std::move(__proj1), std::move(__proj2));
676 }
677 };
678
679 inline constexpr __search_fn search{};
680
681 struct __min_fn
682 {
683 template<typename _Tp, typename _Proj = identity,
684 indirect_strict_weak_order<projected<const _Tp*, _Proj>>
685 _Comp = ranges::less>
686 constexpr const _Tp&
687 operator()(const _Tp& __a, const _Tp& __b,
688 _Comp __comp = {}, _Proj __proj = {}) const
689 {
690 if (std::__invoke(__comp,
691 std::__invoke(__proj, __b),
692 std::__invoke(__proj, __a)))
693 return __b;
694 else
695 return __a;
696 }
697
698 template<input_range _Range, typename _Proj = identity,
699 indirect_strict_weak_order<projected<iterator_t<_Range>, _Proj>>
700 _Comp = ranges::less>
701 requires indirectly_copyable_storable<iterator_t<_Range>,
702 range_value_t<_Range>*>
703 constexpr range_value_t<_Range>
704 operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const
705 {
706 auto __first = ranges::begin(__r);
707 auto __last = ranges::end(__r);
708 __glibcxx_assert(__first != __last);
709 auto __result = *__first;
710 while (++__first != __last)
711 {
712 auto __tmp = *__first;
713 if (std::__invoke(__comp,
714 std::__invoke(__proj, __tmp),
715 std::__invoke(__proj, __result)))
716 __result = std::move(__tmp);
717 }
718 return __result;
719 }
720
721 template<copyable _Tp, typename _Proj = identity,
722 indirect_strict_weak_order<projected<const _Tp*, _Proj>>
723 _Comp = ranges::less>
724 constexpr _Tp
725 operator()(initializer_list<_Tp> __r,
726 _Comp __comp = {}, _Proj __proj = {}) const
727 {
728 return (*this)(ranges::subrange(__r),
729 std::move(__comp), std::move(__proj));
730 }
731 };
732
733 inline constexpr __min_fn min{};
734
735 struct __adjacent_find_fn
736 {
737 template<forward_iterator _Iter, sentinel_for<_Iter> _Sent,
738 typename _Proj = identity,
739 indirect_binary_predicate<projected<_Iter, _Proj>,
740 projected<_Iter, _Proj>> _Pred
741 = ranges::equal_to>
742 constexpr _Iter
743 operator()(_Iter __first, _Sent __last,
744 _Pred __pred = {}, _Proj __proj = {}) const
745 {
746 if (__first == __last)
747 return __first;
748 auto __next = __first;
749 for (; ++__next != __last; __first = __next)
750 {
751 if (std::__invoke(__pred,
752 std::__invoke(__proj, *__first),
753 std::__invoke(__proj, *__next)))
754 return __first;
755 }
756 return __next;
757 }
758
759 template<forward_range _Range, typename _Proj = identity,
760 indirect_binary_predicate<
761 projected<iterator_t<_Range>, _Proj>,
762 projected<iterator_t<_Range>, _Proj>> _Pred = ranges::equal_to>
763 constexpr borrowed_iterator_t<_Range>
764 operator()(_Range&& __r, _Pred __pred = {}, _Proj __proj = {}) const
765 {
766 return (*this)(ranges::begin(__r), ranges::end(__r),
767 std::move(__pred), std::move(__proj));
768 }
769 };
770
771 inline constexpr __adjacent_find_fn adjacent_find{};
772
773} // namespace ranges
774
775 using ranges::get;
776
777 template<typename _Iter, typename _Sent, ranges::subrange_kind _Kind>
778 struct tuple_size<ranges::subrange<_Iter, _Sent, _Kind>>
779 : integral_constant<size_t, 2>
780 { };
781
782 template<typename _Iter, typename _Sent, ranges::subrange_kind _Kind>
783 struct tuple_element<0, ranges::subrange<_Iter, _Sent, _Kind>>
784 { using type = _Iter; };
785
786 template<typename _Iter, typename _Sent, ranges::subrange_kind _Kind>
787 struct tuple_element<1, ranges::subrange<_Iter, _Sent, _Kind>>
788 { using type = _Sent; };
789
790 template<typename _Iter, typename _Sent, ranges::subrange_kind _Kind>
791 struct tuple_element<0, const ranges::subrange<_Iter, _Sent, _Kind>>
792 { using type = _Iter; };
793
794 template<typename _Iter, typename _Sent, ranges::subrange_kind _Kind>
795 struct tuple_element<1, const ranges::subrange<_Iter, _Sent, _Kind>>
796 { using type = _Sent; };
797
798_GLIBCXX_END_NAMESPACE_VERSION
799} // namespace std
800#endif // library concepts
801#endif // C++20
802#endif // _RANGES_UTIL_H
constexpr _Tp * to_address(_Tp *__ptr) noexcept
Obtain address referenced by a pointer to an object.
Definition: ptr_traits.h:250
typename remove_pointer< _Tp >::type remove_pointer_t
Alias template for remove_pointer.
Definition: type_traits:2065
typename decay< _Tp >::type decay_t
Alias template for decay.
Definition: type_traits:2606
constexpr std::remove_reference< _Tp >::type && move(_Tp &&__t) noexcept
Convert a value to an rvalue.
Definition: move.h:104
constexpr __invoke_result< _Callable, _Args... >::type __invoke(_Callable &&__fn, _Args &&... __args) noexcept(__is_nothrow_invocable< _Callable, _Args... >::value)
Invoke a callable object.
Definition: invoke.h:90
_Tp * end(valarray< _Tp > &__va) noexcept
Return an iterator pointing to one past the last element of the valarray.
Definition: valarray:1243
_Tp * begin(valarray< _Tp > &__va) noexcept
Return an iterator pointing to the first element of the valarray.
Definition: valarray:1221
ISO C++ entities toplevel namespace is std.
constexpr auto cend(const _Container &__cont) noexcept(noexcept(std::end(__cont))) -> decltype(std::end(__cont))
Return an iterator pointing to one past the last element of the const container.
Definition: range_access.h:138
constexpr auto empty(const _Container &__cont) noexcept(noexcept(__cont.empty())) -> decltype(__cont.empty())
Return whether a container is empty.
Definition: range_access.h:284
constexpr auto size(const _Container &__cont) noexcept(noexcept(__cont.size())) -> decltype(__cont.size())
Return the size of a container.
Definition: range_access.h:264
constexpr auto cbegin(const _Container &__cont) noexcept(noexcept(std::begin(__cont))) -> decltype(std::begin(__cont))
Return an iterator pointing to the first element of the const container.
Definition: range_access.h:126
integral_constant
Definition: type_traits:63
The ranges::view_interface class template.
Definition: ranges_util.h:63
The ranges::subrange class template.
Definition: ranges_util.h:257
Finds the size of a given tuple type.
Definition: utility.h:49
[concept.derived], concept derived_from
Definition: concepts:67
[concept.convertible], concept convertible_to
Definition: concepts:72
[concept.defaultinitializable], concept default_initializable
Definition: concepts:157
[range.range] The range concept.
Definition: ranges_base.h:501
[range.range] The borrowed_range concept.
Definition: ranges_base.h:510
[range.sized] The sized_range concept.
Definition: ranges_base.h:544
[range.view] The ranges::view concept.
Definition: ranges_base.h:579
A range for which ranges::begin returns an input iterator.
Definition: ranges_base.h:590
A range for which ranges::begin returns a forward iterator.
Definition: ranges_base.h:595
A range for which ranges::begin returns a bidirectional iterator.
Definition: ranges_base.h:600
A range for which ranges::begin and ranges::end return the same type.
Definition: ranges_base.h:619