1 //===----------------------------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #ifndef _LIBCPP___ITERATOR_CPP17_ITERATOR_CONCEPTS_H 10 #define _LIBCPP___ITERATOR_CPP17_ITERATOR_CONCEPTS_H 11 12 #include <__concepts/boolean_testable.h> 13 #include <__concepts/convertible_to.h> 14 #include <__concepts/same_as.h> 15 #include <__config> 16 #include <__iterator/iterator_traits.h> 17 #include <__type_traits/is_constructible.h> 18 #include <__type_traits/is_convertible.h> 19 #include <__type_traits/is_signed.h> 20 #include <__type_traits/is_void.h> 21 #include <__utility/as_const.h> 22 #include <__utility/forward.h> 23 #include <__utility/move.h> 24 #include <__utility/swap.h> 25 26 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 27 # pragma GCC system_header 28 #endif 29 30 _LIBCPP_PUSH_MACROS 31 #include <__undef_macros> 32 33 #if _LIBCPP_STD_VER >= 20 34 35 _LIBCPP_BEGIN_NAMESPACE_STD 36 37 template <class _Tp> 38 concept __cpp17_move_constructible = is_move_constructible_v<_Tp>; 39 40 template <class _Tp> 41 concept __cpp17_copy_constructible = __cpp17_move_constructible<_Tp> && is_copy_constructible_v<_Tp>; 42 43 template <class _Tp> 44 concept __cpp17_move_assignable = requires(_Tp __lhs, _Tp __rhs) { 45 { __lhs = std::move(__rhs) } -> same_as<_Tp&>; 46 }; 47 48 template <class _Tp> 49 concept __cpp17_copy_assignable = __cpp17_move_assignable<_Tp> && requires(_Tp __lhs, _Tp __rhs) { 50 { __lhs = __rhs } -> same_as<_Tp&>; 51 { __lhs = std::as_const(__rhs) } -> same_as<_Tp&>; 52 }; 53 54 template <class _Tp> 55 concept __cpp17_destructible = requires(_Tp __v) { __v.~_Tp(); }; 56 57 template <class _Tp> 58 concept __cpp17_equality_comparable = requires(_Tp __lhs, _Tp __rhs) { 59 { __lhs == __rhs } -> __boolean_testable; 60 { std::as_const(__lhs) == __rhs } -> __boolean_testable; 61 { __lhs == std::as_const(__rhs) } -> __boolean_testable; 62 { std::as_const(__lhs) == std::as_const(__rhs) } -> __boolean_testable; 63 }; 64 65 template <class _Tp> 66 concept __cpp17_default_constructible = is_default_constructible_v<_Tp>; 67 68 template <class _Iter> 69 concept __cpp17_iterator = 70 __cpp17_copy_constructible<_Iter> && __cpp17_copy_assignable<_Iter> && __cpp17_destructible<_Iter> && 71 (is_signed_v<__iter_diff_t<_Iter>> || is_void_v<__iter_diff_t<_Iter>>) && requires(_Iter __iter) { 72 { *__iter }; 73 { ++__iter } -> same_as<_Iter&>; 74 }; 75 76 template <class _Iter> 77 concept __cpp17_input_iterator = 78 __cpp17_iterator<_Iter> && __cpp17_equality_comparable<_Iter> && requires(_Iter __lhs, _Iter __rhs) { 79 { __lhs != __rhs } -> __boolean_testable; 80 { std::as_const(__lhs) != __rhs } -> __boolean_testable; 81 { __lhs != std::as_const(__rhs) } -> __boolean_testable; 82 { std::as_const(__lhs) != std::as_const(__rhs) } -> __boolean_testable; 83 84 { *__lhs } -> same_as<__iter_reference<_Iter>>; 85 { *std::as_const(__lhs) } -> same_as<__iter_reference<_Iter>>; 86 87 { ++__lhs } -> same_as<_Iter&>; 88 { (void)__lhs++ }; 89 { *__lhs++ }; 90 }; 91 92 template <class _Iter, class _WriteTo> 93 concept __cpp17_output_iterator = __cpp17_iterator<_Iter> && requires(_Iter __iter, _WriteTo __write) { 94 { *__iter = std::forward<_WriteTo>(__write) }; 95 { ++__iter } -> same_as<_Iter&>; 96 { __iter++ } -> convertible_to<const _Iter&>; 97 { *__iter++ = std::forward<_WriteTo>(__write) }; 98 }; 99 100 template <class _Iter> 101 concept __cpp17_forward_iterator = 102 __cpp17_input_iterator<_Iter> && __cpp17_default_constructible<_Iter> && requires(_Iter __iter) { 103 { __iter++ } -> convertible_to<const _Iter&>; 104 { *__iter++ } -> same_as<__iter_reference<_Iter>>; 105 }; 106 107 template <class _Iter> 108 concept __cpp17_bidirectional_iterator = __cpp17_forward_iterator<_Iter> && requires(_Iter __iter) { 109 { --__iter } -> same_as<_Iter&>; 110 { __iter-- } -> convertible_to<const _Iter&>; 111 { *__iter-- } -> same_as<__iter_reference<_Iter>>; 112 }; 113 114 template <class _Iter> 115 concept __cpp17_random_access_iterator = 116 __cpp17_bidirectional_iterator<_Iter> && requires(_Iter __iter, __iter_diff_t<_Iter> __n) { 117 { __iter += __n } -> same_as<_Iter&>; 118 119 { __iter + __n } -> same_as<_Iter>; 120 { __n + __iter } -> same_as<_Iter>; 121 { std::as_const(__iter) + __n } -> same_as<_Iter>; 122 { __n + std::as_const(__iter) } -> same_as<_Iter>; 123 124 { __iter -= __n } -> same_as<_Iter&>; 125 { __iter - __n } -> same_as<_Iter>; 126 { std::as_const(__iter) - __n } -> same_as<_Iter>; 127 128 { __iter - __iter } -> same_as<__iter_diff_t<_Iter>>; 129 { std::as_const(__iter) - __iter } -> same_as<__iter_diff_t<_Iter>>; 130 { __iter - std::as_const(__iter) } -> same_as<__iter_diff_t<_Iter>>; 131 { std::as_const(__iter) - std::as_const(__iter) } -> same_as<__iter_diff_t<_Iter>>; 132 133 { __iter[__n] } -> convertible_to<__iter_reference<_Iter>>; 134 { std::as_const(__iter)[__n] } -> convertible_to<__iter_reference<_Iter>>; 135 136 { __iter < __iter } -> __boolean_testable; 137 { std::as_const(__iter) < __iter } -> __boolean_testable; 138 { __iter < std::as_const(__iter) } -> __boolean_testable; 139 { std::as_const(__iter) < std::as_const(__iter) } -> __boolean_testable; 140 141 { __iter > __iter } -> __boolean_testable; 142 { std::as_const(__iter) > __iter } -> __boolean_testable; 143 { __iter > std::as_const(__iter) } -> __boolean_testable; 144 { std::as_const(__iter) > std::as_const(__iter) } -> __boolean_testable; 145 146 { __iter >= __iter } -> __boolean_testable; 147 { std::as_const(__iter) >= __iter } -> __boolean_testable; 148 { __iter >= std::as_const(__iter) } -> __boolean_testable; 149 { std::as_const(__iter) >= std::as_const(__iter) } -> __boolean_testable; 150 151 { __iter <= __iter } -> __boolean_testable; 152 { std::as_const(__iter) <= __iter } -> __boolean_testable; 153 { __iter <= std::as_const(__iter) } -> __boolean_testable; 154 { std::as_const(__iter) <= std::as_const(__iter) } -> __boolean_testable; 155 }; 156 157 _LIBCPP_END_NAMESPACE_STD 158 159 # ifndef _LIBCPP_DISABLE_ITERATOR_CHECKS 160 # define _LIBCPP_REQUIRE_CPP17_INPUT_ITERATOR(iter_t, message) \ 161 static_assert(::std::__cpp17_input_iterator<iter_t>, message) 162 # define _LIBCPP_REQUIRE_CPP17_OUTPUT_ITERATOR(iter_t, write_t, message) \ 163 static_assert(::std::__cpp17_output_iterator<iter_t, write_t>, message) 164 # define _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(iter_t, message) \ 165 static_assert(::std::__cpp17_forward_iterator<iter_t>, message) 166 # define _LIBCPP_REQUIRE_CPP17_BIDIRECTIONAL_ITERATOR(iter_t, message) \ 167 static_assert(::std::__cpp17_bidirectional_iterator<iter_t>, message) 168 # define _LIBCPP_REQUIRE_CPP17_RANDOM_ACCESS_ITERATOR(iter_t, message) \ 169 static_assert(::std::__cpp17_random_access_iterator<iter_t>, message) 170 # else 171 # define _LIBCPP_REQUIRE_CPP17_INPUT_ITERATOR(iter_t, message) static_assert(true) 172 # define _LIBCPP_REQUIRE_CPP17_OUTPUT_ITERATOR(iter_t, write_t, message) static_assert(true) 173 # define _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(iter_t, message) static_assert(true) 174 # define _LIBCPP_REQUIRE_CPP17_BIDIRECTIONAL_ITERATOR(iter_t, message) static_assert(true) 175 # define _LIBCPP_REQUIRE_CPP17_RANDOM_ACCESS_ITERATOR(iter_t, message) static_assert(true) 176 # endif 177 178 #else // _LIBCPP_STD_VER >= 20 179 180 # define _LIBCPP_REQUIRE_CPP17_INPUT_ITERATOR(iter_t, message) static_assert(true) 181 # define _LIBCPP_REQUIRE_CPP17_OUTPUT_ITERATOR(iter_t, write_t, message) static_assert(true) 182 # define _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(iter_t, message) static_assert(true) 183 # define _LIBCPP_REQUIRE_CPP17_BIDIRECTIONAL_ITERATOR(iter_t, message) static_assert(true) 184 # define _LIBCPP_REQUIRE_CPP17_RANDOM_ACCESS_ITERATOR(iter_t, message) static_assert(true) 185 186 #endif // _LIBCPP_STD_VER >= 20 187 188 _LIBCPP_POP_MACROS 189 190 #endif // _LIBCPP___ITERATOR_CPP17_ITERATOR_CONCEPTS_H 191