1988682a3SNikolas Klauser //===----------------------------------------------------------------------===// 2988682a3SNikolas Klauser // 3988682a3SNikolas Klauser // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4988682a3SNikolas Klauser // See https://llvm.org/LICENSE.txt for license information. 5988682a3SNikolas Klauser // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6988682a3SNikolas Klauser // 7988682a3SNikolas Klauser //===----------------------------------------------------------------------===// 8988682a3SNikolas Klauser 9295b951eSKonstantin Varlamov #ifndef _LIBCPP___ALGORITHM_ITERATOR_OPERATIONS_H 10295b951eSKonstantin Varlamov #define _LIBCPP___ALGORITHM_ITERATOR_OPERATIONS_H 11988682a3SNikolas Klauser 12295b951eSKonstantin Varlamov #include <__algorithm/iter_swap.h> 13732cb123SKonstantin Varlamov #include <__algorithm/ranges_iterator_concept.h> 14988682a3SNikolas Klauser #include <__config> 15988682a3SNikolas Klauser #include <__iterator/advance.h> 16988682a3SNikolas Klauser #include <__iterator/distance.h> 17732cb123SKonstantin Varlamov #include <__iterator/incrementable_traits.h> 18295b951eSKonstantin Varlamov #include <__iterator/iter_move.h> 19295b951eSKonstantin Varlamov #include <__iterator/iter_swap.h> 20988682a3SNikolas Klauser #include <__iterator/iterator_traits.h> 2196b674f2SHui Xie #include <__iterator/next.h> 22*33e5f159SKonstantin Varlamov #include <__iterator/prev.h> 2362f1e663SHui Xie #include <__iterator/readable_traits.h> 24c9905b8cSKonstantin Varlamov #include <__utility/declval.h> 25295b951eSKonstantin Varlamov #include <__utility/forward.h> 26295b951eSKonstantin Varlamov #include <__utility/move.h> 27295b951eSKonstantin Varlamov #include <type_traits> 28988682a3SNikolas Klauser 29988682a3SNikolas Klauser #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 30988682a3SNikolas Klauser # pragma GCC system_header 31988682a3SNikolas Klauser #endif 32988682a3SNikolas Klauser 33988682a3SNikolas Klauser _LIBCPP_BEGIN_NAMESPACE_STD 34988682a3SNikolas Klauser 35295b951eSKonstantin Varlamov template <class _AlgPolicy> struct _IterOps; 36295b951eSKonstantin Varlamov 37988682a3SNikolas Klauser #if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) 38295b951eSKonstantin Varlamov struct _RangeAlgPolicy {}; 39295b951eSKonstantin Varlamov 40295b951eSKonstantin Varlamov template <> 41295b951eSKonstantin Varlamov struct _IterOps<_RangeAlgPolicy> { 4262f1e663SHui Xie 4362f1e663SHui Xie template <class _Iter> 4462f1e663SHui Xie using __value_type = iter_value_t<_Iter>; 4562f1e663SHui Xie 46732cb123SKonstantin Varlamov template <class _Iter> 47732cb123SKonstantin Varlamov using __iterator_category = ranges::__iterator_concept<_Iter>; 48732cb123SKonstantin Varlamov 49732cb123SKonstantin Varlamov template <class _Iter> 50732cb123SKonstantin Varlamov using __difference_type = iter_difference_t<_Iter>; 51732cb123SKonstantin Varlamov 52988682a3SNikolas Klauser static constexpr auto advance = ranges::advance; 53988682a3SNikolas Klauser static constexpr auto distance = ranges::distance; 54295b951eSKonstantin Varlamov static constexpr auto __iter_move = ranges::iter_move; 55295b951eSKonstantin Varlamov static constexpr auto iter_swap = ranges::iter_swap; 5696b674f2SHui Xie static constexpr auto next = ranges::next; 57*33e5f159SKonstantin Varlamov static constexpr auto prev = ranges::prev; 58101d1e9bSNikolas Klauser static constexpr auto __advance_to = ranges::advance; 59988682a3SNikolas Klauser }; 60a7c3379cSKonstantin Varlamov 61988682a3SNikolas Klauser #endif 62988682a3SNikolas Klauser 63295b951eSKonstantin Varlamov struct _ClassicAlgPolicy {}; 64988682a3SNikolas Klauser 65295b951eSKonstantin Varlamov template <> 66295b951eSKonstantin Varlamov struct _IterOps<_ClassicAlgPolicy> { 67295b951eSKonstantin Varlamov 6862f1e663SHui Xie template <class _Iter> 6962f1e663SHui Xie using __value_type = typename iterator_traits<_Iter>::value_type; 7062f1e663SHui Xie 71732cb123SKonstantin Varlamov template <class _Iter> 72732cb123SKonstantin Varlamov using __iterator_category = typename iterator_traits<_Iter>::iterator_category; 73732cb123SKonstantin Varlamov 74732cb123SKonstantin Varlamov template <class _Iter> 75732cb123SKonstantin Varlamov using __difference_type = typename iterator_traits<_Iter>::difference_type; 76732cb123SKonstantin Varlamov 77295b951eSKonstantin Varlamov // advance 78295b951eSKonstantin Varlamov template <class _Iter, class _Distance> 79295b951eSKonstantin Varlamov _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 80295b951eSKonstantin Varlamov static void advance(_Iter& __iter, _Distance __count) { 81295b951eSKonstantin Varlamov std::advance(__iter, __count); 82988682a3SNikolas Klauser } 83988682a3SNikolas Klauser 84295b951eSKonstantin Varlamov // distance 85295b951eSKonstantin Varlamov template <class _Iter> 86295b951eSKonstantin Varlamov _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 87295b951eSKonstantin Varlamov static typename iterator_traits<_Iter>::difference_type distance(_Iter __first, _Iter __last) { 88988682a3SNikolas Klauser return std::distance(__first, __last); 89988682a3SNikolas Klauser } 90988682a3SNikolas Klauser 91c9905b8cSKonstantin Varlamov template <class _Iter> 92c9905b8cSKonstantin Varlamov using __deref_t = decltype(*std::declval<_Iter&>()); 93c9905b8cSKonstantin Varlamov 94c9905b8cSKonstantin Varlamov template <class _Iter> 95c9905b8cSKonstantin Varlamov using __move_t = decltype(std::move(*std::declval<_Iter&>())); 96c9905b8cSKonstantin Varlamov 97295b951eSKonstantin Varlamov template <class _Iter> 98295b951eSKonstantin Varlamov _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 99c9905b8cSKonstantin Varlamov static void __validate_iter_reference() { 100c9905b8cSKonstantin Varlamov static_assert(is_same<__deref_t<_Iter>, typename iterator_traits<__uncvref_t<_Iter> >::reference>::value, 101c9905b8cSKonstantin Varlamov "It looks like your iterator's `iterator_traits<It>::reference` does not match the return type of " 102c9905b8cSKonstantin Varlamov "dereferencing the iterator, i.e., calling `*it`. This is undefined behavior according to [input.iterators] " 103c9905b8cSKonstantin Varlamov "and can lead to dangling reference issues at runtime, so we are flagging this."); 104c9905b8cSKonstantin Varlamov } 105c9905b8cSKonstantin Varlamov 106c9905b8cSKonstantin Varlamov // iter_move 107c9905b8cSKonstantin Varlamov template <class _Iter> 108c9905b8cSKonstantin Varlamov _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 static 109c9905b8cSKonstantin Varlamov // If the result of dereferencing `_Iter` is a reference type, deduce the result of calling `std::move` on it. Note 110c9905b8cSKonstantin Varlamov // that the C++03 mode doesn't support `decltype(auto)` as the return type. 111c9905b8cSKonstantin Varlamov __enable_if_t< 112c9905b8cSKonstantin Varlamov is_reference<__deref_t<_Iter> >::value, 113c9905b8cSKonstantin Varlamov __move_t<_Iter> > 1147abbd622SHui Xie __iter_move(_Iter&& __i) { 115c9905b8cSKonstantin Varlamov __validate_iter_reference<_Iter>(); 116c9905b8cSKonstantin Varlamov 117295b951eSKonstantin Varlamov return std::move(*std::forward<_Iter>(__i)); 118295b951eSKonstantin Varlamov } 119295b951eSKonstantin Varlamov 1207abbd622SHui Xie template <class _Iter> 121c9905b8cSKonstantin Varlamov _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 static 122c9905b8cSKonstantin Varlamov // If the result of dereferencing `_Iter` is a value type, deduce the return value of this function to also be a 123c9905b8cSKonstantin Varlamov // value -- otherwise, after `operator*` returns a temporary, this function would return a dangling reference to that 124c9905b8cSKonstantin Varlamov // temporary. Note that the C++03 mode doesn't support `auto` as the return type. 125c9905b8cSKonstantin Varlamov __enable_if_t< 126c9905b8cSKonstantin Varlamov !is_reference<__deref_t<_Iter> >::value, 127c9905b8cSKonstantin Varlamov __deref_t<_Iter> > 1287abbd622SHui Xie __iter_move(_Iter&& __i) { 129c9905b8cSKonstantin Varlamov __validate_iter_reference<_Iter>(); 130c9905b8cSKonstantin Varlamov 1317abbd622SHui Xie return *std::forward<_Iter>(__i); 1327abbd622SHui Xie } 1337abbd622SHui Xie 134295b951eSKonstantin Varlamov // iter_swap 135295b951eSKonstantin Varlamov template <class _Iter1, class _Iter2> 136295b951eSKonstantin Varlamov _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 137295b951eSKonstantin Varlamov static void iter_swap(_Iter1&& __a, _Iter2&& __b) { 138295b951eSKonstantin Varlamov std::iter_swap(std::forward<_Iter1>(__a), std::forward<_Iter2>(__b)); 139295b951eSKonstantin Varlamov } 140295b951eSKonstantin Varlamov 141295b951eSKonstantin Varlamov // next 14296b674f2SHui Xie template <class _Iterator> 14396b674f2SHui Xie _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_AFTER_CXX11 14496b674f2SHui Xie _Iterator next(_Iterator, _Iterator __last) { 14596b674f2SHui Xie return __last; 14696b674f2SHui Xie } 147101d1e9bSNikolas Klauser 148101d1e9bSNikolas Klauser template <class _Iter> 149a7c3379cSKonstantin Varlamov _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_AFTER_CXX11 1508ed702b8SKonstantin Varlamov __uncvref_t<_Iter> next(_Iter&& __it, 1518ed702b8SKonstantin Varlamov typename iterator_traits<__uncvref_t<_Iter> >::difference_type __n = 1) { 1528ed702b8SKonstantin Varlamov return std::next(std::forward<_Iter>(__it), __n); 1538ed702b8SKonstantin Varlamov } 1548ed702b8SKonstantin Varlamov 155*33e5f159SKonstantin Varlamov // prev 156*33e5f159SKonstantin Varlamov template <class _Iter> 157*33e5f159SKonstantin Varlamov _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_AFTER_CXX11 158*33e5f159SKonstantin Varlamov __uncvref_t<_Iter> prev(_Iter&& __iter, 159*33e5f159SKonstantin Varlamov typename iterator_traits<__uncvref_t<_Iter> >::difference_type __n = 1) { 160*33e5f159SKonstantin Varlamov return std::prev(std::forward<_Iter>(__iter), __n); 161*33e5f159SKonstantin Varlamov } 162*33e5f159SKonstantin Varlamov 1638ed702b8SKonstantin Varlamov template <class _Iter> 1648ed702b8SKonstantin Varlamov _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_AFTER_CXX11 165a7c3379cSKonstantin Varlamov void __advance_to(_Iter& __first, _Iter __last) { 166101d1e9bSNikolas Klauser __first = __last; 167101d1e9bSNikolas Klauser } 168988682a3SNikolas Klauser }; 169988682a3SNikolas Klauser 170988682a3SNikolas Klauser _LIBCPP_END_NAMESPACE_STD 171988682a3SNikolas Klauser 172295b951eSKonstantin Varlamov #endif // _LIBCPP___ALGORITHM_ITERATOR_OPERATIONS_H 173