|
| 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_UNWRAP_ITER_H |
| 10 | +#define _LIBCPP___ALGORITHM_UNWRAP_ITER_H |
| 11 | + |
| 12 | +#include <__config> |
| 13 | +#include <__iterator/iterator_traits.h> // __is_cpp17_contiguous_iterator |
| 14 | +#include <__memory/pointer_traits.h> // __to_address |
| 15 | +#include <utility> |
| 16 | + |
| 17 | +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) |
| 18 | +#pragma GCC system_header |
| 19 | +#endif |
| 20 | + |
| 21 | +_LIBCPP_PUSH_MACROS |
| 22 | +#include <__undef_macros> |
| 23 | + |
| 24 | +_LIBCPP_BEGIN_NAMESPACE_STD |
| 25 | + |
| 26 | +// __unwrap_iter, __rewrap_iter |
| 27 | + |
| 28 | +// The job of __unwrap_iter is to lower contiguous iterators (such as |
| 29 | +// vector<T>::iterator) into pointers, to reduce the number of template |
| 30 | +// instantiations and to enable pointer-based optimizations e.g. in std::copy. |
| 31 | +// For iterators that are not contiguous, it must be a no-op. |
| 32 | +// In debug mode, we don't do this. |
| 33 | +// |
| 34 | +// __unwrap_iter is non-constexpr for user-defined iterators whose |
| 35 | +// `to_address` and/or `operator->` is non-constexpr. This is okay; but we |
| 36 | +// try to avoid doing __unwrap_iter in constant-evaluated contexts anyway. |
| 37 | +// |
| 38 | +// Some algorithms (e.g. std::copy, but not std::sort) need to convert an |
| 39 | +// "unwrapped" result back into a contiguous iterator. Since contiguous iterators |
| 40 | +// are random-access, we can do this portably using iterator arithmetic; this |
| 41 | +// is the job of __rewrap_iter. |
| 42 | + |
| 43 | +template <class _Iter, bool = __is_cpp17_contiguous_iterator<_Iter>::value> |
| 44 | +struct __unwrap_iter_impl { |
| 45 | + static _LIBCPP_CONSTEXPR _Iter |
| 46 | + __apply(_Iter __i) _NOEXCEPT { |
| 47 | + return __i; |
| 48 | + } |
| 49 | +}; |
| 50 | + |
| 51 | +#if _LIBCPP_DEBUG_LEVEL < 2 |
| 52 | + |
| 53 | +template <class _Iter> |
| 54 | +struct __unwrap_iter_impl<_Iter, true> { |
| 55 | + static _LIBCPP_CONSTEXPR decltype(_VSTD::__to_address(declval<_Iter>())) |
| 56 | + __apply(_Iter __i) _NOEXCEPT { |
| 57 | + return _VSTD::__to_address(__i); |
| 58 | + } |
| 59 | +}; |
| 60 | + |
| 61 | +#endif // _LIBCPP_DEBUG_LEVEL < 2 |
| 62 | + |
| 63 | +template<class _Iter, class _Impl = __unwrap_iter_impl<_Iter> > |
| 64 | +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR |
| 65 | +decltype(_Impl::__apply(_VSTD::declval<_Iter>())) |
| 66 | +__unwrap_iter(_Iter __i) _NOEXCEPT |
| 67 | +{ |
| 68 | + return _Impl::__apply(__i); |
| 69 | +} |
| 70 | + |
| 71 | +template<class _OrigIter> |
| 72 | +_OrigIter __rewrap_iter(_OrigIter, _OrigIter __result) |
| 73 | +{ |
| 74 | + return __result; |
| 75 | +} |
| 76 | + |
| 77 | +template<class _OrigIter, class _UnwrappedIter> |
| 78 | +_OrigIter __rewrap_iter(_OrigIter __first, _UnwrappedIter __result) |
| 79 | +{ |
| 80 | + // Precondition: __result is reachable from __first |
| 81 | + // Precondition: _OrigIter is a contiguous iterator |
| 82 | + return __first + (__result - _VSTD::__unwrap_iter(__first)); |
| 83 | +} |
| 84 | + |
| 85 | +_LIBCPP_END_NAMESPACE_STD |
| 86 | + |
| 87 | +_LIBCPP_POP_MACROS |
| 88 | + |
| 89 | +#endif // _LIBCPP___ALGORITHM_UNWRAP_ITER_H |
0 commit comments