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