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