348 lines · c
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-exception7//8//===----------------------------------------------------------------------===//9 10#ifndef _LIBCPP___ITERATOR_MOVE_ITERATOR_H11#define _LIBCPP___ITERATOR_MOVE_ITERATOR_H12 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_header40#endif41 42_LIBCPP_PUSH_MACROS43#include <__undef_macros>44 45_LIBCPP_BEGIN_NAMESPACE_STD46 47#if _LIBCPP_STD_VER >= 2048template <class _Iter, class = void>49struct __move_iter_category_base {};50 51template <class _Iter>52 requires requires { typename iterator_traits<_Iter>::iterator_category; }53struct __move_iter_category_base<_Iter> {54 using iterator_category =55 _If< derived_from<typename iterator_traits<_Iter>::iterator_category, random_access_iterator_tag>,56 random_access_iterator_tag,57 typename iterator_traits<_Iter>::iterator_category >;58};59 60template <class _Iter, class _Sent>61concept __move_iter_comparable = requires {62 { std::declval<const _Iter&>() == std::declval<_Sent>() } -> convertible_to<bool>;63};64#endif // _LIBCPP_STD_VER >= 2065 66template <class _Iter>67class move_iterator68#if _LIBCPP_STD_VER >= 2069 : public __move_iter_category_base<_Iter>70#endif71{72#if _LIBCPP_STD_VER >= 2073 74private:75 _LIBCPP_HIDE_FROM_ABI static constexpr auto __get_iter_concept() {76 if constexpr (random_access_iterator<_Iter>) {77 return random_access_iterator_tag{};78 } else if constexpr (bidirectional_iterator<_Iter>) {79 return bidirectional_iterator_tag{};80 } else if constexpr (forward_iterator<_Iter>) {81 return forward_iterator_tag{};82 } else {83 return input_iterator_tag{};84 }85 }86#endif // _LIBCPP_STD_VER >= 2087 88public:89#if _LIBCPP_STD_VER >= 2090 using iterator_type = _Iter;91 using iterator_concept = decltype(__get_iter_concept());92 // iterator_category is inherited and not always present93 using value_type = iter_value_t<_Iter>;94 using difference_type = iter_difference_t<_Iter>;95 using pointer = _Iter;96 using reference = iter_rvalue_reference_t<_Iter>;97#else98 typedef _Iter iterator_type;99 typedef _If< __has_random_access_iterator_category<_Iter>::value,100 random_access_iterator_tag,101 typename iterator_traits<_Iter>::iterator_category >102 iterator_category;103 typedef typename iterator_traits<iterator_type>::value_type value_type;104 typedef typename iterator_traits<iterator_type>::difference_type difference_type;105 typedef iterator_type pointer;106 107 typedef typename iterator_traits<iterator_type>::reference __reference;108 typedef __conditional_t<is_reference<__reference>::value, __libcpp_remove_reference_t<__reference>&&, __reference>109 reference;110#endif // _LIBCPP_STD_VER >= 20111 112 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 explicit move_iterator(_Iter __i) : __current_(std::move(__i)) {}113 114 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 move_iterator& operator++() {115 ++__current_;116 return *this;117 }118 119 _LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 pointer operator->() const {120 return __current_;121 }122 123#if _LIBCPP_STD_VER >= 20124 _LIBCPP_HIDE_FROM_ABI constexpr move_iterator()125 requires is_constructible_v<_Iter>126 : __current_() {}127 128 template <class _Up>129 requires(!_IsSame<_Up, _Iter>::value) && convertible_to<const _Up&, _Iter>130 _LIBCPP_HIDE_FROM_ABI constexpr move_iterator(const move_iterator<_Up>& __u) : __current_(__u.base()) {}131 132 template <class _Up>133 requires(!_IsSame<_Up, _Iter>::value) && convertible_to<const _Up&, _Iter> && assignable_from<_Iter&, const _Up&>134 _LIBCPP_HIDE_FROM_ABI constexpr move_iterator& operator=(const move_iterator<_Up>& __u) {135 __current_ = __u.base();136 return *this;137 }138 139 _LIBCPP_HIDE_FROM_ABI constexpr const _Iter& base() const& noexcept { return __current_; }140 _LIBCPP_HIDE_FROM_ABI constexpr _Iter base() && { return std::move(__current_); }141 142 _LIBCPP_HIDE_FROM_ABI constexpr reference operator*() const { return ranges::iter_move(__current_); }143 _LIBCPP_HIDE_FROM_ABI constexpr reference operator[](difference_type __n) const {144 return ranges::iter_move(__current_ + __n);145 }146 147 _LIBCPP_HIDE_FROM_ABI constexpr auto operator++(int)148 requires forward_iterator<_Iter>149 {150 move_iterator __tmp(*this);151 ++__current_;152 return __tmp;153 }154 155 _LIBCPP_HIDE_FROM_ABI constexpr void operator++(int) { ++__current_; }156#else157 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 move_iterator() : __current_() {}158 159 template <class _Up, __enable_if_t< !is_same<_Up, _Iter>::value && is_convertible<const _Up&, _Iter>::value, int> = 0>160 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 move_iterator(const move_iterator<_Up>& __u)161 : __current_(__u.base()) {}162 163 template <class _Up,164 __enable_if_t< !is_same<_Up, _Iter>::value && is_convertible<const _Up&, _Iter>::value &&165 is_assignable<_Iter&, const _Up&>::value,166 int> = 0>167 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 move_iterator& operator=(const move_iterator<_Up>& __u) {168 __current_ = __u.base();169 return *this;170 }171 172 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 _Iter base() const { return __current_; }173 174 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 reference operator*() const {175 return static_cast<reference>(*__current_);176 }177 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 reference operator[](difference_type __n) const {178 return static_cast<reference>(__current_[__n]);179 }180 181 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 move_iterator operator++(int) {182 move_iterator __tmp(*this);183 ++__current_;184 return __tmp;185 }186#endif // _LIBCPP_STD_VER >= 20187 188 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 move_iterator& operator--() {189 --__current_;190 return *this;191 }192 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 move_iterator operator--(int) {193 move_iterator __tmp(*this);194 --__current_;195 return __tmp;196 }197 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 move_iterator operator+(difference_type __n) const {198 return move_iterator(__current_ + __n);199 }200 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 move_iterator& operator+=(difference_type __n) {201 __current_ += __n;202 return *this;203 }204 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 move_iterator operator-(difference_type __n) const {205 return move_iterator(__current_ - __n);206 }207 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 move_iterator& operator-=(difference_type __n) {208 __current_ -= __n;209 return *this;210 }211 212#if _LIBCPP_STD_VER >= 20213 template <sentinel_for<_Iter> _Sent>214 friend _LIBCPP_HIDE_FROM_ABI constexpr bool operator==(const move_iterator& __x, const move_sentinel<_Sent>& __y)215 requires __move_iter_comparable<_Iter, _Sent>216 {217 return __x.base() == __y.base();218 }219 220 template <sized_sentinel_for<_Iter> _Sent>221 friend _LIBCPP_HIDE_FROM_ABI constexpr iter_difference_t<_Iter>222 operator-(const move_sentinel<_Sent>& __x, const move_iterator& __y) {223 return __x.base() - __y.base();224 }225 226 template <sized_sentinel_for<_Iter> _Sent>227 friend _LIBCPP_HIDE_FROM_ABI constexpr iter_difference_t<_Iter>228 operator-(const move_iterator& __x, const move_sentinel<_Sent>& __y) {229 return __x.base() - __y.base();230 }231 232 friend _LIBCPP_HIDE_FROM_ABI constexpr iter_rvalue_reference_t<_Iter>233 iter_move(const move_iterator& __i) noexcept(noexcept(ranges::iter_move(__i.__current_))) {234 return ranges::iter_move(__i.__current_);235 }236 237 template <indirectly_swappable<_Iter> _It2>238 friend _LIBCPP_HIDE_FROM_ABI constexpr void239 iter_swap(const move_iterator& __x,240 const move_iterator<_It2>& __y) noexcept(noexcept(ranges::iter_swap(__x.__current_, __y.__current_))) {241 return ranges::iter_swap(__x.__current_, __y.__current_);242 }243#endif // _LIBCPP_STD_VER >= 20244 245private:246 template <class _It2>247 friend class move_iterator;248 249 _Iter __current_;250};251_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(move_iterator);252 253template <class _Iter1, class _Iter2>254inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 bool255operator==(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y) {256 return __x.base() == __y.base();257}258 259#if _LIBCPP_STD_VER <= 17260template <class _Iter1, class _Iter2>261inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 bool262operator!=(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y) {263 return __x.base() != __y.base();264}265#endif // _LIBCPP_STD_VER <= 17266 267template <class _Iter1, class _Iter2>268inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 bool269operator<(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y) {270 return __x.base() < __y.base();271}272 273template <class _Iter1, class _Iter2>274inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 bool275operator>(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y) {276 return __x.base() > __y.base();277}278 279template <class _Iter1, class _Iter2>280inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 bool281operator<=(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y) {282 return __x.base() <= __y.base();283}284 285template <class _Iter1, class _Iter2>286inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 bool287operator>=(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y) {288 return __x.base() >= __y.base();289}290 291#if _LIBCPP_STD_VER >= 20292template <class _Iter1, three_way_comparable_with<_Iter1> _Iter2>293inline _LIBCPP_HIDE_FROM_ABI constexpr auto294operator<=>(const move_iterator<_Iter1>& __x,295 const move_iterator<_Iter2>& __y) -> compare_three_way_result_t<_Iter1, _Iter2> {296 return __x.base() <=> __y.base();297}298#endif // _LIBCPP_STD_VER >= 20299 300#ifndef _LIBCPP_CXX03_LANG301template <class _Iter1, class _Iter2>302inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 auto303operator-(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y) -> decltype(__x.base() - __y.base()) {304 return __x.base() - __y.base();305}306#else307template <class _Iter1, class _Iter2>308inline _LIBCPP_HIDE_FROM_ABI typename move_iterator<_Iter1>::difference_type309operator-(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y) {310 return __x.base() - __y.base();311}312#endif // !_LIBCPP_CXX03_LANG313 314#if _LIBCPP_STD_VER >= 20315template <class _Iter>316inline _LIBCPP_HIDE_FROM_ABI constexpr move_iterator<_Iter>317operator+(iter_difference_t<_Iter> __n, const move_iterator<_Iter>& __x)318 requires requires {319 { __x.base() + __n } -> same_as<_Iter>;320 }321{322 return __x + __n;323}324#else325template <class _Iter>326inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 move_iterator<_Iter>327operator+(typename move_iterator<_Iter>::difference_type __n, const move_iterator<_Iter>& __x) {328 return move_iterator<_Iter>(__x.base() + __n);329}330#endif // _LIBCPP_STD_VER >= 20331 332#if _LIBCPP_STD_VER >= 20333template <class _Iter1, class _Iter2>334 requires(!sized_sentinel_for<_Iter1, _Iter2>)335inline constexpr bool disable_sized_sentinel_for<move_iterator<_Iter1>, move_iterator<_Iter2>> = true;336#endif // _LIBCPP_STD_VER >= 20337 338template <class _Iter>339inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 move_iterator<_Iter> make_move_iterator(_Iter __i) {340 return move_iterator<_Iter>(std::move(__i));341}342 343_LIBCPP_END_NAMESPACE_STD344 345_LIBCPP_POP_MACROS346 347#endif // _LIBCPP___ITERATOR_MOVE_ITERATOR_H348