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