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