xref: /netbsd-src/external/gpl3/gcc/dist/libstdc++-v3/include/bits/ranges_util.h (revision b1e838363e3c6fc78a55519254d99869742dd33c)
1 // Utilities for representing and manipulating ranges -*- C++ -*-
2 
3 // Copyright (C) 2019-2022 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
_GLIBCXX_VISIBILITY(default)38 namespace std _GLIBCXX_VISIBILITY(default)
39 {
40 _GLIBCXX_BEGIN_NAMESPACE_VERSION
41 namespace 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     template<typename _Tp, typename _Up>
57       concept __different_from
58 	= !same_as<remove_cvref_t<_Tp>, remove_cvref_t<_Up>>;
59   } // namespace __detail
60 
61   /// The ranges::view_interface class template
62   template<typename _Derived>
63     requires is_class_v<_Derived> && same_as<_Derived, remove_cv_t<_Derived>>
64     class view_interface
65     {
66     private:
67       constexpr _Derived& _M_derived() noexcept
68       {
69 	static_assert(derived_from<_Derived, view_interface<_Derived>>);
70 	static_assert(view<_Derived>);
71 	return static_cast<_Derived&>(*this);
72       }
73 
74       constexpr const _Derived& _M_derived() const noexcept
75       {
76 	static_assert(derived_from<_Derived, view_interface<_Derived>>);
77 	static_assert(view<_Derived>);
78 	return static_cast<const _Derived&>(*this);
79       }
80 
81       static constexpr bool
82       _S_bool(bool) noexcept; // not defined
83 
84       template<typename _Tp>
85 	static constexpr bool
86 	_S_empty(_Tp& __t)
87 	noexcept(noexcept(_S_bool(ranges::begin(__t) == ranges::end(__t))))
88 	{ return ranges::begin(__t) == ranges::end(__t); }
89 
90       template<typename _Tp>
91 	static constexpr auto
92 	_S_size(_Tp& __t)
93 	noexcept(noexcept(ranges::end(__t) - ranges::begin(__t)))
94 	{ return ranges::end(__t) - ranges::begin(__t); }
95 
96     public:
97       constexpr bool
98       empty()
99       noexcept(noexcept(_S_empty(_M_derived())))
100       requires forward_range<_Derived>
101       { return _S_empty(_M_derived()); }
102 
103       constexpr bool
104       empty() const
105       noexcept(noexcept(_S_empty(_M_derived())))
106       requires forward_range<const _Derived>
107       { return _S_empty(_M_derived()); }
108 
109       constexpr explicit
110       operator bool() noexcept(noexcept(ranges::empty(_M_derived())))
111       requires requires { ranges::empty(_M_derived()); }
112       { return !ranges::empty(_M_derived()); }
113 
114       constexpr explicit
115       operator bool() const noexcept(noexcept(ranges::empty(_M_derived())))
116       requires requires { ranges::empty(_M_derived()); }
117       { return !ranges::empty(_M_derived()); }
118 
119       constexpr auto
120       data() noexcept(noexcept(ranges::begin(_M_derived())))
121       requires contiguous_iterator<iterator_t<_Derived>>
122       { return std::to_address(ranges::begin(_M_derived())); }
123 
124       constexpr auto
125       data() const noexcept(noexcept(ranges::begin(_M_derived())))
126       requires range<const _Derived>
127 	&& contiguous_iterator<iterator_t<const _Derived>>
128       { return std::to_address(ranges::begin(_M_derived())); }
129 
130       constexpr auto
131       size() noexcept(noexcept(_S_size(_M_derived())))
132       requires forward_range<_Derived>
133 	&& sized_sentinel_for<sentinel_t<_Derived>, iterator_t<_Derived>>
134       { return _S_size(_M_derived()); }
135 
136       constexpr auto
137       size() const noexcept(noexcept(_S_size(_M_derived())))
138       requires forward_range<const _Derived>
139 	&& sized_sentinel_for<sentinel_t<const _Derived>,
140 			      iterator_t<const _Derived>>
141       { return _S_size(_M_derived()); }
142 
143       constexpr decltype(auto)
144       front() requires forward_range<_Derived>
145       {
146 	__glibcxx_assert(!empty());
147 	return *ranges::begin(_M_derived());
148       }
149 
150       constexpr decltype(auto)
151       front() const requires forward_range<const _Derived>
152       {
153 	__glibcxx_assert(!empty());
154 	return *ranges::begin(_M_derived());
155       }
156 
157       constexpr decltype(auto)
158       back()
159       requires bidirectional_range<_Derived> && common_range<_Derived>
160       {
161 	__glibcxx_assert(!empty());
162 	return *ranges::prev(ranges::end(_M_derived()));
163       }
164 
165       constexpr decltype(auto)
166       back() const
167       requires bidirectional_range<const _Derived>
168 	&& common_range<const _Derived>
169       {
170 	__glibcxx_assert(!empty());
171 	return *ranges::prev(ranges::end(_M_derived()));
172       }
173 
174       template<random_access_range _Range = _Derived>
175 	constexpr decltype(auto)
176 	operator[](range_difference_t<_Range> __n)
177 	{ return ranges::begin(_M_derived())[__n]; }
178 
179       template<random_access_range _Range = const _Derived>
180 	constexpr decltype(auto)
181 	operator[](range_difference_t<_Range> __n) const
182 	{ return ranges::begin(_M_derived())[__n]; }
183     };
184 
185   namespace __detail
186   {
187     template<typename _From, typename _To>
188       concept __uses_nonqualification_pointer_conversion
189 	= is_pointer_v<_From> && is_pointer_v<_To>
190 	  && !convertible_to<remove_pointer_t<_From>(*)[],
191 			     remove_pointer_t<_To>(*)[]>;
192 
193     template<typename _From, typename _To>
194       concept __convertible_to_non_slicing = convertible_to<_From, _To>
195 	&& !__uses_nonqualification_pointer_conversion<decay_t<_From>,
196 						       decay_t<_To>>;
197 
198     template<typename _Tp>
199       concept __pair_like
200 	= !is_reference_v<_Tp> && requires(_Tp __t)
201 	{
202 	  typename tuple_size<_Tp>::type;
203 	  requires derived_from<tuple_size<_Tp>, integral_constant<size_t, 2>>;
204 	  typename tuple_element_t<0, remove_const_t<_Tp>>;
205 	  typename tuple_element_t<1, remove_const_t<_Tp>>;
206 	  { get<0>(__t) } -> convertible_to<const tuple_element_t<0, _Tp>&>;
207 	  { get<1>(__t) } -> convertible_to<const tuple_element_t<1, _Tp>&>;
208 	};
209 
210     template<typename _Tp, typename _Up, typename _Vp>
211       concept __pair_like_convertible_from
212 	= !range<_Tp> && __pair_like<_Tp>
213 	&& constructible_from<_Tp, _Up, _Vp>
214 	&& __convertible_to_non_slicing<_Up, tuple_element_t<0, _Tp>>
215 	&& convertible_to<_Vp, tuple_element_t<1, _Tp>>;
216 
217   } // namespace __detail
218 
219   namespace views { struct _Drop; } // defined in <ranges>
220 
221   enum class subrange_kind : bool { unsized, sized };
222 
223   /// The ranges::subrange class template
224   template<input_or_output_iterator _It, sentinel_for<_It> _Sent = _It,
225 	   subrange_kind _Kind = sized_sentinel_for<_Sent, _It>
226 	     ? subrange_kind::sized : subrange_kind::unsized>
227     requires (_Kind == subrange_kind::sized || !sized_sentinel_for<_Sent, _It>)
228     class subrange : public view_interface<subrange<_It, _Sent, _Kind>>
229     {
230     private:
231       static constexpr bool _S_store_size
232 	= _Kind == subrange_kind::sized && !sized_sentinel_for<_Sent, _It>;
233 
234       friend struct views::_Drop; // Needs to inspect _S_store_size.
235 
236       _It _M_begin = _It();
237       [[no_unique_address]] _Sent _M_end = _Sent();
238 
239       using __size_type
240 	= __detail::__make_unsigned_like_t<iter_difference_t<_It>>;
241 
242       template<typename, bool = _S_store_size>
243 	struct _Size
244 	{ };
245 
246       template<typename _Tp>
247 	struct _Size<_Tp, true>
248 	{ _Tp _M_size; };
249 
250       [[no_unique_address]] _Size<__size_type> _M_size = {};
251 
252     public:
253       subrange() requires default_initializable<_It> = default;
254 
255       constexpr
256       subrange(__detail::__convertible_to_non_slicing<_It> auto __i, _Sent __s)
257       noexcept(is_nothrow_constructible_v<_It, decltype(__i)>
258 	       && is_nothrow_constructible_v<_Sent, _Sent&>)
259 	requires (!_S_store_size)
260       : _M_begin(std::move(__i)), _M_end(__s)
261       { }
262 
263       constexpr
264       subrange(__detail::__convertible_to_non_slicing<_It> auto __i, _Sent __s,
265 	       __size_type __n)
266       noexcept(is_nothrow_constructible_v<_It, decltype(__i)>
267 	       && is_nothrow_constructible_v<_Sent, _Sent&>)
268 	requires (_Kind == subrange_kind::sized)
269       : _M_begin(std::move(__i)), _M_end(__s)
270       {
271 	if constexpr (_S_store_size)
272 	  _M_size._M_size = __n;
273       }
274 
275       template<__detail::__different_from<subrange> _Rng>
276 	requires borrowed_range<_Rng>
277 	  && __detail::__convertible_to_non_slicing<iterator_t<_Rng>, _It>
278 	  && convertible_to<sentinel_t<_Rng>, _Sent>
279 	constexpr
280 	subrange(_Rng&& __r)
281 	noexcept(noexcept(subrange(__r, ranges::size(__r))))
282 	requires _S_store_size && sized_range<_Rng>
283 	: subrange(__r, ranges::size(__r))
284 	{ }
285 
286       template<__detail::__different_from<subrange> _Rng>
287 	requires borrowed_range<_Rng>
288 	  && __detail::__convertible_to_non_slicing<iterator_t<_Rng>, _It>
289 	  && convertible_to<sentinel_t<_Rng>, _Sent>
290 	constexpr
291 	subrange(_Rng&& __r)
292 	noexcept(noexcept(subrange(ranges::begin(__r), ranges::end(__r))))
293 	requires (!_S_store_size)
294 	: subrange(ranges::begin(__r), ranges::end(__r))
295 	{ }
296 
297       template<borrowed_range _Rng>
298 	requires __detail::__convertible_to_non_slicing<iterator_t<_Rng>, _It>
299 	  && convertible_to<sentinel_t<_Rng>, _Sent>
300 	constexpr
301 	subrange(_Rng&& __r, __size_type __n)
302 	noexcept(noexcept(subrange(ranges::begin(__r), ranges::end(__r), __n)))
303 	requires (_Kind == subrange_kind::sized)
304 	: subrange{ranges::begin(__r), ranges::end(__r), __n}
305 	{ }
306 
307       template<__detail::__different_from<subrange> _PairLike>
308 	requires __detail::__pair_like_convertible_from<_PairLike, const _It&,
309 							const _Sent&>
310 	constexpr
311 	operator _PairLike() const
312 	{ return _PairLike(_M_begin, _M_end); }
313 
314       constexpr _It
315       begin() const requires copyable<_It>
316       { return _M_begin; }
317 
318       [[nodiscard]] constexpr _It
319       begin() requires (!copyable<_It>)
320       { return std::move(_M_begin); }
321 
322       constexpr _Sent end() const { return _M_end; }
323 
324       constexpr bool empty() const { return _M_begin == _M_end; }
325 
326       constexpr __size_type
327       size() const requires (_Kind == subrange_kind::sized)
328       {
329 	if constexpr (_S_store_size)
330 	  return _M_size._M_size;
331 	else
332 	  return __detail::__to_unsigned_like(_M_end - _M_begin);
333       }
334 
335       [[nodiscard]] constexpr subrange
336       next(iter_difference_t<_It> __n = 1) const &
337 	requires forward_iterator<_It>
338       {
339 	auto __tmp = *this;
340 	__tmp.advance(__n);
341 	return __tmp;
342       }
343 
344       [[nodiscard]] constexpr subrange
345       next(iter_difference_t<_It> __n = 1) &&
346       {
347 	advance(__n);
348 	return std::move(*this);
349       }
350 
351       [[nodiscard]] constexpr subrange
352       prev(iter_difference_t<_It> __n = 1) const
353 	requires bidirectional_iterator<_It>
354       {
355 	auto __tmp = *this;
356 	__tmp.advance(-__n);
357 	return __tmp;
358       }
359 
360       constexpr subrange&
361       advance(iter_difference_t<_It> __n)
362       {
363 	// _GLIBCXX_RESOLVE_LIB_DEFECTS
364 	// 3433. subrange::advance(n) has UB when n < 0
365 	if constexpr (bidirectional_iterator<_It>)
366 	  if (__n < 0)
367 	    {
368 	      ranges::advance(_M_begin, __n);
369 	      if constexpr (_S_store_size)
370 		_M_size._M_size += __detail::__to_unsigned_like(-__n);
371 	      return *this;
372 	    }
373 
374 	__glibcxx_assert(__n >= 0);
375 	auto __d = __n - ranges::advance(_M_begin, __n, _M_end);
376 	if constexpr (_S_store_size)
377 	  _M_size._M_size -= __detail::__to_unsigned_like(__d);
378 	return *this;
379       }
380     };
381 
382   template<input_or_output_iterator _It, sentinel_for<_It> _Sent>
383     subrange(_It, _Sent) -> subrange<_It, _Sent>;
384 
385   template<input_or_output_iterator _It, sentinel_for<_It> _Sent>
386     subrange(_It, _Sent,
387 	     __detail::__make_unsigned_like_t<iter_difference_t<_It>>)
388       -> subrange<_It, _Sent, subrange_kind::sized>;
389 
390   template<borrowed_range _Rng>
391     subrange(_Rng&&)
392       -> subrange<iterator_t<_Rng>, sentinel_t<_Rng>,
393 		 (sized_range<_Rng>
394 		  || sized_sentinel_for<sentinel_t<_Rng>, iterator_t<_Rng>>)
395 		 ? subrange_kind::sized : subrange_kind::unsized>;
396 
397   template<borrowed_range _Rng>
398     subrange(_Rng&&,
399 	     __detail::__make_unsigned_like_t<range_difference_t<_Rng>>)
400       -> subrange<iterator_t<_Rng>, sentinel_t<_Rng>, subrange_kind::sized>;
401 
402   template<size_t _Num, class _It, class _Sent, subrange_kind _Kind>
403     requires (_Num < 2)
404     constexpr auto
405     get(const subrange<_It, _Sent, _Kind>& __r)
406     {
407       if constexpr (_Num == 0)
408 	return __r.begin();
409       else
410 	return __r.end();
411     }
412 
413   template<size_t _Num, class _It, class _Sent, subrange_kind _Kind>
414     requires (_Num < 2)
415     constexpr auto
416     get(subrange<_It, _Sent, _Kind>&& __r)
417     {
418       if constexpr (_Num == 0)
419 	return __r.begin();
420       else
421 	return __r.end();
422     }
423 
424   template<typename _It, typename _Sent, subrange_kind _Kind>
425     inline constexpr bool
426       enable_borrowed_range<subrange<_It, _Sent, _Kind>> = true;
427 
428   template<range _Range>
429     using borrowed_subrange_t = __conditional_t<borrowed_range<_Range>,
430 						subrange<iterator_t<_Range>>,
431 						dangling>;
432 } // namespace ranges
433 
434 // The following ranges algorithms are used by <ranges>, and are defined here
435 // so that <ranges> can avoid including all of <bits/ranges_algo.h>.
436 namespace ranges
437 {
438   struct __find_fn
439   {
440     template<input_iterator _Iter, sentinel_for<_Iter> _Sent, typename _Tp,
441 	     typename _Proj = identity>
442       requires indirect_binary_predicate<ranges::equal_to,
443 					 projected<_Iter, _Proj>, const _Tp*>
444       constexpr _Iter
445       operator()(_Iter __first, _Sent __last,
446 		 const _Tp& __value, _Proj __proj = {}) const
447       {
448 	while (__first != __last
449 	    && !(std::__invoke(__proj, *__first) == __value))
450 	  ++__first;
451 	return __first;
452       }
453 
454     template<input_range _Range, typename _Tp, typename _Proj = identity>
455       requires indirect_binary_predicate<ranges::equal_to,
456 					 projected<iterator_t<_Range>, _Proj>,
457 					 const _Tp*>
458       constexpr borrowed_iterator_t<_Range>
459       operator()(_Range&& __r, const _Tp& __value, _Proj __proj = {}) const
460       {
461 	return (*this)(ranges::begin(__r), ranges::end(__r),
462 		       __value, std::move(__proj));
463       }
464   };
465 
466   inline constexpr __find_fn find{};
467 
468   struct __find_if_fn
469   {
470     template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
471 	     typename _Proj = identity,
472 	     indirect_unary_predicate<projected<_Iter, _Proj>> _Pred>
473       constexpr _Iter
474       operator()(_Iter __first, _Sent __last,
475 		 _Pred __pred, _Proj __proj = {}) const
476       {
477 	while (__first != __last
478 	    && !(bool)std::__invoke(__pred, std::__invoke(__proj, *__first)))
479 	  ++__first;
480 	return __first;
481       }
482 
483     template<input_range _Range, typename _Proj = identity,
484 	     indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>>
485 	       _Pred>
486       constexpr borrowed_iterator_t<_Range>
487       operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const
488       {
489 	return (*this)(ranges::begin(__r), ranges::end(__r),
490 		       std::move(__pred), std::move(__proj));
491       }
492   };
493 
494   inline constexpr __find_if_fn find_if{};
495 
496   struct __find_if_not_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_not_fn find_if_not{};
523 
524   template<typename _Iter1, typename _Iter2>
525     struct in_in_result
526     {
527       [[no_unique_address]] _Iter1 in1;
528       [[no_unique_address]] _Iter2 in2;
529 
530       template<typename _IIter1, typename _IIter2>
531 	requires convertible_to<const _Iter1&, _IIter1>
532 	  && convertible_to<const _Iter2&, _IIter2>
533 	constexpr
534 	operator in_in_result<_IIter1, _IIter2>() const &
535 	{ return {in1, in2}; }
536 
537       template<typename _IIter1, typename _IIter2>
538 	requires convertible_to<_Iter1, _IIter1>
539 	  && convertible_to<_Iter2, _IIter2>
540 	constexpr
541 	operator in_in_result<_IIter1, _IIter2>() &&
542 	{ return {std::move(in1), std::move(in2)}; }
543     };
544 
545   template<typename _Iter1, typename _Iter2>
546     using mismatch_result = in_in_result<_Iter1, _Iter2>;
547 
548   struct __mismatch_fn
549   {
550     template<input_iterator _Iter1, sentinel_for<_Iter1> _Sent1,
551 	     input_iterator _Iter2, sentinel_for<_Iter2> _Sent2,
552 	     typename _Pred = ranges::equal_to,
553 	     typename _Proj1 = identity, typename _Proj2 = identity>
554       requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2>
555       constexpr mismatch_result<_Iter1, _Iter2>
556       operator()(_Iter1 __first1, _Sent1 __last1,
557 		 _Iter2 __first2, _Sent2 __last2, _Pred __pred = {},
558 		 _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const
559       {
560 	while (__first1 != __last1 && __first2 != __last2
561 	       && (bool)std::__invoke(__pred,
562 				      std::__invoke(__proj1, *__first1),
563 				      std::__invoke(__proj2, *__first2)))
564 	{
565 	  ++__first1;
566 	  ++__first2;
567 	}
568 	return { std::move(__first1), std::move(__first2) };
569       }
570 
571     template<input_range _Range1, input_range _Range2,
572 	     typename _Pred = ranges::equal_to,
573 	     typename _Proj1 = identity, typename _Proj2 = identity>
574       requires indirectly_comparable<iterator_t<_Range1>, iterator_t<_Range2>,
575 				     _Pred, _Proj1, _Proj2>
576       constexpr mismatch_result<iterator_t<_Range1>, iterator_t<_Range2>>
577       operator()(_Range1&& __r1, _Range2&& __r2, _Pred __pred = {},
578 		 _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const
579       {
580 	return (*this)(ranges::begin(__r1), ranges::end(__r1),
581 		       ranges::begin(__r2), ranges::end(__r2),
582 		       std::move(__pred),
583 		       std::move(__proj1), std::move(__proj2));
584       }
585   };
586 
587   inline constexpr __mismatch_fn mismatch{};
588 
589   struct __search_fn
590   {
591     template<forward_iterator _Iter1, sentinel_for<_Iter1> _Sent1,
592 	     forward_iterator _Iter2, sentinel_for<_Iter2> _Sent2,
593 	     typename _Pred = ranges::equal_to,
594 	     typename _Proj1 = identity, typename _Proj2 = identity>
595       requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2>
596       constexpr subrange<_Iter1>
597       operator()(_Iter1 __first1, _Sent1 __last1,
598 		 _Iter2 __first2, _Sent2 __last2, _Pred __pred = {},
599 		 _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const
600       {
601 	if (__first1 == __last1 || __first2 == __last2)
602 	  return {__first1, __first1};
603 
604 	for (;;)
605 	  {
606 	    for (;;)
607 	      {
608 		if (__first1 == __last1)
609 		  return {__first1, __first1};
610 		if (std::__invoke(__pred,
611 				  std::__invoke(__proj1, *__first1),
612 				  std::__invoke(__proj2, *__first2)))
613 		  break;
614 		++__first1;
615 	      }
616 	    auto __cur1 = __first1;
617 	    auto __cur2 = __first2;
618 	    for (;;)
619 	      {
620 		if (++__cur2 == __last2)
621 		  return {__first1, ++__cur1};
622 		if (++__cur1 == __last1)
623 		  return {__cur1, __cur1};
624 		if (!(bool)std::__invoke(__pred,
625 					 std::__invoke(__proj1, *__cur1),
626 					 std::__invoke(__proj2, *__cur2)))
627 		  {
628 		    ++__first1;
629 		    break;
630 		  }
631 	      }
632 	  }
633       }
634 
635     template<forward_range _Range1, forward_range _Range2,
636 	     typename _Pred = ranges::equal_to,
637 	     typename _Proj1 = identity, typename _Proj2 = identity>
638       requires indirectly_comparable<iterator_t<_Range1>, iterator_t<_Range2>,
639 				     _Pred, _Proj1, _Proj2>
640       constexpr borrowed_subrange_t<_Range1>
641       operator()(_Range1&& __r1, _Range2&& __r2, _Pred __pred = {},
642 		 _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const
643       {
644 	return (*this)(ranges::begin(__r1), ranges::end(__r1),
645 		       ranges::begin(__r2), ranges::end(__r2),
646 		       std::move(__pred),
647 		       std::move(__proj1), std::move(__proj2));
648       }
649   };
650 
651   inline constexpr __search_fn search{};
652 } // namespace ranges
653 
654   using ranges::get;
655 
656   template<typename _Iter, typename _Sent, ranges::subrange_kind _Kind>
657     struct tuple_size<ranges::subrange<_Iter, _Sent, _Kind>>
658     : integral_constant<size_t, 2>
659     { };
660 
661   template<typename _Iter, typename _Sent, ranges::subrange_kind _Kind>
662     struct tuple_element<0, ranges::subrange<_Iter, _Sent, _Kind>>
663     { using type = _Iter; };
664 
665   template<typename _Iter, typename _Sent, ranges::subrange_kind _Kind>
666     struct tuple_element<1, ranges::subrange<_Iter, _Sent, _Kind>>
667     { using type = _Sent; };
668 
669   template<typename _Iter, typename _Sent, ranges::subrange_kind _Kind>
670     struct tuple_element<0, const ranges::subrange<_Iter, _Sent, _Kind>>
671     { using type = _Iter; };
672 
673   template<typename _Iter, typename _Sent, ranges::subrange_kind _Kind>
674     struct tuple_element<1, const ranges::subrange<_Iter, _Sent, _Kind>>
675     { using type = _Sent; };
676 
677 _GLIBCXX_END_NAMESPACE_VERSION
678 } // namespace std
679 #endif // library concepts
680 #endif // C++20
681 #endif // _RANGES_UTIL_H
682