xref: /llvm-project/libcxx/include/__iterator/concepts.h (revision f69585235ec85d54e0f3fc41b2d5700430907f99)
1e0adf7e0Szoecarver // -*- C++ -*-
2e0adf7e0Szoecarver //===----------------------------------------------------------------------===//
3e0adf7e0Szoecarver //
4e0adf7e0Szoecarver // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5e0adf7e0Szoecarver // See https://llvm.org/LICENSE.txt for license information.
6e0adf7e0Szoecarver // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7e0adf7e0Szoecarver //
8e0adf7e0Szoecarver //===----------------------------------------------------------------------===//
9e0adf7e0Szoecarver 
10e0adf7e0Szoecarver #ifndef _LIBCPP___ITERATOR_CONCEPTS_H
11e0adf7e0Szoecarver #define _LIBCPP___ITERATOR_CONCEPTS_H
12e0adf7e0Szoecarver 
1389b356f0SNikolas Klauser #include <__concepts/arithmetic.h>
1489b356f0SNikolas Klauser #include <__concepts/assignable.h>
1589b356f0SNikolas Klauser #include <__concepts/common_reference_with.h>
1689b356f0SNikolas Klauser #include <__concepts/constructible.h>
1789b356f0SNikolas Klauser #include <__concepts/copyable.h>
1889b356f0SNikolas Klauser #include <__concepts/derived_from.h>
1989b356f0SNikolas Klauser #include <__concepts/equality_comparable.h>
2089b356f0SNikolas Klauser #include <__concepts/invocable.h>
2189b356f0SNikolas Klauser #include <__concepts/movable.h>
2289b356f0SNikolas Klauser #include <__concepts/predicate.h>
2389b356f0SNikolas Klauser #include <__concepts/regular.h>
2489b356f0SNikolas Klauser #include <__concepts/relation.h>
2589b356f0SNikolas Klauser #include <__concepts/same_as.h>
2689b356f0SNikolas Klauser #include <__concepts/semiregular.h>
2789b356f0SNikolas Klauser #include <__concepts/totally_ordered.h>
28e0adf7e0Szoecarver #include <__config>
2957ebf3d0SLouis Dionne #include <__iterator/incrementable_traits.h>
30bede7523Szoecarver #include <__iterator/iter_move.h>
318110a731Szoecarver #include <__iterator/iterator_traits.h>
3257ebf3d0SLouis Dionne #include <__iterator/readable_traits.h>
33bede7523Szoecarver #include <__memory/pointer_traits.h>
34e0a66116SNikolas Klauser #include <__type_traits/add_pointer.h>
35e0a66116SNikolas Klauser #include <__type_traits/common_reference.h>
36d6832a61SLouis Dionne #include <__type_traits/integral_constant.h>
3709e3a360SLouis Dionne #include <__type_traits/invoke.h>
38e0a66116SNikolas Klauser #include <__type_traits/is_pointer.h>
39026210e8SA. Jiang #include <__type_traits/is_primary_template.h>
40e0a66116SNikolas Klauser #include <__type_traits/is_reference.h>
41e0a66116SNikolas Klauser #include <__type_traits/remove_cv.h>
42e0a66116SNikolas Klauser #include <__type_traits/remove_cvref.h>
436adbc83eSChristopher Di Bella #include <__utility/forward.h>
44e0adf7e0Szoecarver 
45e0adf7e0Szoecarver #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
46e0adf7e0Szoecarver #  pragma GCC system_header
47e0adf7e0Szoecarver #endif
48e0adf7e0Szoecarver 
49e0adf7e0Szoecarver _LIBCPP_BEGIN_NAMESPACE_STD
50e0adf7e0Szoecarver 
514f15267dSNikolas Klauser #if _LIBCPP_STD_VER >= 20
52e0adf7e0Szoecarver 
5357ebf3d0SLouis Dionne // [iterator.concept.readable]
5457ebf3d0SLouis Dionne template <class _In>
5557ebf3d0SLouis Dionne concept __indirectly_readable_impl =
568d0dfa0dSMartin Storsjö     requires(const _In __i) {
5757ebf3d0SLouis Dionne       typename iter_value_t<_In>;
5857ebf3d0SLouis Dionne       typename iter_reference_t<_In>;
5957ebf3d0SLouis Dionne       typename iter_rvalue_reference_t<_In>;
608d0dfa0dSMartin Storsjö       { *__i } -> same_as<iter_reference_t<_In>>;
618d0dfa0dSMartin Storsjö       { ranges::iter_move(__i) } -> same_as<iter_rvalue_reference_t<_In>>;
629783f28cSLouis Dionne     } && common_reference_with<iter_reference_t<_In>&&, iter_value_t<_In>&> &&
6357ebf3d0SLouis Dionne     common_reference_with<iter_reference_t<_In>&&, iter_rvalue_reference_t<_In>&&> &&
6457ebf3d0SLouis Dionne     common_reference_with<iter_rvalue_reference_t<_In>&&, const iter_value_t<_In>&>;
6557ebf3d0SLouis Dionne 
6657ebf3d0SLouis Dionne template <class _In>
6757ebf3d0SLouis Dionne concept indirectly_readable = __indirectly_readable_impl<remove_cvref_t<_In>>;
6857ebf3d0SLouis Dionne 
69026210e8SA. Jiang template <class _Tp>
70*f6958523SNikolas Klauser using __projected_iterator_t _LIBCPP_NODEBUG = typename _Tp::__projected_iterator;
71026210e8SA. Jiang 
72026210e8SA. Jiang template <class _Tp>
73*f6958523SNikolas Klauser using __projected_projection_t _LIBCPP_NODEBUG = typename _Tp::__projected_projection;
74026210e8SA. Jiang 
75026210e8SA. Jiang template <class _Tp>
76026210e8SA. Jiang concept __specialization_of_projected = requires {
77026210e8SA. Jiang   typename __projected_iterator_t<_Tp>;
78026210e8SA. Jiang   typename __projected_projection_t<_Tp>;
79026210e8SA. Jiang } && __is_primary_template<_Tp>::value;
80026210e8SA. Jiang 
81026210e8SA. Jiang template <class _Tp>
82026210e8SA. Jiang struct __indirect_value_t_impl {
83026210e8SA. Jiang   using type = iter_value_t<_Tp>&;
84026210e8SA. Jiang };
85026210e8SA. Jiang template <__specialization_of_projected _Tp>
86026210e8SA. Jiang struct __indirect_value_t_impl<_Tp> {
87026210e8SA. Jiang   using type = invoke_result_t<__projected_projection_t<_Tp>&,
88026210e8SA. Jiang                                typename __indirect_value_t_impl<__projected_iterator_t<_Tp>>::type>;
89026210e8SA. Jiang };
90026210e8SA. Jiang 
9158b29a4eSLouis Dionne template <indirectly_readable _Tp>
92*f6958523SNikolas Klauser using __indirect_value_t _LIBCPP_NODEBUG = typename __indirect_value_t_impl<_Tp>::type;
93026210e8SA. Jiang 
94026210e8SA. Jiang template <indirectly_readable _Tp>
95026210e8SA. Jiang using iter_common_reference_t = common_reference_t<iter_reference_t<_Tp>, __indirect_value_t<_Tp>>;
9658b29a4eSLouis Dionne 
9757ebf3d0SLouis Dionne // [iterator.concept.writable]
9857ebf3d0SLouis Dionne template <class _Out, class _Tp>
999783f28cSLouis Dionne concept indirectly_writable = requires(_Out&& __o, _Tp&& __t) {
10077a00c0dSLouis Dionne   *__o                                             = std::forward<_Tp>(__t); // not required to be equality-preserving
10177a00c0dSLouis Dionne   *std::forward<_Out>(__o)                         = std::forward<_Tp>(__t); // not required to be equality-preserving
10277a00c0dSLouis Dionne   const_cast<const iter_reference_t<_Out>&&>(*__o) = std::forward<_Tp>(__t); // not required to be equality-preserving
1039783f28cSLouis Dionne   const_cast<const iter_reference_t<_Out>&&>(*std::forward<_Out>(__o)) =
1049783f28cSLouis Dionne       std::forward<_Tp>(__t); // not required to be equality-preserving
105e0adf7e0Szoecarver };
106e0adf7e0Szoecarver 
10722052860SChristopher Di Bella // [iterator.concept.winc]
10822052860SChristopher Di Bella template <class _Tp>
10922052860SChristopher Di Bella concept __integer_like = integral<_Tp> && !same_as<_Tp, bool>;
11022052860SChristopher Di Bella 
11122052860SChristopher Di Bella template <class _Tp>
11222052860SChristopher Di Bella concept __signed_integer_like = signed_integral<_Tp>;
11322052860SChristopher Di Bella 
11422052860SChristopher Di Bella template <class _Ip>
11522052860SChristopher Di Bella concept weakly_incrementable =
1167b20e05cSzoecarver     // TODO: remove this once the clang bug is fixed (bugs.llvm.org/PR48173).
1177b20e05cSzoecarver     !same_as<_Ip, bool> && // Currently, clang does not handle bool correctly.
1189783f28cSLouis Dionne     movable<_Ip> && requires(_Ip __i) {
11922052860SChristopher Di Bella       typename iter_difference_t<_Ip>;
12022052860SChristopher Di Bella       requires __signed_integer_like<iter_difference_t<_Ip>>;
12122052860SChristopher Di Bella       { ++__i } -> same_as<_Ip&>; // not required to be equality-preserving
12222052860SChristopher Di Bella       __i++;                      // not required to be equality-preserving
12322052860SChristopher Di Bella     };
12422052860SChristopher Di Bella 
12522052860SChristopher Di Bella // [iterator.concept.inc]
12622052860SChristopher Di Bella template <class _Ip>
1279783f28cSLouis Dionne concept incrementable = regular<_Ip> && weakly_incrementable<_Ip> && requires(_Ip __i) {
12822052860SChristopher Di Bella   { __i++ } -> same_as<_Ip>;
12922052860SChristopher Di Bella };
13022052860SChristopher Di Bella 
13138225d69SChristopher Di Bella // [iterator.concept.iterator]
13238225d69SChristopher Di Bella template <class _Ip>
1339783f28cSLouis Dionne concept input_or_output_iterator = requires(_Ip __i) {
1340b5fb7c6SArthur O'Dwyer   { *__i } -> __can_reference;
1359783f28cSLouis Dionne } && weakly_incrementable<_Ip>;
13638225d69SChristopher Di Bella 
13738225d69SChristopher Di Bella // [iterator.concept.sentinel]
13838225d69SChristopher Di Bella template <class _Sp, class _Ip>
1399783f28cSLouis Dionne concept sentinel_for = semiregular<_Sp> && input_or_output_iterator<_Ip> && __weakly_equality_comparable_with<_Sp, _Ip>;
14038225d69SChristopher Di Bella 
141bdd68357Szoecarver template <class, class>
142bdd68357Szoecarver inline constexpr bool disable_sized_sentinel_for = false;
143bdd68357Szoecarver 
144bdd68357Szoecarver template <class _Sp, class _Ip>
145bdd68357Szoecarver concept sized_sentinel_for =
1469783f28cSLouis Dionne     sentinel_for<_Sp, _Ip> && !disable_sized_sentinel_for<remove_cv_t<_Sp>, remove_cv_t<_Ip>> &&
147bdd68357Szoecarver     requires(const _Ip& __i, const _Sp& __s) {
148bdd68357Szoecarver       { __s - __i } -> same_as<iter_difference_t<_Ip>>;
149bdd68357Szoecarver       { __i - __s } -> same_as<iter_difference_t<_Ip>>;
150bdd68357Szoecarver     };
151bdd68357Szoecarver 
152c05d1eedSChristopher Di Bella // [iterator.concept.input]
153c05d1eedSChristopher Di Bella template <class _Ip>
1549783f28cSLouis Dionne concept input_iterator = input_or_output_iterator<_Ip> && indirectly_readable<_Ip> && requires {
1559783f28cSLouis Dionne   typename _ITER_CONCEPT<_Ip>;
1569783f28cSLouis Dionne } && derived_from<_ITER_CONCEPT<_Ip>, input_iterator_tag>;
157c05d1eedSChristopher Di Bella 
1587b28c5d3SLouis Dionne // [iterator.concept.output]
1597b28c5d3SLouis Dionne template <class _Ip, class _Tp>
1607b28c5d3SLouis Dionne concept output_iterator =
1619783f28cSLouis Dionne     input_or_output_iterator<_Ip> && indirectly_writable<_Ip, _Tp> && requires(_Ip __it, _Tp&& __t) {
16277a00c0dSLouis Dionne       *__it++ = std::forward<_Tp>(__t); // not required to be equality-preserving
1637b28c5d3SLouis Dionne     };
1647b28c5d3SLouis Dionne 
165fa3e2626SChristopher Di Bella // [iterator.concept.forward]
166fa3e2626SChristopher Di Bella template <class _Ip>
167fa3e2626SChristopher Di Bella concept forward_iterator =
1689783f28cSLouis Dionne     input_iterator<_Ip> && derived_from<_ITER_CONCEPT<_Ip>, forward_iterator_tag> && incrementable<_Ip> &&
169fa3e2626SChristopher Di Bella     sentinel_for<_Ip, _Ip>;
170fa3e2626SChristopher Di Bella 
1719c5d86aaSChristopher Di Bella // [iterator.concept.bidir]
1729c5d86aaSChristopher Di Bella template <class _Ip>
1739c5d86aaSChristopher Di Bella concept bidirectional_iterator =
1749783f28cSLouis Dionne     forward_iterator<_Ip> && derived_from<_ITER_CONCEPT<_Ip>, bidirectional_iterator_tag> && requires(_Ip __i) {
1759c5d86aaSChristopher Di Bella       { --__i } -> same_as<_Ip&>;
1769c5d86aaSChristopher Di Bella       { __i-- } -> same_as<_Ip>;
1779c5d86aaSChristopher Di Bella     };
1789c5d86aaSChristopher Di Bella 
1796ffc41b0Szoecarver template <class _Ip>
1806ffc41b0Szoecarver concept random_access_iterator =
1819783f28cSLouis Dionne     bidirectional_iterator<_Ip> && derived_from<_ITER_CONCEPT<_Ip>, random_access_iterator_tag> &&
1829783f28cSLouis Dionne     totally_ordered<_Ip> && sized_sentinel_for<_Ip, _Ip> &&
1836ffc41b0Szoecarver     requires(_Ip __i, const _Ip __j, const iter_difference_t<_Ip> __n) {
1846ffc41b0Szoecarver       { __i += __n } -> same_as<_Ip&>;
1856ffc41b0Szoecarver       { __j + __n } -> same_as<_Ip>;
1866ffc41b0Szoecarver       { __n + __j } -> same_as<_Ip>;
1876ffc41b0Szoecarver       { __i -= __n } -> same_as<_Ip&>;
1886ffc41b0Szoecarver       { __j - __n } -> same_as<_Ip>;
1896ffc41b0Szoecarver       { __j[__n] } -> same_as<iter_reference_t<_Ip>>;
1906ffc41b0Szoecarver     };
1916ffc41b0Szoecarver 
192bede7523Szoecarver template <class _Ip>
193bede7523Szoecarver concept contiguous_iterator =
1949783f28cSLouis Dionne     random_access_iterator<_Ip> && derived_from<_ITER_CONCEPT<_Ip>, contiguous_iterator_tag> &&
1959783f28cSLouis Dionne     is_lvalue_reference_v<iter_reference_t<_Ip>> && same_as<iter_value_t<_Ip>, remove_cvref_t<iter_reference_t<_Ip>>> &&
196bede7523Szoecarver     requires(const _Ip& __i) {
19777a00c0dSLouis Dionne       { std::to_address(__i) } -> same_as<add_pointer_t<iter_reference_t<_Ip>>>;
198bede7523Szoecarver     };
199bede7523Szoecarver 
20089599e8bSzoecarver template <class _Ip>
20189599e8bSzoecarver concept __has_arrow = input_iterator<_Ip> && (is_pointer_v<_Ip> || requires(_Ip __i) { __i.operator->(); });
20289599e8bSzoecarver 
203c54d3050SLouis Dionne // [indirectcallable.indirectinvocable]
204c54d3050SLouis Dionne template <class _Fp, class _It>
205c54d3050SLouis Dionne concept indirectly_unary_invocable =
206026210e8SA. Jiang     indirectly_readable<_It> && copy_constructible<_Fp> && invocable<_Fp&, __indirect_value_t<_It>> &&
207cb3de24bSHristo Hristov     invocable<_Fp&, iter_reference_t<_It>> &&
208026210e8SA. Jiang     common_reference_with< invoke_result_t<_Fp&, __indirect_value_t<_It>>,
209026210e8SA. Jiang                            invoke_result_t<_Fp&, iter_reference_t<_It>>>;
210c54d3050SLouis Dionne 
211c54d3050SLouis Dionne template <class _Fp, class _It>
212c54d3050SLouis Dionne concept indirectly_regular_unary_invocable =
213026210e8SA. Jiang     indirectly_readable<_It> && copy_constructible<_Fp> && regular_invocable<_Fp&, __indirect_value_t<_It>> &&
214cb3de24bSHristo Hristov     regular_invocable<_Fp&, iter_reference_t<_It>> &&
215026210e8SA. Jiang     common_reference_with< invoke_result_t<_Fp&, __indirect_value_t<_It>>,
216026210e8SA. Jiang                            invoke_result_t<_Fp&, iter_reference_t<_It>>>;
217c54d3050SLouis Dionne 
218c54d3050SLouis Dionne template <class _Fp, class _It>
219c54d3050SLouis Dionne concept indirect_unary_predicate =
220026210e8SA. Jiang     indirectly_readable<_It> && copy_constructible<_Fp> && predicate<_Fp&, __indirect_value_t<_It>> &&
221cb3de24bSHristo Hristov     predicate<_Fp&, iter_reference_t<_It>>;
222c54d3050SLouis Dionne 
223c54d3050SLouis Dionne template <class _Fp, class _It1, class _It2>
224c54d3050SLouis Dionne concept indirect_binary_predicate =
2259783f28cSLouis Dionne     indirectly_readable<_It1> && indirectly_readable<_It2> && copy_constructible<_Fp> &&
226026210e8SA. Jiang     predicate<_Fp&, __indirect_value_t<_It1>, __indirect_value_t<_It2>> &&
227026210e8SA. Jiang     predicate<_Fp&, __indirect_value_t<_It1>, iter_reference_t<_It2>> &&
228026210e8SA. Jiang     predicate<_Fp&, iter_reference_t<_It1>, __indirect_value_t<_It2>> &&
229cb3de24bSHristo Hristov     predicate<_Fp&, iter_reference_t<_It1>, iter_reference_t<_It2>>;
230c54d3050SLouis Dionne 
231c54d3050SLouis Dionne template <class _Fp, class _It1, class _It2 = _It1>
232c54d3050SLouis Dionne concept indirect_equivalence_relation =
2339783f28cSLouis Dionne     indirectly_readable<_It1> && indirectly_readable<_It2> && copy_constructible<_Fp> &&
234026210e8SA. Jiang     equivalence_relation<_Fp&, __indirect_value_t<_It1>, __indirect_value_t<_It2>> &&
235026210e8SA. Jiang     equivalence_relation<_Fp&, __indirect_value_t<_It1>, iter_reference_t<_It2>> &&
236026210e8SA. Jiang     equivalence_relation<_Fp&, iter_reference_t<_It1>, __indirect_value_t<_It2>> &&
237cb3de24bSHristo Hristov     equivalence_relation<_Fp&, iter_reference_t<_It1>, iter_reference_t<_It2>>;
238c54d3050SLouis Dionne 
239c54d3050SLouis Dionne template <class _Fp, class _It1, class _It2 = _It1>
240c54d3050SLouis Dionne concept indirect_strict_weak_order =
2419783f28cSLouis Dionne     indirectly_readable<_It1> && indirectly_readable<_It2> && copy_constructible<_Fp> &&
242026210e8SA. Jiang     strict_weak_order<_Fp&, __indirect_value_t<_It1>, __indirect_value_t<_It2>> &&
243026210e8SA. Jiang     strict_weak_order<_Fp&, __indirect_value_t<_It1>, iter_reference_t<_It2>> &&
244026210e8SA. Jiang     strict_weak_order<_Fp&, iter_reference_t<_It1>, __indirect_value_t<_It2>> &&
245cb3de24bSHristo Hristov     strict_weak_order<_Fp&, iter_reference_t<_It1>, iter_reference_t<_It2>>;
246c54d3050SLouis Dionne 
247c54d3050SLouis Dionne template <class _Fp, class... _Its>
248c54d3050SLouis Dionne   requires(indirectly_readable<_Its> && ...) && invocable<_Fp, iter_reference_t<_Its>...>
249c54d3050SLouis Dionne using indirect_result_t = invoke_result_t<_Fp, iter_reference_t<_Its>...>;
250c54d3050SLouis Dionne 
251075f2370Szoecarver template <class _In, class _Out>
2529783f28cSLouis Dionne concept indirectly_movable = indirectly_readable<_In> && indirectly_writable<_Out, iter_rvalue_reference_t<_In>>;
253075f2370Szoecarver 
254075f2370Szoecarver template <class _In, class _Out>
255075f2370Szoecarver concept indirectly_movable_storable =
2569783f28cSLouis Dionne     indirectly_movable<_In, _Out> && indirectly_writable<_Out, iter_value_t<_In>> && movable<iter_value_t<_In>> &&
257075f2370Szoecarver     constructible_from<iter_value_t<_In>, iter_rvalue_reference_t<_In>> &&
258075f2370Szoecarver     assignable_from<iter_value_t<_In>&, iter_rvalue_reference_t<_In>>;
259075f2370Szoecarver 
260e65d3760SKonstantin Varlamov template <class _In, class _Out>
2619783f28cSLouis Dionne concept indirectly_copyable = indirectly_readable<_In> && indirectly_writable<_Out, iter_reference_t<_In>>;
262e65d3760SKonstantin Varlamov 
263e65d3760SKonstantin Varlamov template <class _In, class _Out>
264e65d3760SKonstantin Varlamov concept indirectly_copyable_storable =
2659783f28cSLouis Dionne     indirectly_copyable<_In, _Out> && indirectly_writable<_Out, iter_value_t<_In>&> &&
2669783f28cSLouis Dionne     indirectly_writable<_Out, const iter_value_t<_In>&> && indirectly_writable<_Out, iter_value_t<_In>&&> &&
2679783f28cSLouis Dionne     indirectly_writable<_Out, const iter_value_t<_In>&&> && copyable<iter_value_t<_In>> &&
268e65d3760SKonstantin Varlamov     constructible_from<iter_value_t<_In>, iter_reference_t<_In>> &&
269e65d3760SKonstantin Varlamov     assignable_from<iter_value_t<_In>&, iter_reference_t<_In>>;
270e65d3760SKonstantin Varlamov 
271edc1f0c1Szoecarver // Note: indirectly_swappable is located in iter_swap.h to prevent a dependency cycle
272edc1f0c1Szoecarver // (both iter_swap and indirectly_swappable require indirectly_readable).
273edc1f0c1Szoecarver 
2744f15267dSNikolas Klauser #endif // _LIBCPP_STD_VER >= 20
275e0adf7e0Szoecarver 
2760e2de665SGonzalo Brito Gadeschi template <class _Tp>
277*f6958523SNikolas Klauser using __has_random_access_iterator_category_or_concept _LIBCPP_NODEBUG
2780e2de665SGonzalo Brito Gadeschi #if _LIBCPP_STD_VER >= 20
2790e2de665SGonzalo Brito Gadeschi     = integral_constant<bool, random_access_iterator<_Tp>>;
2800e2de665SGonzalo Brito Gadeschi #else  // _LIBCPP_STD_VER < 20
2810e2de665SGonzalo Brito Gadeschi     = __has_random_access_iterator_category<_Tp>;
2820e2de665SGonzalo Brito Gadeschi #endif // _LIBCPP_STD_VER
2830e2de665SGonzalo Brito Gadeschi 
284e0adf7e0Szoecarver _LIBCPP_END_NAMESPACE_STD
285e0adf7e0Szoecarver 
286e0adf7e0Szoecarver #endif // _LIBCPP___ITERATOR_CONCEPTS_H
287