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___ALGORITHM_ITERATOR_OPERATIONS_H 10 #define _LIBCPP___ALGORITHM_ITERATOR_OPERATIONS_H 11 12 #include <__algorithm/iter_swap.h> 13 #include <__algorithm/ranges_iterator_concept.h> 14 #include <__config> 15 #include <__iterator/advance.h> 16 #include <__iterator/distance.h> 17 #include <__iterator/incrementable_traits.h> 18 #include <__iterator/iter_move.h> 19 #include <__iterator/iter_swap.h> 20 #include <__iterator/iterator_traits.h> 21 #include <__iterator/next.h> 22 #include <__iterator/prev.h> 23 #include <__iterator/readable_traits.h> 24 #include <__type_traits/enable_if.h> 25 #include <__type_traits/is_reference.h> 26 #include <__type_traits/is_same.h> 27 #include <__type_traits/remove_cvref.h> 28 #include <__utility/declval.h> 29 #include <__utility/forward.h> 30 #include <__utility/move.h> 31 32 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 33 # pragma GCC system_header 34 #endif 35 36 _LIBCPP_PUSH_MACROS 37 #include <__undef_macros> 38 39 _LIBCPP_BEGIN_NAMESPACE_STD 40 41 template <class _AlgPolicy> struct _IterOps; 42 43 #if _LIBCPP_STD_VER >= 20 44 struct _RangeAlgPolicy {}; 45 46 template <> 47 struct _IterOps<_RangeAlgPolicy> { 48 49 template <class _Iter> 50 using __value_type = iter_value_t<_Iter>; 51 52 template <class _Iter> 53 using __iterator_category = ranges::__iterator_concept<_Iter>; 54 55 template <class _Iter> 56 using __difference_type = iter_difference_t<_Iter>; 57 58 static constexpr auto advance = ranges::advance; 59 static constexpr auto distance = ranges::distance; 60 static constexpr auto __iter_move = ranges::iter_move; 61 static constexpr auto iter_swap = ranges::iter_swap; 62 static constexpr auto next = ranges::next; 63 static constexpr auto prev = ranges::prev; 64 static constexpr auto __advance_to = ranges::advance; 65 }; 66 67 #endif 68 69 struct _ClassicAlgPolicy {}; 70 71 template <> 72 struct _IterOps<_ClassicAlgPolicy> { 73 74 template <class _Iter> 75 using __value_type = typename iterator_traits<_Iter>::value_type; 76 77 template <class _Iter> 78 using __iterator_category = typename iterator_traits<_Iter>::iterator_category; 79 80 template <class _Iter> 81 using __difference_type = typename iterator_traits<_Iter>::difference_type; 82 83 // advance 84 template <class _Iter, class _Distance> 85 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 86 static void advance(_Iter& __iter, _Distance __count) { 87 std::advance(__iter, __count); 88 } 89 90 // distance 91 template <class _Iter> 92 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 93 static typename iterator_traits<_Iter>::difference_type distance(_Iter __first, _Iter __last) { 94 return std::distance(__first, __last); 95 } 96 97 template <class _Iter> 98 using __deref_t = decltype(*std::declval<_Iter&>()); 99 100 template <class _Iter> 101 using __move_t = decltype(std::move(*std::declval<_Iter&>())); 102 103 template <class _Iter> 104 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 105 static void __validate_iter_reference() { 106 static_assert(is_same<__deref_t<_Iter>, typename iterator_traits<__remove_cvref_t<_Iter> >::reference>::value, 107 "It looks like your iterator's `iterator_traits<It>::reference` does not match the return type of " 108 "dereferencing the iterator, i.e., calling `*it`. This is undefined behavior according to [input.iterators] " 109 "and can lead to dangling reference issues at runtime, so we are flagging this."); 110 } 111 112 // iter_move 113 template <class _Iter> 114 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 static 115 // If the result of dereferencing `_Iter` is a reference type, deduce the result of calling `std::move` on it. Note 116 // that the C++03 mode doesn't support `decltype(auto)` as the return type. 117 __enable_if_t< 118 is_reference<__deref_t<_Iter> >::value, 119 __move_t<_Iter> > 120 __iter_move(_Iter&& __i) { 121 __validate_iter_reference<_Iter>(); 122 123 return std::move(*std::forward<_Iter>(__i)); 124 } 125 126 template <class _Iter> 127 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 static 128 // If the result of dereferencing `_Iter` is a value type, deduce the return value of this function to also be a 129 // value -- otherwise, after `operator*` returns a temporary, this function would return a dangling reference to that 130 // temporary. Note that the C++03 mode doesn't support `auto` as the return type. 131 __enable_if_t< 132 !is_reference<__deref_t<_Iter> >::value, 133 __deref_t<_Iter> > 134 __iter_move(_Iter&& __i) { 135 __validate_iter_reference<_Iter>(); 136 137 return *std::forward<_Iter>(__i); 138 } 139 140 // iter_swap 141 template <class _Iter1, class _Iter2> 142 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 143 static void iter_swap(_Iter1&& __a, _Iter2&& __b) { 144 std::iter_swap(std::forward<_Iter1>(__a), std::forward<_Iter2>(__b)); 145 } 146 147 // next 148 template <class _Iterator> 149 _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX14 150 _Iterator next(_Iterator, _Iterator __last) { 151 return __last; 152 } 153 154 template <class _Iter> 155 _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX14 156 __remove_cvref_t<_Iter> next(_Iter&& __it, 157 typename iterator_traits<__remove_cvref_t<_Iter> >::difference_type __n = 1) { 158 return std::next(std::forward<_Iter>(__it), __n); 159 } 160 161 // prev 162 template <class _Iter> 163 _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX14 164 __remove_cvref_t<_Iter> prev(_Iter&& __iter, 165 typename iterator_traits<__remove_cvref_t<_Iter> >::difference_type __n = 1) { 166 return std::prev(std::forward<_Iter>(__iter), __n); 167 } 168 169 template <class _Iter> 170 _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX14 171 void __advance_to(_Iter& __first, _Iter __last) { 172 __first = __last; 173 } 174 }; 175 176 _LIBCPP_END_NAMESPACE_STD 177 178 _LIBCPP_POP_MACROS 179 180 #endif // _LIBCPP___ALGORITHM_ITERATOR_OPERATIONS_H 181