1fe6060f1SDimitry Andric // -*- C++ -*- 2fe6060f1SDimitry Andric //===----------------------------------------------------------------------===// 3fe6060f1SDimitry Andric // 4fe6060f1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5fe6060f1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 6fe6060f1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7fe6060f1SDimitry Andric // 8fe6060f1SDimitry Andric //===----------------------------------------------------------------------===// 9fe6060f1SDimitry Andric 10fe6060f1SDimitry Andric #ifndef _LIBCPP___ITERATOR_CONCEPTS_H 11fe6060f1SDimitry Andric #define _LIBCPP___ITERATOR_CONCEPTS_H 12fe6060f1SDimitry Andric 13*bdd1243dSDimitry Andric #include <__concepts/arithmetic.h> 14*bdd1243dSDimitry Andric #include <__concepts/assignable.h> 15*bdd1243dSDimitry Andric #include <__concepts/common_reference_with.h> 16*bdd1243dSDimitry Andric #include <__concepts/constructible.h> 17*bdd1243dSDimitry Andric #include <__concepts/copyable.h> 18*bdd1243dSDimitry Andric #include <__concepts/derived_from.h> 19*bdd1243dSDimitry Andric #include <__concepts/equality_comparable.h> 20*bdd1243dSDimitry Andric #include <__concepts/invocable.h> 21*bdd1243dSDimitry Andric #include <__concepts/movable.h> 22*bdd1243dSDimitry Andric #include <__concepts/predicate.h> 23*bdd1243dSDimitry Andric #include <__concepts/regular.h> 24*bdd1243dSDimitry Andric #include <__concepts/relation.h> 25*bdd1243dSDimitry Andric #include <__concepts/same_as.h> 26*bdd1243dSDimitry Andric #include <__concepts/semiregular.h> 27*bdd1243dSDimitry Andric #include <__concepts/totally_ordered.h> 28fe6060f1SDimitry Andric #include <__config> 29*bdd1243dSDimitry Andric #include <__functional/invoke.h> 30fe6060f1SDimitry Andric #include <__iterator/incrementable_traits.h> 31fe6060f1SDimitry Andric #include <__iterator/iter_move.h> 32fe6060f1SDimitry Andric #include <__iterator/iterator_traits.h> 33fe6060f1SDimitry Andric #include <__iterator/readable_traits.h> 34fe6060f1SDimitry Andric #include <__memory/pointer_traits.h> 35*bdd1243dSDimitry Andric #include <__type_traits/add_pointer.h> 36*bdd1243dSDimitry Andric #include <__type_traits/common_reference.h> 37*bdd1243dSDimitry Andric #include <__type_traits/is_pointer.h> 38*bdd1243dSDimitry Andric #include <__type_traits/is_reference.h> 39*bdd1243dSDimitry Andric #include <__type_traits/remove_cv.h> 40*bdd1243dSDimitry Andric #include <__type_traits/remove_cvref.h> 41fe6060f1SDimitry Andric #include <__utility/forward.h> 42fe6060f1SDimitry Andric 43fe6060f1SDimitry Andric #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 44fe6060f1SDimitry Andric # pragma GCC system_header 45fe6060f1SDimitry Andric #endif 46fe6060f1SDimitry Andric 47fe6060f1SDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD 48fe6060f1SDimitry Andric 4981ad6265SDimitry Andric #if _LIBCPP_STD_VER > 17 50fe6060f1SDimitry Andric 51fe6060f1SDimitry Andric // [iterator.concept.readable] 52fe6060f1SDimitry Andric template<class _In> 53fe6060f1SDimitry Andric concept __indirectly_readable_impl = 54fe6060f1SDimitry Andric requires(const _In __i) { 55fe6060f1SDimitry Andric typename iter_value_t<_In>; 56fe6060f1SDimitry Andric typename iter_reference_t<_In>; 57fe6060f1SDimitry Andric typename iter_rvalue_reference_t<_In>; 58fe6060f1SDimitry Andric { *__i } -> same_as<iter_reference_t<_In>>; 59fe6060f1SDimitry Andric { ranges::iter_move(__i) } -> same_as<iter_rvalue_reference_t<_In>>; 60fe6060f1SDimitry Andric } && 61fe6060f1SDimitry Andric common_reference_with<iter_reference_t<_In>&&, iter_value_t<_In>&> && 62fe6060f1SDimitry Andric common_reference_with<iter_reference_t<_In>&&, iter_rvalue_reference_t<_In>&&> && 63fe6060f1SDimitry Andric common_reference_with<iter_rvalue_reference_t<_In>&&, const iter_value_t<_In>&>; 64fe6060f1SDimitry Andric 65fe6060f1SDimitry Andric template<class _In> 66fe6060f1SDimitry Andric concept indirectly_readable = __indirectly_readable_impl<remove_cvref_t<_In>>; 67fe6060f1SDimitry Andric 68fe6060f1SDimitry Andric template<indirectly_readable _Tp> 69fe6060f1SDimitry Andric using iter_common_reference_t = common_reference_t<iter_reference_t<_Tp>, iter_value_t<_Tp>&>; 70fe6060f1SDimitry Andric 71fe6060f1SDimitry Andric // [iterator.concept.writable] 72fe6060f1SDimitry Andric template<class _Out, class _Tp> 73fe6060f1SDimitry Andric concept indirectly_writable = 74fe6060f1SDimitry Andric requires(_Out&& __o, _Tp&& __t) { 75fe6060f1SDimitry Andric *__o = _VSTD::forward<_Tp>(__t); // not required to be equality-preserving 76fe6060f1SDimitry Andric *_VSTD::forward<_Out>(__o) = _VSTD::forward<_Tp>(__t); // not required to be equality-preserving 77fe6060f1SDimitry Andric const_cast<const iter_reference_t<_Out>&&>(*__o) = _VSTD::forward<_Tp>(__t); // not required to be equality-preserving 78fe6060f1SDimitry Andric const_cast<const iter_reference_t<_Out>&&>(*_VSTD::forward<_Out>(__o)) = _VSTD::forward<_Tp>(__t); // not required to be equality-preserving 79fe6060f1SDimitry Andric }; 80fe6060f1SDimitry Andric 81fe6060f1SDimitry Andric // [iterator.concept.winc] 82fe6060f1SDimitry Andric template<class _Tp> 83fe6060f1SDimitry Andric concept __integer_like = integral<_Tp> && !same_as<_Tp, bool>; 84fe6060f1SDimitry Andric 85fe6060f1SDimitry Andric template<class _Tp> 86fe6060f1SDimitry Andric concept __signed_integer_like = signed_integral<_Tp>; 87fe6060f1SDimitry Andric 88fe6060f1SDimitry Andric template<class _Ip> 89fe6060f1SDimitry Andric concept weakly_incrementable = 90349cc55cSDimitry Andric // TODO: remove this once the clang bug is fixed (bugs.llvm.org/PR48173). 91349cc55cSDimitry Andric !same_as<_Ip, bool> && // Currently, clang does not handle bool correctly. 92fe6060f1SDimitry Andric movable<_Ip> && 93fe6060f1SDimitry Andric requires(_Ip __i) { 94fe6060f1SDimitry Andric typename iter_difference_t<_Ip>; 95fe6060f1SDimitry Andric requires __signed_integer_like<iter_difference_t<_Ip>>; 96fe6060f1SDimitry Andric { ++__i } -> same_as<_Ip&>; // not required to be equality-preserving 97fe6060f1SDimitry Andric __i++; // not required to be equality-preserving 98fe6060f1SDimitry Andric }; 99fe6060f1SDimitry Andric 100fe6060f1SDimitry Andric // [iterator.concept.inc] 101fe6060f1SDimitry Andric template<class _Ip> 102fe6060f1SDimitry Andric concept incrementable = 103fe6060f1SDimitry Andric regular<_Ip> && 104fe6060f1SDimitry Andric weakly_incrementable<_Ip> && 105fe6060f1SDimitry Andric requires(_Ip __i) { 106fe6060f1SDimitry Andric { __i++ } -> same_as<_Ip>; 107fe6060f1SDimitry Andric }; 108fe6060f1SDimitry Andric 109fe6060f1SDimitry Andric // [iterator.concept.iterator] 110fe6060f1SDimitry Andric template<class _Ip> 111fe6060f1SDimitry Andric concept input_or_output_iterator = 112fe6060f1SDimitry Andric requires(_Ip __i) { 11381ad6265SDimitry Andric { *__i } -> __can_reference; 114fe6060f1SDimitry Andric } && 115fe6060f1SDimitry Andric weakly_incrementable<_Ip>; 116fe6060f1SDimitry Andric 117fe6060f1SDimitry Andric // [iterator.concept.sentinel] 118fe6060f1SDimitry Andric template<class _Sp, class _Ip> 119fe6060f1SDimitry Andric concept sentinel_for = 120fe6060f1SDimitry Andric semiregular<_Sp> && 121fe6060f1SDimitry Andric input_or_output_iterator<_Ip> && 122fe6060f1SDimitry Andric __weakly_equality_comparable_with<_Sp, _Ip>; 123fe6060f1SDimitry Andric 124fe6060f1SDimitry Andric template<class, class> 125fe6060f1SDimitry Andric inline constexpr bool disable_sized_sentinel_for = false; 126fe6060f1SDimitry Andric 127fe6060f1SDimitry Andric template<class _Sp, class _Ip> 128fe6060f1SDimitry Andric concept sized_sentinel_for = 129fe6060f1SDimitry Andric sentinel_for<_Sp, _Ip> && 130fe6060f1SDimitry Andric !disable_sized_sentinel_for<remove_cv_t<_Sp>, remove_cv_t<_Ip>> && 131fe6060f1SDimitry Andric requires(const _Ip& __i, const _Sp& __s) { 132fe6060f1SDimitry Andric { __s - __i } -> same_as<iter_difference_t<_Ip>>; 133fe6060f1SDimitry Andric { __i - __s } -> same_as<iter_difference_t<_Ip>>; 134fe6060f1SDimitry Andric }; 135fe6060f1SDimitry Andric 136fe6060f1SDimitry Andric // [iterator.concept.input] 137fe6060f1SDimitry Andric template<class _Ip> 138fe6060f1SDimitry Andric concept input_iterator = 139fe6060f1SDimitry Andric input_or_output_iterator<_Ip> && 140fe6060f1SDimitry Andric indirectly_readable<_Ip> && 141fe6060f1SDimitry Andric requires { typename _ITER_CONCEPT<_Ip>; } && 142fe6060f1SDimitry Andric derived_from<_ITER_CONCEPT<_Ip>, input_iterator_tag>; 143fe6060f1SDimitry Andric 144fe6060f1SDimitry Andric // [iterator.concept.output] 145fe6060f1SDimitry Andric template<class _Ip, class _Tp> 146fe6060f1SDimitry Andric concept output_iterator = 147fe6060f1SDimitry Andric input_or_output_iterator<_Ip> && 148fe6060f1SDimitry Andric indirectly_writable<_Ip, _Tp> && 149fe6060f1SDimitry Andric requires (_Ip __it, _Tp&& __t) { 150fe6060f1SDimitry Andric *__it++ = _VSTD::forward<_Tp>(__t); // not required to be equality-preserving 151fe6060f1SDimitry Andric }; 152fe6060f1SDimitry Andric 153fe6060f1SDimitry Andric // [iterator.concept.forward] 154fe6060f1SDimitry Andric template<class _Ip> 155fe6060f1SDimitry Andric concept forward_iterator = 156fe6060f1SDimitry Andric input_iterator<_Ip> && 157fe6060f1SDimitry Andric derived_from<_ITER_CONCEPT<_Ip>, forward_iterator_tag> && 158fe6060f1SDimitry Andric incrementable<_Ip> && 159fe6060f1SDimitry Andric sentinel_for<_Ip, _Ip>; 160fe6060f1SDimitry Andric 161fe6060f1SDimitry Andric // [iterator.concept.bidir] 162fe6060f1SDimitry Andric template<class _Ip> 163fe6060f1SDimitry Andric concept bidirectional_iterator = 164fe6060f1SDimitry Andric forward_iterator<_Ip> && 165fe6060f1SDimitry Andric derived_from<_ITER_CONCEPT<_Ip>, bidirectional_iterator_tag> && 166fe6060f1SDimitry Andric requires(_Ip __i) { 167fe6060f1SDimitry Andric { --__i } -> same_as<_Ip&>; 168fe6060f1SDimitry Andric { __i-- } -> same_as<_Ip>; 169fe6060f1SDimitry Andric }; 170fe6060f1SDimitry Andric 171fe6060f1SDimitry Andric template<class _Ip> 172fe6060f1SDimitry Andric concept random_access_iterator = 173fe6060f1SDimitry Andric bidirectional_iterator<_Ip> && 174fe6060f1SDimitry Andric derived_from<_ITER_CONCEPT<_Ip>, random_access_iterator_tag> && 175fe6060f1SDimitry Andric totally_ordered<_Ip> && 176fe6060f1SDimitry Andric sized_sentinel_for<_Ip, _Ip> && 177fe6060f1SDimitry Andric requires(_Ip __i, const _Ip __j, const iter_difference_t<_Ip> __n) { 178fe6060f1SDimitry Andric { __i += __n } -> same_as<_Ip&>; 179fe6060f1SDimitry Andric { __j + __n } -> same_as<_Ip>; 180fe6060f1SDimitry Andric { __n + __j } -> same_as<_Ip>; 181fe6060f1SDimitry Andric { __i -= __n } -> same_as<_Ip&>; 182fe6060f1SDimitry Andric { __j - __n } -> same_as<_Ip>; 183fe6060f1SDimitry Andric { __j[__n] } -> same_as<iter_reference_t<_Ip>>; 184fe6060f1SDimitry Andric }; 185fe6060f1SDimitry Andric 186fe6060f1SDimitry Andric template<class _Ip> 187fe6060f1SDimitry Andric concept contiguous_iterator = 188fe6060f1SDimitry Andric random_access_iterator<_Ip> && 189fe6060f1SDimitry Andric derived_from<_ITER_CONCEPT<_Ip>, contiguous_iterator_tag> && 190fe6060f1SDimitry Andric is_lvalue_reference_v<iter_reference_t<_Ip>> && 191fe6060f1SDimitry Andric same_as<iter_value_t<_Ip>, remove_cvref_t<iter_reference_t<_Ip>>> && 192fe6060f1SDimitry Andric requires(const _Ip& __i) { 193fe6060f1SDimitry Andric { _VSTD::to_address(__i) } -> same_as<add_pointer_t<iter_reference_t<_Ip>>>; 194fe6060f1SDimitry Andric }; 195fe6060f1SDimitry Andric 196fe6060f1SDimitry Andric template<class _Ip> 197fe6060f1SDimitry Andric concept __has_arrow = input_iterator<_Ip> && (is_pointer_v<_Ip> || requires(_Ip __i) { __i.operator->(); }); 198fe6060f1SDimitry Andric 199fe6060f1SDimitry Andric // [indirectcallable.indirectinvocable] 200fe6060f1SDimitry Andric template<class _Fp, class _It> 201fe6060f1SDimitry Andric concept indirectly_unary_invocable = 202fe6060f1SDimitry Andric indirectly_readable<_It> && 203fe6060f1SDimitry Andric copy_constructible<_Fp> && 204fe6060f1SDimitry Andric invocable<_Fp&, iter_value_t<_It>&> && 205fe6060f1SDimitry Andric invocable<_Fp&, iter_reference_t<_It>> && 206fe6060f1SDimitry Andric invocable<_Fp&, iter_common_reference_t<_It>> && 207fe6060f1SDimitry Andric common_reference_with< 208fe6060f1SDimitry Andric invoke_result_t<_Fp&, iter_value_t<_It>&>, 209fe6060f1SDimitry Andric invoke_result_t<_Fp&, iter_reference_t<_It>>>; 210fe6060f1SDimitry Andric 211fe6060f1SDimitry Andric template<class _Fp, class _It> 212fe6060f1SDimitry Andric concept indirectly_regular_unary_invocable = 213fe6060f1SDimitry Andric indirectly_readable<_It> && 214fe6060f1SDimitry Andric copy_constructible<_Fp> && 215fe6060f1SDimitry Andric regular_invocable<_Fp&, iter_value_t<_It>&> && 216fe6060f1SDimitry Andric regular_invocable<_Fp&, iter_reference_t<_It>> && 217fe6060f1SDimitry Andric regular_invocable<_Fp&, iter_common_reference_t<_It>> && 218fe6060f1SDimitry Andric common_reference_with< 219fe6060f1SDimitry Andric invoke_result_t<_Fp&, iter_value_t<_It>&>, 220fe6060f1SDimitry Andric invoke_result_t<_Fp&, iter_reference_t<_It>>>; 221fe6060f1SDimitry Andric 222fe6060f1SDimitry Andric template<class _Fp, class _It> 223fe6060f1SDimitry Andric concept indirect_unary_predicate = 224fe6060f1SDimitry Andric indirectly_readable<_It> && 225fe6060f1SDimitry Andric copy_constructible<_Fp> && 226fe6060f1SDimitry Andric predicate<_Fp&, iter_value_t<_It>&> && 227fe6060f1SDimitry Andric predicate<_Fp&, iter_reference_t<_It>> && 228fe6060f1SDimitry Andric predicate<_Fp&, iter_common_reference_t<_It>>; 229fe6060f1SDimitry Andric 230fe6060f1SDimitry Andric template<class _Fp, class _It1, class _It2> 231fe6060f1SDimitry Andric concept indirect_binary_predicate = 232fe6060f1SDimitry Andric indirectly_readable<_It1> && indirectly_readable<_It2> && 233fe6060f1SDimitry Andric copy_constructible<_Fp> && 234fe6060f1SDimitry Andric predicate<_Fp&, iter_value_t<_It1>&, iter_value_t<_It2>&> && 235fe6060f1SDimitry Andric predicate<_Fp&, iter_value_t<_It1>&, iter_reference_t<_It2>> && 236fe6060f1SDimitry Andric predicate<_Fp&, iter_reference_t<_It1>, iter_value_t<_It2>&> && 237fe6060f1SDimitry Andric predicate<_Fp&, iter_reference_t<_It1>, iter_reference_t<_It2>> && 238fe6060f1SDimitry Andric predicate<_Fp&, iter_common_reference_t<_It1>, iter_common_reference_t<_It2>>; 239fe6060f1SDimitry Andric 240fe6060f1SDimitry Andric template<class _Fp, class _It1, class _It2 = _It1> 241fe6060f1SDimitry Andric concept indirect_equivalence_relation = 242fe6060f1SDimitry Andric indirectly_readable<_It1> && indirectly_readable<_It2> && 243fe6060f1SDimitry Andric copy_constructible<_Fp> && 244fe6060f1SDimitry Andric equivalence_relation<_Fp&, iter_value_t<_It1>&, iter_value_t<_It2>&> && 245fe6060f1SDimitry Andric equivalence_relation<_Fp&, iter_value_t<_It1>&, iter_reference_t<_It2>> && 246fe6060f1SDimitry Andric equivalence_relation<_Fp&, iter_reference_t<_It1>, iter_value_t<_It2>&> && 247fe6060f1SDimitry Andric equivalence_relation<_Fp&, iter_reference_t<_It1>, iter_reference_t<_It2>> && 248fe6060f1SDimitry Andric equivalence_relation<_Fp&, iter_common_reference_t<_It1>, iter_common_reference_t<_It2>>; 249fe6060f1SDimitry Andric 250fe6060f1SDimitry Andric template<class _Fp, class _It1, class _It2 = _It1> 251fe6060f1SDimitry Andric concept indirect_strict_weak_order = 252fe6060f1SDimitry Andric indirectly_readable<_It1> && indirectly_readable<_It2> && 253fe6060f1SDimitry Andric copy_constructible<_Fp> && 254fe6060f1SDimitry Andric strict_weak_order<_Fp&, iter_value_t<_It1>&, iter_value_t<_It2>&> && 255fe6060f1SDimitry Andric strict_weak_order<_Fp&, iter_value_t<_It1>&, iter_reference_t<_It2>> && 256fe6060f1SDimitry Andric strict_weak_order<_Fp&, iter_reference_t<_It1>, iter_value_t<_It2>&> && 257fe6060f1SDimitry Andric strict_weak_order<_Fp&, iter_reference_t<_It1>, iter_reference_t<_It2>> && 258fe6060f1SDimitry Andric strict_weak_order<_Fp&, iter_common_reference_t<_It1>, iter_common_reference_t<_It2>>; 259fe6060f1SDimitry Andric 260fe6060f1SDimitry Andric template<class _Fp, class... _Its> 261fe6060f1SDimitry Andric requires (indirectly_readable<_Its> && ...) && invocable<_Fp, iter_reference_t<_Its>...> 262fe6060f1SDimitry Andric using indirect_result_t = invoke_result_t<_Fp, iter_reference_t<_Its>...>; 263fe6060f1SDimitry Andric 264fe6060f1SDimitry Andric template<class _In, class _Out> 265fe6060f1SDimitry Andric concept indirectly_movable = 266fe6060f1SDimitry Andric indirectly_readable<_In> && 267fe6060f1SDimitry Andric indirectly_writable<_Out, iter_rvalue_reference_t<_In>>; 268fe6060f1SDimitry Andric 269fe6060f1SDimitry Andric template<class _In, class _Out> 270fe6060f1SDimitry Andric concept indirectly_movable_storable = 271fe6060f1SDimitry Andric indirectly_movable<_In, _Out> && 272fe6060f1SDimitry Andric indirectly_writable<_Out, iter_value_t<_In>> && 273fe6060f1SDimitry Andric movable<iter_value_t<_In>> && 274fe6060f1SDimitry Andric constructible_from<iter_value_t<_In>, iter_rvalue_reference_t<_In>> && 275fe6060f1SDimitry Andric assignable_from<iter_value_t<_In>&, iter_rvalue_reference_t<_In>>; 276fe6060f1SDimitry Andric 27781ad6265SDimitry Andric template<class _In, class _Out> 27881ad6265SDimitry Andric concept indirectly_copyable = 27981ad6265SDimitry Andric indirectly_readable<_In> && 28081ad6265SDimitry Andric indirectly_writable<_Out, iter_reference_t<_In>>; 28181ad6265SDimitry Andric 28281ad6265SDimitry Andric template<class _In, class _Out> 28381ad6265SDimitry Andric concept indirectly_copyable_storable = 28481ad6265SDimitry Andric indirectly_copyable<_In, _Out> && 28581ad6265SDimitry Andric indirectly_writable<_Out, iter_value_t<_In>&> && 28681ad6265SDimitry Andric indirectly_writable<_Out, const iter_value_t<_In>&> && 28781ad6265SDimitry Andric indirectly_writable<_Out, iter_value_t<_In>&&> && 28881ad6265SDimitry Andric indirectly_writable<_Out, const iter_value_t<_In>&&> && 28981ad6265SDimitry Andric copyable<iter_value_t<_In>> && 29081ad6265SDimitry Andric constructible_from<iter_value_t<_In>, iter_reference_t<_In>> && 29181ad6265SDimitry Andric assignable_from<iter_value_t<_In>&, iter_reference_t<_In>>; 29281ad6265SDimitry Andric 293fe6060f1SDimitry Andric // Note: indirectly_swappable is located in iter_swap.h to prevent a dependency cycle 294fe6060f1SDimitry Andric // (both iter_swap and indirectly_swappable require indirectly_readable). 295fe6060f1SDimitry Andric 29681ad6265SDimitry Andric #endif // _LIBCPP_STD_VER > 17 297fe6060f1SDimitry Andric 298fe6060f1SDimitry Andric _LIBCPP_END_NAMESPACE_STD 299fe6060f1SDimitry Andric 300fe6060f1SDimitry Andric #endif // _LIBCPP___ITERATOR_CONCEPTS_H 301