1 // Concepts and traits for use with iterators -*- 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/iterator_concepts.h
26 * This is an internal header file, included by other library headers.
27 * Do not attempt to use it directly. @headername{iterator}
28 */
29
30 #ifndef _ITERATOR_CONCEPTS_H
31 #define _ITERATOR_CONCEPTS_H 1
32
33 #pragma GCC system_header
34
35 #if __cplusplus >= 202002L
36 #include <concepts>
37 #include <bits/ptr_traits.h> // to_address
38 #include <bits/ranges_cmp.h> // identity, ranges::less
39
_GLIBCXX_VISIBILITY(default)40 namespace std _GLIBCXX_VISIBILITY(default)
41 {
42 _GLIBCXX_BEGIN_NAMESPACE_VERSION
43
44 /** A sentinel type that can be used to check for the end of a range.
45 *
46 * For some iterator types the past-the-end sentinel value is independent
47 * of the underlying sequence, and a default sentinel can be used with them.
48 * For example, a `std::counted_iterator` keeps a count of how many elements
49 * remain, and so checking for the past-the-end value only requires checking
50 * if that count has reached zero. A past-the-end `std::istream_iterator` is
51 * equal to the default-constructed value, which can be easily checked.
52 *
53 * Comparing iterators of these types to `std::default_sentinel` is a
54 * convenient way to check if the end has been reached.
55 *
56 * @since C++20
57 */
58 struct default_sentinel_t { };
59
60 /// A default sentinel value.
61 inline constexpr default_sentinel_t default_sentinel{};
62
63 #if __cpp_lib_concepts
64 struct input_iterator_tag;
65 struct output_iterator_tag;
66 struct forward_iterator_tag;
67 struct bidirectional_iterator_tag;
68 struct random_access_iterator_tag;
69 struct contiguous_iterator_tag;
70
71 template<typename _Iterator>
72 struct iterator_traits;
73
74 template<typename _Tp> requires is_object_v<_Tp>
75 struct iterator_traits<_Tp*>;
76
77 template<typename _Iterator, typename>
78 struct __iterator_traits;
79
80 namespace __detail
81 {
82 template<typename _Tp>
83 using __with_ref = _Tp&;
84
85 template<typename _Tp>
86 concept __can_reference = requires { typename __with_ref<_Tp>; };
87
88 template<typename _Tp>
89 concept __dereferenceable = requires(_Tp& __t)
90 {
91 { *__t } -> __can_reference;
92 };
93 } // namespace __detail
94
95 template<__detail::__dereferenceable _Tp>
96 using iter_reference_t = decltype(*std::declval<_Tp&>());
97
98 namespace ranges
99 {
100 namespace __cust_imove
101 {
102 void iter_move();
103
104 template<typename _Tp>
105 concept __adl_imove
106 = (std::__detail::__class_or_enum<remove_reference_t<_Tp>>)
107 && requires(_Tp&& __t) { iter_move(static_cast<_Tp&&>(__t)); };
108
109 struct _IMove
110 {
111 private:
112 template<typename _Tp>
113 struct __result
114 { using type = iter_reference_t<_Tp>; };
115
116 template<typename _Tp>
117 requires __adl_imove<_Tp>
118 struct __result<_Tp>
119 { using type = decltype(iter_move(std::declval<_Tp>())); };
120
121 template<typename _Tp>
122 requires (!__adl_imove<_Tp>)
123 && is_lvalue_reference_v<iter_reference_t<_Tp>>
124 struct __result<_Tp>
125 { using type = remove_reference_t<iter_reference_t<_Tp>>&&; };
126
127 template<typename _Tp>
128 static constexpr bool
129 _S_noexcept()
130 {
131 if constexpr (__adl_imove<_Tp>)
132 return noexcept(iter_move(std::declval<_Tp>()));
133 else
134 return noexcept(*std::declval<_Tp>());
135 }
136
137 public:
138 // The result type of iter_move(std::declval<_Tp>())
139 template<std::__detail::__dereferenceable _Tp>
140 using __type = typename __result<_Tp>::type;
141
142 template<std::__detail::__dereferenceable _Tp>
143 [[nodiscard]]
144 constexpr __type<_Tp>
145 operator()(_Tp&& __e) const
146 noexcept(_S_noexcept<_Tp>())
147 {
148 if constexpr (__adl_imove<_Tp>)
149 return iter_move(static_cast<_Tp&&>(__e));
150 else if constexpr (is_lvalue_reference_v<iter_reference_t<_Tp>>)
151 return static_cast<__type<_Tp>>(*__e);
152 else
153 return *__e;
154 }
155 };
156 } // namespace __cust_imove
157
158 inline namespace __cust
159 {
160 inline constexpr __cust_imove::_IMove iter_move{};
161 } // inline namespace __cust
162 } // namespace ranges
163
164 template<__detail::__dereferenceable _Tp>
165 requires __detail::
166 __can_reference<ranges::__cust_imove::_IMove::__type<_Tp&>>
167 using iter_rvalue_reference_t
168 = ranges::__cust_imove::_IMove::__type<_Tp&>;
169
170 template<typename> struct incrementable_traits { };
171
172 template<typename _Tp> requires is_object_v<_Tp>
173 struct incrementable_traits<_Tp*>
174 { using difference_type = ptrdiff_t; };
175
176 template<typename _Iter>
177 struct incrementable_traits<const _Iter>
178 : incrementable_traits<_Iter> { };
179
180 template<typename _Tp> requires requires { typename _Tp::difference_type; }
181 struct incrementable_traits<_Tp>
182 { using difference_type = typename _Tp::difference_type; };
183
184 template<typename _Tp>
185 requires (!requires { typename _Tp::difference_type; }
186 && requires(const _Tp& __a, const _Tp& __b)
187 { { __a - __b } -> integral; })
188 struct incrementable_traits<_Tp>
189 {
190 using difference_type
191 = make_signed_t<decltype(std::declval<_Tp>() - std::declval<_Tp>())>;
192 };
193
194 #if defined __STRICT_ANSI__ && defined __SIZEOF_INT128__
195 // __int128 is incrementable even if !integral<__int128>
196 template<>
197 struct incrementable_traits<__int128>
198 { using difference_type = __int128; };
199
200 template<>
201 struct incrementable_traits<unsigned __int128>
202 { using difference_type = __int128; };
203 #endif
204
205 namespace __detail
206 {
207 // An iterator such that iterator_traits<_Iter> names a specialization
208 // generated from the primary template.
209 template<typename _Iter>
210 concept __primary_traits_iter
211 = __is_base_of(__iterator_traits<_Iter, void>, iterator_traits<_Iter>);
212
213 template<typename _Iter, typename _Tp>
214 struct __iter_traits_impl
215 { using type = iterator_traits<_Iter>; };
216
217 template<typename _Iter, typename _Tp>
218 requires __primary_traits_iter<_Iter>
219 struct __iter_traits_impl<_Iter, _Tp>
220 { using type = _Tp; };
221
222 // ITER_TRAITS
223 template<typename _Iter, typename _Tp = _Iter>
224 using __iter_traits = typename __iter_traits_impl<_Iter, _Tp>::type;
225
226 template<typename _Tp>
227 using __iter_diff_t = typename
228 __iter_traits<_Tp, incrementable_traits<_Tp>>::difference_type;
229 } // namespace __detail
230
231 template<typename _Tp>
232 using iter_difference_t = __detail::__iter_diff_t<remove_cvref_t<_Tp>>;
233
234 namespace __detail
235 {
236 template<typename> struct __cond_value_type { };
237
238 template<typename _Tp> requires is_object_v<_Tp>
239 struct __cond_value_type<_Tp>
240 { using value_type = remove_cv_t<_Tp>; };
241
242 template<typename _Tp>
243 concept __has_member_value_type
244 = requires { typename _Tp::value_type; };
245
246 template<typename _Tp>
247 concept __has_member_element_type
248 = requires { typename _Tp::element_type; };
249
250 } // namespace __detail
251
252 template<typename> struct indirectly_readable_traits { };
253
254 template<typename _Tp>
255 struct indirectly_readable_traits<_Tp*>
256 : __detail::__cond_value_type<_Tp>
257 { };
258
259 template<typename _Iter> requires is_array_v<_Iter>
260 struct indirectly_readable_traits<_Iter>
261 { using value_type = remove_cv_t<remove_extent_t<_Iter>>; };
262
263 template<typename _Iter>
264 struct indirectly_readable_traits<const _Iter>
265 : indirectly_readable_traits<_Iter>
266 { };
267
268 template<__detail::__has_member_value_type _Tp>
269 struct indirectly_readable_traits<_Tp>
270 : __detail::__cond_value_type<typename _Tp::value_type>
271 { };
272
273 template<__detail::__has_member_element_type _Tp>
274 struct indirectly_readable_traits<_Tp>
275 : __detail::__cond_value_type<typename _Tp::element_type>
276 { };
277
278 // _GLIBCXX_RESOLVE_LIB_DEFECTS
279 // 3446. indirectly_readable_traits ambiguity for types with both [...]
280 template<__detail::__has_member_value_type _Tp>
281 requires __detail::__has_member_element_type<_Tp>
282 && same_as<remove_cv_t<typename _Tp::element_type>,
283 remove_cv_t<typename _Tp::value_type>>
284 struct indirectly_readable_traits<_Tp>
285 : __detail::__cond_value_type<typename _Tp::value_type>
286 { };
287
288 // _GLIBCXX_RESOLVE_LIB_DEFECTS
289 // 3541. indirectly_readable_traits should be SFINAE-friendly for all types
290 template<__detail::__has_member_value_type _Tp>
291 requires __detail::__has_member_element_type<_Tp>
292 struct indirectly_readable_traits<_Tp>
293 { };
294
295 namespace __detail
296 {
297 template<typename _Tp>
298 using __iter_value_t = typename
299 __iter_traits<_Tp, indirectly_readable_traits<_Tp>>::value_type;
300 } // namespace __detail
301
302 template<typename _Tp>
303 using iter_value_t = __detail::__iter_value_t<remove_cvref_t<_Tp>>;
304
305 namespace __detail
306 {
307 // _GLIBCXX_RESOLVE_LIB_DEFECTS
308 // 3420. cpp17-iterator should check [type] looks like an iterator first
309 template<typename _Iter>
310 concept __cpp17_iterator = requires(_Iter __it)
311 {
312 { *__it } -> __can_reference;
313 { ++__it } -> same_as<_Iter&>;
314 { *__it++ } -> __can_reference;
315 } && copyable<_Iter>;
316
317 template<typename _Iter>
318 concept __cpp17_input_iterator = __cpp17_iterator<_Iter>
319 && equality_comparable<_Iter>
320 && requires(_Iter __it)
321 {
322 typename incrementable_traits<_Iter>::difference_type;
323 typename indirectly_readable_traits<_Iter>::value_type;
324 typename common_reference_t<iter_reference_t<_Iter>&&,
325 typename indirectly_readable_traits<_Iter>::value_type&>;
326 typename common_reference_t<decltype(*__it++)&&,
327 typename indirectly_readable_traits<_Iter>::value_type&>;
328 requires signed_integral<
329 typename incrementable_traits<_Iter>::difference_type>;
330 };
331
332 template<typename _Iter>
333 concept __cpp17_fwd_iterator = __cpp17_input_iterator<_Iter>
334 && constructible_from<_Iter>
335 && is_lvalue_reference_v<iter_reference_t<_Iter>>
336 && same_as<remove_cvref_t<iter_reference_t<_Iter>>,
337 typename indirectly_readable_traits<_Iter>::value_type>
338 && requires(_Iter __it)
339 {
340 { __it++ } -> convertible_to<const _Iter&>;
341 { *__it++ } -> same_as<iter_reference_t<_Iter>>;
342 };
343
344 template<typename _Iter>
345 concept __cpp17_bidi_iterator = __cpp17_fwd_iterator<_Iter>
346 && requires(_Iter __it)
347 {
348 { --__it } -> same_as<_Iter&>;
349 { __it-- } -> convertible_to<const _Iter&>;
350 { *__it-- } -> same_as<iter_reference_t<_Iter>>;
351 };
352
353 template<typename _Iter>
354 concept __cpp17_randacc_iterator = __cpp17_bidi_iterator<_Iter>
355 && totally_ordered<_Iter>
356 && requires(_Iter __it,
357 typename incrementable_traits<_Iter>::difference_type __n)
358 {
359 { __it += __n } -> same_as<_Iter&>;
360 { __it -= __n } -> same_as<_Iter&>;
361 { __it + __n } -> same_as<_Iter>;
362 { __n + __it } -> same_as<_Iter>;
363 { __it - __n } -> same_as<_Iter>;
364 { __it - __it } -> same_as<decltype(__n)>;
365 { __it[__n] } -> convertible_to<iter_reference_t<_Iter>>;
366 };
367
368 template<typename _Iter>
369 concept __iter_with_nested_types = requires {
370 typename _Iter::iterator_category;
371 typename _Iter::value_type;
372 typename _Iter::difference_type;
373 typename _Iter::reference;
374 };
375
376 template<typename _Iter>
377 concept __iter_without_nested_types = !__iter_with_nested_types<_Iter>;
378
379 template<typename _Iter>
380 concept __iter_without_category
381 = !requires { typename _Iter::iterator_category; };
382
383 } // namespace __detail
384
385 template<typename _Iterator>
386 requires __detail::__iter_with_nested_types<_Iterator>
387 struct __iterator_traits<_Iterator, void>
388 {
389 private:
390 template<typename _Iter>
391 struct __ptr
392 { using type = void; };
393
394 template<typename _Iter> requires requires { typename _Iter::pointer; }
395 struct __ptr<_Iter>
396 { using type = typename _Iter::pointer; };
397
398 public:
399 using iterator_category = typename _Iterator::iterator_category;
400 using value_type = typename _Iterator::value_type;
401 using difference_type = typename _Iterator::difference_type;
402 using pointer = typename __ptr<_Iterator>::type;
403 using reference = typename _Iterator::reference;
404 };
405
406 template<typename _Iterator>
407 requires __detail::__iter_without_nested_types<_Iterator>
408 && __detail::__cpp17_input_iterator<_Iterator>
409 struct __iterator_traits<_Iterator, void>
410 {
411 private:
412 template<typename _Iter>
413 struct __cat
414 { using type = input_iterator_tag; };
415
416 template<typename _Iter>
417 requires requires { typename _Iter::iterator_category; }
418 struct __cat<_Iter>
419 { using type = typename _Iter::iterator_category; };
420
421 template<typename _Iter>
422 requires __detail::__iter_without_category<_Iter>
423 && __detail::__cpp17_randacc_iterator<_Iter>
424 struct __cat<_Iter>
425 { using type = random_access_iterator_tag; };
426
427 template<typename _Iter>
428 requires __detail::__iter_without_category<_Iter>
429 && __detail::__cpp17_bidi_iterator<_Iter>
430 struct __cat<_Iter>
431 { using type = bidirectional_iterator_tag; };
432
433 template<typename _Iter>
434 requires __detail::__iter_without_category<_Iter>
435 && __detail::__cpp17_fwd_iterator<_Iter>
436 struct __cat<_Iter>
437 { using type = forward_iterator_tag; };
438
439 template<typename _Iter>
440 struct __ptr
441 { using type = void; };
442
443 template<typename _Iter> requires requires { typename _Iter::pointer; }
444 struct __ptr<_Iter>
445 { using type = typename _Iter::pointer; };
446
447 template<typename _Iter>
448 requires (!requires { typename _Iter::pointer; }
449 && requires(_Iter& __it) { __it.operator->(); })
450 struct __ptr<_Iter>
451 { using type = decltype(std::declval<_Iter&>().operator->()); };
452
453 template<typename _Iter>
454 struct __ref
455 { using type = iter_reference_t<_Iter>; };
456
457 template<typename _Iter> requires requires { typename _Iter::reference; }
458 struct __ref<_Iter>
459 { using type = typename _Iter::reference; };
460
461 public:
462 using iterator_category = typename __cat<_Iterator>::type;
463 using value_type
464 = typename indirectly_readable_traits<_Iterator>::value_type;
465 using difference_type
466 = typename incrementable_traits<_Iterator>::difference_type;
467 using pointer = typename __ptr<_Iterator>::type;
468 using reference = typename __ref<_Iterator>::type;
469 };
470
471 template<typename _Iterator>
472 requires __detail::__iter_without_nested_types<_Iterator>
473 && __detail::__cpp17_iterator<_Iterator>
474 struct __iterator_traits<_Iterator, void>
475 {
476 private:
477 template<typename _Iter>
478 struct __diff
479 { using type = void; };
480
481 template<typename _Iter>
482 requires requires
483 { typename incrementable_traits<_Iter>::difference_type; }
484 struct __diff<_Iter>
485 {
486 using type = typename incrementable_traits<_Iter>::difference_type;
487 };
488
489 public:
490 using iterator_category = output_iterator_tag;
491 using value_type = void;
492 using difference_type = typename __diff<_Iterator>::type;
493 using pointer = void;
494 using reference = void;
495 };
496
497 namespace __detail
498 {
499 template<typename _Iter>
500 struct __iter_concept_impl;
501
502 // ITER_CONCEPT(I) is ITER_TRAITS(I)::iterator_concept if that is valid.
503 template<typename _Iter>
504 requires requires { typename __iter_traits<_Iter>::iterator_concept; }
505 struct __iter_concept_impl<_Iter>
506 { using type = typename __iter_traits<_Iter>::iterator_concept; };
507
508 // Otherwise, ITER_TRAITS(I)::iterator_category if that is valid.
509 template<typename _Iter>
510 requires (!requires { typename __iter_traits<_Iter>::iterator_concept; }
511 && requires { typename __iter_traits<_Iter>::iterator_category; })
512 struct __iter_concept_impl<_Iter>
513 { using type = typename __iter_traits<_Iter>::iterator_category; };
514
515 // Otherwise, random_access_tag if iterator_traits<I> is not specialized.
516 template<typename _Iter>
517 requires (!requires { typename __iter_traits<_Iter>::iterator_concept; }
518 && !requires { typename __iter_traits<_Iter>::iterator_category; }
519 && __primary_traits_iter<_Iter>)
520 struct __iter_concept_impl<_Iter>
521 { using type = random_access_iterator_tag; };
522
523 // Otherwise, there is no ITER_CONCEPT(I) type.
524 template<typename _Iter>
525 struct __iter_concept_impl
526 { };
527
528 // ITER_CONCEPT
529 template<typename _Iter>
530 using __iter_concept = typename __iter_concept_impl<_Iter>::type;
531
532 template<typename _In>
533 concept __indirectly_readable_impl = requires
534 {
535 typename iter_value_t<_In>;
536 typename iter_reference_t<_In>;
537 typename iter_rvalue_reference_t<_In>;
538 requires same_as<iter_reference_t<const _In>,
539 iter_reference_t<_In>>;
540 requires same_as<iter_rvalue_reference_t<const _In>,
541 iter_rvalue_reference_t<_In>>;
542 }
543 && common_reference_with<iter_reference_t<_In>&&, iter_value_t<_In>&>
544 && common_reference_with<iter_reference_t<_In>&&,
545 iter_rvalue_reference_t<_In>&&>
546 && common_reference_with<iter_rvalue_reference_t<_In>&&,
547 const iter_value_t<_In>&>;
548
549 } // namespace __detail
550
551 /// Requirements for types that are readable by applying operator*.
552 template<typename _In>
553 concept indirectly_readable
554 = __detail::__indirectly_readable_impl<remove_cvref_t<_In>>;
555
556 template<indirectly_readable _Tp>
557 using iter_common_reference_t
558 = common_reference_t<iter_reference_t<_Tp>, iter_value_t<_Tp>&>;
559
560 /// Requirements for writing a value into an iterator's referenced object.
561 template<typename _Out, typename _Tp>
562 concept indirectly_writable = requires(_Out&& __o, _Tp&& __t)
563 {
564 *__o = std::forward<_Tp>(__t);
565 *std::forward<_Out>(__o) = std::forward<_Tp>(__t);
566 const_cast<const iter_reference_t<_Out>&&>(*__o)
567 = std::forward<_Tp>(__t);
568 const_cast<const iter_reference_t<_Out>&&>(*std::forward<_Out>(__o))
569 = std::forward<_Tp>(__t);
570 };
571
572 namespace ranges::__detail
573 {
574 class __max_diff_type;
575 class __max_size_type;
576
577 __extension__
578 template<typename _Tp>
579 concept __is_signed_int128
580 #if __SIZEOF_INT128__
581 = same_as<_Tp, __int128>;
582 #else
583 = false;
584 #endif
585
586 __extension__
587 template<typename _Tp>
588 concept __is_unsigned_int128
589 #if __SIZEOF_INT128__
590 = same_as<_Tp, unsigned __int128>;
591 #else
592 = false;
593 #endif
594
595 template<typename _Tp>
596 concept __cv_bool = same_as<const volatile _Tp, const volatile bool>;
597
598 template<typename _Tp>
599 concept __integral_nonbool = integral<_Tp> && !__cv_bool<_Tp>;
600
601 template<typename _Tp>
602 concept __is_int128 = __is_signed_int128<_Tp> || __is_unsigned_int128<_Tp>;
603
604 template<typename _Tp>
605 concept __is_integer_like = __integral_nonbool<_Tp>
606 || __is_int128<_Tp>
607 || same_as<_Tp, __max_diff_type> || same_as<_Tp, __max_size_type>;
608
609 template<typename _Tp>
610 concept __is_signed_integer_like = signed_integral<_Tp>
611 || __is_signed_int128<_Tp>
612 || same_as<_Tp, __max_diff_type>;
613
614 } // namespace ranges::__detail
615
616 namespace __detail { using ranges::__detail::__is_signed_integer_like; }
617
618 /// Requirements on types that can be incremented with ++.
619 template<typename _Iter>
620 concept weakly_incrementable = movable<_Iter>
621 && requires(_Iter __i)
622 {
623 typename iter_difference_t<_Iter>;
624 requires __detail::__is_signed_integer_like<iter_difference_t<_Iter>>;
625 { ++__i } -> same_as<_Iter&>;
626 __i++;
627 };
628
629 template<typename _Iter>
630 concept incrementable = regular<_Iter> && weakly_incrementable<_Iter>
631 && requires(_Iter __i) { { __i++ } -> same_as<_Iter>; };
632
633 template<typename _Iter>
634 concept input_or_output_iterator
635 = requires(_Iter __i) { { *__i } -> __detail::__can_reference; }
636 && weakly_incrementable<_Iter>;
637
638 template<typename _Sent, typename _Iter>
639 concept sentinel_for = semiregular<_Sent>
640 && input_or_output_iterator<_Iter>
641 && __detail::__weakly_eq_cmp_with<_Sent, _Iter>;
642
643 template<typename _Sent, typename _Iter>
644 inline constexpr bool disable_sized_sentinel_for = false;
645
646 template<typename _Sent, typename _Iter>
647 concept sized_sentinel_for = sentinel_for<_Sent, _Iter>
648 && !disable_sized_sentinel_for<remove_cv_t<_Sent>, remove_cv_t<_Iter>>
649 && requires(const _Iter& __i, const _Sent& __s)
650 {
651 { __s - __i } -> same_as<iter_difference_t<_Iter>>;
652 { __i - __s } -> same_as<iter_difference_t<_Iter>>;
653 };
654
655 template<typename _Iter>
656 concept input_iterator = input_or_output_iterator<_Iter>
657 && indirectly_readable<_Iter>
658 && requires { typename __detail::__iter_concept<_Iter>; }
659 && derived_from<__detail::__iter_concept<_Iter>, input_iterator_tag>;
660
661 template<typename _Iter, typename _Tp>
662 concept output_iterator = input_or_output_iterator<_Iter>
663 && indirectly_writable<_Iter, _Tp>
664 && requires(_Iter __i, _Tp&& __t) { *__i++ = std::forward<_Tp>(__t); };
665
666 template<typename _Iter>
667 concept forward_iterator = input_iterator<_Iter>
668 && derived_from<__detail::__iter_concept<_Iter>, forward_iterator_tag>
669 && incrementable<_Iter> && sentinel_for<_Iter, _Iter>;
670
671 template<typename _Iter>
672 concept bidirectional_iterator = forward_iterator<_Iter>
673 && derived_from<__detail::__iter_concept<_Iter>,
674 bidirectional_iterator_tag>
675 && requires(_Iter __i)
676 {
677 { --__i } -> same_as<_Iter&>;
678 { __i-- } -> same_as<_Iter>;
679 };
680
681 template<typename _Iter>
682 concept random_access_iterator = bidirectional_iterator<_Iter>
683 && derived_from<__detail::__iter_concept<_Iter>,
684 random_access_iterator_tag>
685 && totally_ordered<_Iter> && sized_sentinel_for<_Iter, _Iter>
686 && requires(_Iter __i, const _Iter __j,
687 const iter_difference_t<_Iter> __n)
688 {
689 { __i += __n } -> same_as<_Iter&>;
690 { __j + __n } -> same_as<_Iter>;
691 { __n + __j } -> same_as<_Iter>;
692 { __i -= __n } -> same_as<_Iter&>;
693 { __j - __n } -> same_as<_Iter>;
694 { __j[__n] } -> same_as<iter_reference_t<_Iter>>;
695 };
696
697 template<typename _Iter>
698 concept contiguous_iterator = random_access_iterator<_Iter>
699 && derived_from<__detail::__iter_concept<_Iter>, contiguous_iterator_tag>
700 && is_lvalue_reference_v<iter_reference_t<_Iter>>
701 && same_as<iter_value_t<_Iter>, remove_cvref_t<iter_reference_t<_Iter>>>
702 && requires(const _Iter& __i)
703 {
704 { std::to_address(__i) }
705 -> same_as<add_pointer_t<iter_reference_t<_Iter>>>;
706 };
707
708 // [indirectcallable], indirect callable requirements
709
710 // [indirectcallable.indirectinvocable], indirect callables
711
712 template<typename _Fn, typename _Iter>
713 concept indirectly_unary_invocable = indirectly_readable<_Iter>
714 && copy_constructible<_Fn> && invocable<_Fn&, iter_value_t<_Iter>&>
715 && invocable<_Fn&, iter_reference_t<_Iter>>
716 && invocable<_Fn&, iter_common_reference_t<_Iter>>
717 && common_reference_with<invoke_result_t<_Fn&, iter_value_t<_Iter>&>,
718 invoke_result_t<_Fn&, iter_reference_t<_Iter>>>;
719
720 template<typename _Fn, typename _Iter>
721 concept indirectly_regular_unary_invocable = indirectly_readable<_Iter>
722 && copy_constructible<_Fn>
723 && regular_invocable<_Fn&, iter_value_t<_Iter>&>
724 && regular_invocable<_Fn&, iter_reference_t<_Iter>>
725 && regular_invocable<_Fn&, iter_common_reference_t<_Iter>>
726 && common_reference_with<invoke_result_t<_Fn&, iter_value_t<_Iter>&>,
727 invoke_result_t<_Fn&, iter_reference_t<_Iter>>>;
728
729 template<typename _Fn, typename _Iter>
730 concept indirect_unary_predicate = indirectly_readable<_Iter>
731 && copy_constructible<_Fn> && predicate<_Fn&, iter_value_t<_Iter>&>
732 && predicate<_Fn&, iter_reference_t<_Iter>>
733 && predicate<_Fn&, iter_common_reference_t<_Iter>>;
734
735 template<typename _Fn, typename _I1, typename _I2>
736 concept indirect_binary_predicate
737 = indirectly_readable<_I1> && indirectly_readable<_I2>
738 && copy_constructible<_Fn>
739 && predicate<_Fn&, iter_value_t<_I1>&, iter_value_t<_I2>&>
740 && predicate<_Fn&, iter_value_t<_I1>&, iter_reference_t<_I2>>
741 && predicate<_Fn&, iter_reference_t<_I1>, iter_value_t<_I2>&>
742 && predicate<_Fn&, iter_reference_t<_I1>, iter_reference_t<_I2>>
743 && predicate<_Fn&, iter_common_reference_t<_I1>,
744 iter_common_reference_t<_I2>>;
745
746 template<typename _Fn, typename _I1, typename _I2 = _I1>
747 concept indirect_equivalence_relation
748 = indirectly_readable<_I1> && indirectly_readable<_I2>
749 && copy_constructible<_Fn>
750 && equivalence_relation<_Fn&, iter_value_t<_I1>&, iter_value_t<_I2>&>
751 && equivalence_relation<_Fn&, iter_value_t<_I1>&, iter_reference_t<_I2>>
752 && equivalence_relation<_Fn&, iter_reference_t<_I1>, iter_value_t<_I2>&>
753 && equivalence_relation<_Fn&, iter_reference_t<_I1>,
754 iter_reference_t<_I2>>
755 && equivalence_relation<_Fn&, iter_common_reference_t<_I1>,
756 iter_common_reference_t<_I2>>;
757
758 template<typename _Fn, typename _I1, typename _I2 = _I1>
759 concept indirect_strict_weak_order
760 = indirectly_readable<_I1> && indirectly_readable<_I2>
761 && copy_constructible<_Fn>
762 && strict_weak_order<_Fn&, iter_value_t<_I1>&, iter_value_t<_I2>&>
763 && strict_weak_order<_Fn&, iter_value_t<_I1>&, iter_reference_t<_I2>>
764 && strict_weak_order<_Fn&, iter_reference_t<_I1>, iter_value_t<_I2>&>
765 && strict_weak_order<_Fn&, iter_reference_t<_I1>, iter_reference_t<_I2>>
766 && strict_weak_order<_Fn&, iter_common_reference_t<_I1>,
767 iter_common_reference_t<_I2>>;
768
769 template<typename _Fn, typename... _Is>
770 requires (indirectly_readable<_Is> && ...)
771 && invocable<_Fn, iter_reference_t<_Is>...>
772 using indirect_result_t = invoke_result_t<_Fn, iter_reference_t<_Is>...>;
773
774 namespace __detail
775 {
776 template<typename _Iter, typename _Proj>
777 struct __projected
778 {
779 struct __type
780 {
781 using value_type = remove_cvref_t<indirect_result_t<_Proj&, _Iter>>;
782 indirect_result_t<_Proj&, _Iter> operator*() const; // not defined
783 };
784 };
785
786 template<weakly_incrementable _Iter, typename _Proj>
787 struct __projected<_Iter, _Proj>
788 {
789 struct __type
790 {
791 using value_type = remove_cvref_t<indirect_result_t<_Proj&, _Iter>>;
792 using difference_type = iter_difference_t<_Iter>;
793 indirect_result_t<_Proj&, _Iter> operator*() const; // not defined
794 };
795 };
796 } // namespace __detail
797
798 /// [projected], projected
799 template<indirectly_readable _Iter,
800 indirectly_regular_unary_invocable<_Iter> _Proj>
801 using projected = typename __detail::__projected<_Iter, _Proj>::__type;
802
803 // [alg.req], common algorithm requirements
804
805 /// [alg.req.ind.move], concept `indirectly_movable`
806
807 template<typename _In, typename _Out>
808 concept indirectly_movable = indirectly_readable<_In>
809 && indirectly_writable<_Out, iter_rvalue_reference_t<_In>>;
810
811 template<typename _In, typename _Out>
812 concept indirectly_movable_storable = indirectly_movable<_In, _Out>
813 && indirectly_writable<_Out, iter_value_t<_In>>
814 && movable<iter_value_t<_In>>
815 && constructible_from<iter_value_t<_In>, iter_rvalue_reference_t<_In>>
816 && assignable_from<iter_value_t<_In>&, iter_rvalue_reference_t<_In>>;
817
818 /// [alg.req.ind.copy], concept `indirectly_copyable`
819 template<typename _In, typename _Out>
820 concept indirectly_copyable = indirectly_readable<_In>
821 && indirectly_writable<_Out, iter_reference_t<_In>>;
822
823 template<typename _In, typename _Out>
824 concept indirectly_copyable_storable = indirectly_copyable<_In, _Out>
825 && indirectly_writable<_Out, iter_value_t<_In>&>
826 && indirectly_writable<_Out, const iter_value_t<_In>&>
827 && indirectly_writable<_Out, iter_value_t<_In>&&>
828 && indirectly_writable<_Out, const iter_value_t<_In>&&>
829 && copyable<iter_value_t<_In>>
830 && constructible_from<iter_value_t<_In>, iter_reference_t<_In>>
831 && assignable_from<iter_value_t<_In>&, iter_reference_t<_In>>;
832
833 namespace ranges
834 {
835 namespace __cust_iswap
836 {
837 template<typename _It1, typename _It2>
838 void iter_swap(_It1, _It2) = delete;
839
840 template<typename _Tp, typename _Up>
841 concept __adl_iswap
842 = (std::__detail::__class_or_enum<remove_reference_t<_Tp>>
843 || std::__detail::__class_or_enum<remove_reference_t<_Up>>)
844 && requires(_Tp&& __t, _Up&& __u) {
845 iter_swap(static_cast<_Tp&&>(__t), static_cast<_Up&&>(__u));
846 };
847
848 template<typename _Xp, typename _Yp>
849 constexpr iter_value_t<_Xp>
850 __iter_exchange_move(_Xp&& __x, _Yp&& __y)
851 noexcept(noexcept(iter_value_t<_Xp>(iter_move(__x)))
852 && noexcept(*__x = iter_move(__y)))
853 {
854 iter_value_t<_Xp> __old_value(iter_move(__x));
855 *__x = iter_move(__y);
856 return __old_value;
857 }
858
859 struct _IterSwap
860 {
861 private:
862 template<typename _Tp, typename _Up>
863 static constexpr bool
864 _S_noexcept()
865 {
866 if constexpr (__adl_iswap<_Tp, _Up>)
867 return noexcept(iter_swap(std::declval<_Tp>(),
868 std::declval<_Up>()));
869 else if constexpr (indirectly_readable<_Tp>
870 && indirectly_readable<_Up>
871 && swappable_with<iter_reference_t<_Tp>, iter_reference_t<_Up>>)
872 return noexcept(ranges::swap(*std::declval<_Tp>(),
873 *std::declval<_Up>()));
874 else
875 return noexcept(*std::declval<_Tp>()
876 = __iter_exchange_move(std::declval<_Up>(),
877 std::declval<_Tp>()));
878 }
879
880 public:
881 template<typename _Tp, typename _Up>
882 requires __adl_iswap<_Tp, _Up>
883 || (indirectly_readable<remove_reference_t<_Tp>>
884 && indirectly_readable<remove_reference_t<_Up>>
885 && swappable_with<iter_reference_t<_Tp>, iter_reference_t<_Up>>)
886 || (indirectly_movable_storable<_Tp, _Up>
887 && indirectly_movable_storable<_Up, _Tp>)
888 constexpr void
889 operator()(_Tp&& __e1, _Up&& __e2) const
890 noexcept(_S_noexcept<_Tp, _Up>())
891 {
892 if constexpr (__adl_iswap<_Tp, _Up>)
893 iter_swap(static_cast<_Tp&&>(__e1), static_cast<_Up&&>(__e2));
894 else if constexpr (indirectly_readable<_Tp>
895 && indirectly_readable<_Up>
896 && swappable_with<iter_reference_t<_Tp>, iter_reference_t<_Up>>)
897 ranges::swap(*__e1, *__e2);
898 else
899 *__e1 = __iter_exchange_move(__e2, __e1);
900 }
901 };
902 } // namespace __cust_iswap
903
904 inline namespace __cust
905 {
906 inline constexpr __cust_iswap::_IterSwap iter_swap{};
907 } // inline namespace __cust
908
909 } // namespace ranges
910
911 /// [alg.req.ind.swap], concept `indirectly_swappable`
912 template<typename _I1, typename _I2 = _I1>
913 concept indirectly_swappable
914 = indirectly_readable<_I1> && indirectly_readable<_I2>
915 && requires(const _I1 __i1, const _I2 __i2)
916 {
917 ranges::iter_swap(__i1, __i1);
918 ranges::iter_swap(__i2, __i2);
919 ranges::iter_swap(__i1, __i2);
920 ranges::iter_swap(__i2, __i1);
921 };
922
923 /// [alg.req.ind.cmp], concept `indirectly_comparable`
924 template<typename _I1, typename _I2, typename _Rel, typename _P1 = identity,
925 typename _P2 = identity>
926 concept indirectly_comparable
927 = indirect_binary_predicate<_Rel, projected<_I1, _P1>,
928 projected<_I2, _P2>>;
929
930 /// [alg.req.permutable], concept `permutable`
931 template<typename _Iter>
932 concept permutable = forward_iterator<_Iter>
933 && indirectly_movable_storable<_Iter, _Iter>
934 && indirectly_swappable<_Iter, _Iter>;
935
936 /// [alg.req.mergeable], concept `mergeable`
937 template<typename _I1, typename _I2, typename _Out,
938 typename _Rel = ranges::less, typename _P1 = identity,
939 typename _P2 = identity>
940 concept mergeable = input_iterator<_I1> && input_iterator<_I2>
941 && weakly_incrementable<_Out> && indirectly_copyable<_I1, _Out>
942 && indirectly_copyable<_I2, _Out>
943 && indirect_strict_weak_order<_Rel, projected<_I1, _P1>,
944 projected<_I2, _P2>>;
945
946 /// [alg.req.sortable], concept `sortable`
947 template<typename _Iter, typename _Rel = ranges::less,
948 typename _Proj = identity>
949 concept sortable = permutable<_Iter>
950 && indirect_strict_weak_order<_Rel, projected<_Iter, _Proj>>;
951
952 struct unreachable_sentinel_t
953 {
954 template<weakly_incrementable _It>
955 friend constexpr bool
956 operator==(unreachable_sentinel_t, const _It&) noexcept
957 { return false; }
958 };
959
960 inline constexpr unreachable_sentinel_t unreachable_sentinel{};
961
962 // This is the namespace for [range.access] CPOs.
963 namespace ranges::__cust_access
964 {
965 using std::__detail::__class_or_enum;
966
967 struct _Decay_copy final
968 {
969 template<typename _Tp>
970 constexpr decay_t<_Tp>
971 operator()(_Tp&& __t) const
972 noexcept(is_nothrow_convertible_v<_Tp, decay_t<_Tp>>)
973 { return std::forward<_Tp>(__t); }
974 } inline constexpr __decay_copy{};
975
976 template<typename _Tp>
977 concept __member_begin = requires(_Tp& __t)
978 {
979 { __decay_copy(__t.begin()) } -> input_or_output_iterator;
980 };
981
982 // Poison pills so that unqualified lookup doesn't find std::begin.
983 void begin(auto&) = delete;
984 void begin(const auto&) = delete;
985
986 template<typename _Tp>
987 concept __adl_begin = __class_or_enum<remove_reference_t<_Tp>>
988 && requires(_Tp& __t)
989 {
990 { __decay_copy(begin(__t)) } -> input_or_output_iterator;
991 };
992
993 // Simplified version of std::ranges::begin that only supports lvalues,
994 // for use by __range_iter_t below.
995 template<typename _Tp>
996 requires is_array_v<_Tp> || __member_begin<_Tp&> || __adl_begin<_Tp&>
997 auto
998 __begin(_Tp& __t)
999 {
1000 if constexpr (is_array_v<_Tp>)
1001 return __t + 0;
1002 else if constexpr (__member_begin<_Tp&>)
1003 return __t.begin();
1004 else
1005 return begin(__t);
1006 }
1007 } // namespace ranges::__cust_access
1008
1009 namespace __detail
1010 {
1011 // Implementation of std::ranges::iterator_t, without using ranges::begin.
1012 template<typename _Tp>
1013 using __range_iter_t
1014 = decltype(ranges::__cust_access::__begin(std::declval<_Tp&>()));
1015
1016 } // namespace __detail
1017
1018 #endif // C++20 library concepts
1019 _GLIBCXX_END_NAMESPACE_VERSION
1020 } // namespace std
1021 #endif // C++20
1022 #endif // _ITERATOR_CONCEPTS_H
1023