1 // -*- C++ -*- 2 //===----------------------------------------------------------------------===// 3 // 4 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5 // See https://llvm.org/LICENSE.txt for license information. 6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7 // 8 //===----------------------------------------------------------------------===// 9 10 #ifndef _LIBCPP___ITERATOR_MOVE_ITERATOR_H 11 #define _LIBCPP___ITERATOR_MOVE_ITERATOR_H 12 13 #include <__compare/compare_three_way_result.h> 14 #include <__compare/three_way_comparable.h> 15 #include <__concepts/assignable.h> 16 #include <__concepts/convertible_to.h> 17 #include <__concepts/derived_from.h> 18 #include <__concepts/same_as.h> 19 #include <__config> 20 #include <__iterator/concepts.h> 21 #include <__iterator/incrementable_traits.h> 22 #include <__iterator/iter_move.h> 23 #include <__iterator/iter_swap.h> 24 #include <__iterator/iterator_traits.h> 25 #include <__iterator/move_sentinel.h> 26 #include <__iterator/readable_traits.h> 27 #include <__type_traits/conditional.h> 28 #include <__type_traits/enable_if.h> 29 #include <__type_traits/is_assignable.h> 30 #include <__type_traits/is_constructible.h> 31 #include <__type_traits/is_convertible.h> 32 #include <__type_traits/is_reference.h> 33 #include <__type_traits/is_same.h> 34 #include <__type_traits/remove_reference.h> 35 #include <__utility/declval.h> 36 #include <__utility/move.h> 37 38 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 39 # pragma GCC system_header 40 #endif 41 42 _LIBCPP_BEGIN_NAMESPACE_STD 43 44 #if _LIBCPP_STD_VER >= 20 45 template<class _Iter, class = void> 46 struct __move_iter_category_base {}; 47 48 template<class _Iter> 49 requires requires { typename iterator_traits<_Iter>::iterator_category; } 50 struct __move_iter_category_base<_Iter> { 51 using iterator_category = _If< 52 derived_from<typename iterator_traits<_Iter>::iterator_category, random_access_iterator_tag>, 53 random_access_iterator_tag, 54 typename iterator_traits<_Iter>::iterator_category 55 >; 56 }; 57 58 template<class _Iter, class _Sent> 59 concept __move_iter_comparable = requires { 60 { std::declval<const _Iter&>() == std::declval<_Sent>() } -> convertible_to<bool>; 61 }; 62 #endif // _LIBCPP_STD_VER >= 20 63 64 template <class _Iter> 65 class _LIBCPP_TEMPLATE_VIS move_iterator 66 #if _LIBCPP_STD_VER >= 20 67 : public __move_iter_category_base<_Iter> 68 #endif 69 { 70 #if _LIBCPP_STD_VER >= 20 71 private: 72 _LIBCPP_HIDE_FROM_ABI 73 static constexpr auto __get_iter_concept() { 74 if constexpr (random_access_iterator<_Iter>) { 75 return random_access_iterator_tag{}; 76 } else if constexpr (bidirectional_iterator<_Iter>) { 77 return bidirectional_iterator_tag{}; 78 } else if constexpr (forward_iterator<_Iter>) { 79 return forward_iterator_tag{}; 80 } else { 81 return input_iterator_tag{}; 82 } 83 } 84 #endif // _LIBCPP_STD_VER >= 20 85 public: 86 #if _LIBCPP_STD_VER >= 20 87 using iterator_type = _Iter; 88 using iterator_concept = decltype(__get_iter_concept()); 89 // iterator_category is inherited and not always present 90 using value_type = iter_value_t<_Iter>; 91 using difference_type = iter_difference_t<_Iter>; 92 using pointer = _Iter; 93 using reference = iter_rvalue_reference_t<_Iter>; 94 #else 95 typedef _Iter iterator_type; 96 typedef _If< 97 __is_cpp17_random_access_iterator<_Iter>::value, 98 random_access_iterator_tag, 99 typename iterator_traits<_Iter>::iterator_category 100 > iterator_category; 101 typedef typename iterator_traits<iterator_type>::value_type value_type; 102 typedef typename iterator_traits<iterator_type>::difference_type difference_type; 103 typedef iterator_type pointer; 104 105 typedef typename iterator_traits<iterator_type>::reference __reference; 106 typedef typename conditional< 107 is_reference<__reference>::value, 108 __libcpp_remove_reference_t<__reference>&&, 109 __reference 110 >::type reference; 111 #endif // _LIBCPP_STD_VER >= 20 112 113 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 114 explicit move_iterator(_Iter __i) : __current_(std::move(__i)) {} 115 116 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 117 move_iterator& operator++() { ++__current_; return *this; } 118 119 _LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 120 pointer operator->() const { return __current_; } 121 122 #if _LIBCPP_STD_VER >= 20 123 _LIBCPP_HIDE_FROM_ABI constexpr 124 move_iterator() requires is_constructible_v<_Iter> : __current_() {} 125 126 template <class _Up> 127 requires (!_IsSame<_Up, _Iter>::value) && convertible_to<const _Up&, _Iter> 128 _LIBCPP_HIDE_FROM_ABI constexpr 129 move_iterator(const move_iterator<_Up>& __u) : __current_(__u.base()) {} 130 131 template <class _Up> 132 requires (!_IsSame<_Up, _Iter>::value) && 133 convertible_to<const _Up&, _Iter> && 134 assignable_from<_Iter&, const _Up&> 135 _LIBCPP_HIDE_FROM_ABI constexpr 136 move_iterator& operator=(const move_iterator<_Up>& __u) { 137 __current_ = __u.base(); 138 return *this; 139 } 140 141 _LIBCPP_HIDE_FROM_ABI constexpr const _Iter& base() const & noexcept { return __current_; } 142 _LIBCPP_HIDE_FROM_ABI constexpr _Iter base() && { return std::move(__current_); } 143 144 _LIBCPP_HIDE_FROM_ABI constexpr 145 reference operator*() const { return ranges::iter_move(__current_); } 146 _LIBCPP_HIDE_FROM_ABI constexpr 147 reference operator[](difference_type __n) const { return ranges::iter_move(__current_ + __n); } 148 149 _LIBCPP_HIDE_FROM_ABI constexpr 150 auto operator++(int) 151 requires forward_iterator<_Iter> 152 { 153 move_iterator __tmp(*this); ++__current_; return __tmp; 154 } 155 156 _LIBCPP_HIDE_FROM_ABI constexpr 157 void operator++(int) { ++__current_; } 158 #else 159 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 160 move_iterator() : __current_() {} 161 162 template <class _Up, class = __enable_if_t< 163 !is_same<_Up, _Iter>::value && is_convertible<const _Up&, _Iter>::value 164 > > 165 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 166 move_iterator(const move_iterator<_Up>& __u) : __current_(__u.base()) {} 167 168 template <class _Up, class = __enable_if_t< 169 !is_same<_Up, _Iter>::value && 170 is_convertible<const _Up&, _Iter>::value && 171 is_assignable<_Iter&, const _Up&>::value 172 > > 173 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 174 move_iterator& operator=(const move_iterator<_Up>& __u) { 175 __current_ = __u.base(); 176 return *this; 177 } 178 179 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 180 _Iter base() const { return __current_; } 181 182 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 183 reference operator*() const { return static_cast<reference>(*__current_); } 184 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 185 reference operator[](difference_type __n) const { return static_cast<reference>(__current_[__n]); } 186 187 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 188 move_iterator operator++(int) { move_iterator __tmp(*this); ++__current_; return __tmp; } 189 #endif // _LIBCPP_STD_VER >= 20 190 191 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 192 move_iterator& operator--() { --__current_; return *this; } 193 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 194 move_iterator operator--(int) { move_iterator __tmp(*this); --__current_; return __tmp; } 195 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 196 move_iterator operator+(difference_type __n) const { return move_iterator(__current_ + __n); } 197 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 198 move_iterator& operator+=(difference_type __n) { __current_ += __n; return *this; } 199 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 200 move_iterator operator-(difference_type __n) const { return move_iterator(__current_ - __n); } 201 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 202 move_iterator& operator-=(difference_type __n) { __current_ -= __n; return *this; } 203 204 #if _LIBCPP_STD_VER >= 20 205 template<sentinel_for<_Iter> _Sent> 206 friend _LIBCPP_HIDE_FROM_ABI constexpr 207 bool operator==(const move_iterator& __x, const move_sentinel<_Sent>& __y) 208 requires __move_iter_comparable<_Iter, _Sent> 209 { 210 return __x.base() == __y.base(); 211 } 212 213 template<sized_sentinel_for<_Iter> _Sent> 214 friend _LIBCPP_HIDE_FROM_ABI constexpr 215 iter_difference_t<_Iter> operator-(const move_sentinel<_Sent>& __x, const move_iterator& __y) 216 { 217 return __x.base() - __y.base(); 218 } 219 220 template<sized_sentinel_for<_Iter> _Sent> 221 friend _LIBCPP_HIDE_FROM_ABI constexpr 222 iter_difference_t<_Iter> operator-(const move_iterator& __x, const move_sentinel<_Sent>& __y) 223 { 224 return __x.base() - __y.base(); 225 } 226 227 friend _LIBCPP_HIDE_FROM_ABI constexpr 228 iter_rvalue_reference_t<_Iter> iter_move(const move_iterator& __i) 229 noexcept(noexcept(ranges::iter_move(__i.__current_))) 230 { 231 return ranges::iter_move(__i.__current_); 232 } 233 234 template<indirectly_swappable<_Iter> _It2> 235 friend _LIBCPP_HIDE_FROM_ABI constexpr 236 void iter_swap(const move_iterator& __x, const move_iterator<_It2>& __y) 237 noexcept(noexcept(ranges::iter_swap(__x.__current_, __y.__current_))) 238 { 239 return ranges::iter_swap(__x.__current_, __y.__current_); 240 } 241 #endif // _LIBCPP_STD_VER >= 20 242 243 private: 244 template<class _It2> friend class move_iterator; 245 246 _Iter __current_; 247 }; 248 _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(move_iterator); 249 250 template <class _Iter1, class _Iter2> 251 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 252 bool operator==(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y) 253 { 254 return __x.base() == __y.base(); 255 } 256 257 #if _LIBCPP_STD_VER <= 17 258 template <class _Iter1, class _Iter2> 259 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 260 bool operator!=(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y) 261 { 262 return __x.base() != __y.base(); 263 } 264 #endif // _LIBCPP_STD_VER <= 17 265 266 template <class _Iter1, class _Iter2> 267 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 268 bool operator<(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y) 269 { 270 return __x.base() < __y.base(); 271 } 272 273 template <class _Iter1, class _Iter2> 274 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 275 bool operator>(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y) 276 { 277 return __x.base() > __y.base(); 278 } 279 280 template <class _Iter1, class _Iter2> 281 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 282 bool operator<=(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y) 283 { 284 return __x.base() <= __y.base(); 285 } 286 287 template <class _Iter1, class _Iter2> 288 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 289 bool operator>=(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y) 290 { 291 return __x.base() >= __y.base(); 292 } 293 294 #if _LIBCPP_STD_VER >= 20 295 template <class _Iter1, three_way_comparable_with<_Iter1> _Iter2> 296 inline _LIBCPP_HIDE_FROM_ABI constexpr 297 auto operator<=>(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y) 298 -> compare_three_way_result_t<_Iter1, _Iter2> 299 { 300 return __x.base() <=> __y.base(); 301 } 302 #endif // _LIBCPP_STD_VER >= 20 303 304 #ifndef _LIBCPP_CXX03_LANG 305 template <class _Iter1, class _Iter2> 306 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 307 auto operator-(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y) 308 -> decltype(__x.base() - __y.base()) 309 { 310 return __x.base() - __y.base(); 311 } 312 #else 313 template <class _Iter1, class _Iter2> 314 inline _LIBCPP_HIDE_FROM_ABI 315 typename move_iterator<_Iter1>::difference_type 316 operator-(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y) 317 { 318 return __x.base() - __y.base(); 319 } 320 #endif // !_LIBCPP_CXX03_LANG 321 322 #if _LIBCPP_STD_VER >= 20 323 template <class _Iter> 324 inline _LIBCPP_HIDE_FROM_ABI constexpr 325 move_iterator<_Iter> operator+(iter_difference_t<_Iter> __n, const move_iterator<_Iter>& __x) 326 requires requires { { __x.base() + __n } -> same_as<_Iter>; } 327 { 328 return __x + __n; 329 } 330 #else 331 template <class _Iter> 332 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 333 move_iterator<_Iter> 334 operator+(typename move_iterator<_Iter>::difference_type __n, const move_iterator<_Iter>& __x) 335 { 336 return move_iterator<_Iter>(__x.base() + __n); 337 } 338 #endif // _LIBCPP_STD_VER >= 20 339 340 template <class _Iter> 341 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 342 move_iterator<_Iter> 343 make_move_iterator(_Iter __i) 344 { 345 return move_iterator<_Iter>(std::move(__i)); 346 } 347 348 _LIBCPP_END_NAMESPACE_STD 349 350 #endif // _LIBCPP___ITERATOR_MOVE_ITERATOR_H 351