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