|
| 1 | +//===----------------------------------------------------------------------===// |
| 2 | +// |
| 3 | +// Part of libcu++, the C++ Standard Library for your entire system, |
| 4 | +// 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-exception |
| 7 | +// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. |
| 8 | +// |
| 9 | +//===----------------------------------------------------------------------===// |
| 10 | + |
| 11 | +#ifndef _CUDA___ITERATOR_CONTIGUOUS_ITERATOR_ADAPTOR_H |
| 12 | +#define _CUDA___ITERATOR_CONTIGUOUS_ITERATOR_ADAPTOR_H |
| 13 | + |
| 14 | +#include <cuda/std/detail/__config> |
| 15 | + |
| 16 | +#if defined(_CCCL_IMPLICIT_SYSTEM_HEADER_GCC) |
| 17 | +# pragma GCC system_header |
| 18 | +#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_CLANG) |
| 19 | +# pragma clang system_header |
| 20 | +#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_MSVC) |
| 21 | +# pragma system_header |
| 22 | +#endif // no system header |
| 23 | + |
| 24 | +#include <cuda/__fwd/iterator.h> |
| 25 | +#include <cuda/std/__concepts/concept_macros.h> |
| 26 | +#include <cuda/std/__iterator/concepts.h> |
| 27 | +#include <cuda/std/__iterator/iterator_traits.h> |
| 28 | +#include <cuda/std/__iterator/readable_traits.h> |
| 29 | +#include <cuda/std/__memory/pointer_traits.h> |
| 30 | +#include <cuda/std/__type_traits/is_convertible.h> |
| 31 | +#include <cuda/std/__type_traits/is_pointer.h> |
| 32 | +#include <cuda/std/__type_traits/remove_cvref.h> |
| 33 | +#include <cuda/std/__utility/declval.h> |
| 34 | + |
| 35 | +#include <cuda/std/__cccl/prologue.h> |
| 36 | + |
| 37 | +_CCCL_BEGIN_NAMESPACE_CUDA |
| 38 | + |
| 39 | +//! @brief True when `_Iter` is an iterator adaptor whose `base()` returns the iterator it adapts, so not e.g. the |
| 40 | +//! counter of a counting iterator. |
| 41 | +template <class _Iter> |
| 42 | +_CCCL_CONCEPT __iter_has_member_base = _CCCL_REQUIRES_EXPR((_Iter), const _Iter& __iter)( |
| 43 | + requires(::cuda::std::__can_to_address<::cuda::std::remove_cvref_t<decltype(__iter.base())>> |
| 44 | + || ::cuda::std::input_or_output_iterator<::cuda::std::remove_cvref_t<decltype(__iter.base())>>)); |
| 45 | + |
| 46 | +//! @brief True when `_Iter` is an iterator adaptor that can rebuild itself over the storage at a `_Tp*`. |
| 47 | +template <class _Iter, class _Tp> |
| 48 | +_CCCL_CONCEPT __iter_has_member_rebind = |
| 49 | + _CCCL_REQUIRES_EXPR((_Iter, _Tp), const _Iter& __iter, _Tp* __ptr)((__iter.__rebind(__ptr))); |
| 50 | + |
| 51 | +//! @brief Peel iterator adaptors until a contiguous iterator or an iterator that adapts no other iterator remains. |
| 52 | +//! @param[in] __iter The iterator to unwrap. |
| 53 | +//! @return The address of the storage of a contiguous iterator. Otherwise the unwrapped base iterator of an iterator |
| 54 | +//! adaptor, or `__iter` when it is not an iterator adaptor. |
| 55 | +template <class _Iter> |
| 56 | +[[nodiscard]] _CCCL_API constexpr auto __unwrap_iterator_adaptor(const _Iter& __iter) |
| 57 | +{ |
| 58 | + if constexpr (::cuda::std::__can_to_address<_Iter>) |
| 59 | + { // Support standard contiguous iterators |
| 60 | + return ::cuda::std::to_address(__iter); |
| 61 | + } |
| 62 | + else if constexpr (__iter_has_member_base<_Iter>) |
| 63 | + { |
| 64 | + return ::cuda::__unwrap_iterator_adaptor(__iter.base()); |
| 65 | + } |
| 66 | + else |
| 67 | + { |
| 68 | + return __iter; |
| 69 | + } |
| 70 | +} |
| 71 | + |
| 72 | +//! @brief The iterator that remains after peeling iterator adaptors from `_Iter`. |
| 73 | +template <class _Iter> |
| 74 | +using __unwrapped_iterator_t = decltype(::cuda::__unwrap_iterator_adaptor(::cuda::std::declval<_Iter>())); |
| 75 | + |
| 76 | +//! @brief The value type of the iterator that remains after peeling iterator adaptors from `_Iter`. |
| 77 | +template <class _Iter> |
| 78 | +using __unwrapped_iter_value_t = ::cuda::std::iter_value_t<__unwrapped_iterator_t<_Iter>>; |
| 79 | + |
| 80 | +//! @brief True when `_Iter` can be rebuilt over the storage at a `_Tp*`, because it is a contiguous iterator or an |
| 81 | +//! iterator adaptor that can rebuild itself over it. |
| 82 | +template <class _Iter, class _Tp> |
| 83 | +_CCCL_CONCEPT __iter_can_rebind = |
| 84 | + (::cuda::std::__has_contiguous_traversal<_Iter> && ::cuda::std::is_convertible_v<_Tp*, __unwrapped_iterator_t<_Iter>>) |
| 85 | + || __iter_has_member_rebind<_Iter, _Tp>; |
| 86 | + |
| 87 | +//! @brief Rebuild `__iter` over the storage at `__ptr`. |
| 88 | +//! @param[in] __iter The iterator to rebuild. |
| 89 | +//! @param[in] __ptr The address of the storage that replaces the storage `__iter` reads from. |
| 90 | +//! @return A pointer to `__ptr` with the qualifiers of the address of a contiguous iterator. Otherwise a copy of the |
| 91 | +//! iterator adaptor over its rebuilt base iterator. |
| 92 | +_CCCL_TEMPLATE(class _Iter, class _Tp) |
| 93 | +_CCCL_REQUIRES(__iter_can_rebind<_Iter, _Tp>) |
| 94 | +[[nodiscard]] _CCCL_API constexpr auto __rebind_iterator_adaptor([[maybe_unused]] const _Iter& __iter, _Tp* __ptr) |
| 95 | +{ |
| 96 | + if constexpr (__iter_has_member_rebind<_Iter, _Tp>) |
| 97 | + { |
| 98 | + return __iter.__rebind(__ptr); |
| 99 | + } |
| 100 | + else |
| 101 | + { |
| 102 | + return static_cast<__unwrapped_iterator_t<_Iter>>(__ptr); |
| 103 | + } |
| 104 | +} |
| 105 | + |
| 106 | +//! @brief True when `_Iter` is an iterator adaptor over contiguous storage, which unwraps to a pointer and can be |
| 107 | +//! rebuilt over a copy of the storage behind it. |
| 108 | +template <class _Iter> |
| 109 | +_CCCL_CONCEPT __iter_can_unwrap = _CCCL_REQUIRES_EXPR((_Iter)) // |
| 110 | + (requires(::cuda::std::is_pointer_v<__unwrapped_iterator_t<_Iter>>), |
| 111 | + requires(__iter_has_member_rebind<_Iter, __unwrapped_iter_value_t<_Iter>>)); |
| 112 | + |
| 113 | +template <class _Iter> |
| 114 | +inline constexpr bool __is_contiguous_iterator_or_adaptor_impl = |
| 115 | + ::cuda::std::is_pointer_v<_Iter> || ::cuda::std::__has_contiguous_traversal<_Iter>; |
| 116 | + |
| 117 | +template <class _Fn, class _Iter> |
| 118 | +inline constexpr bool __is_contiguous_iterator_or_adaptor_impl<::cuda::transform_iterator<_Fn, _Iter>> = |
| 119 | + __is_contiguous_iterator_or_adaptor_impl<::cuda::std::remove_cvref_t<_Iter>>; |
| 120 | + |
| 121 | +//! @brief True when `_Iter` is contiguous storage, or an adaptor whose stored iterator is. |
| 122 | +//! @tparam _Iter The iterator type to query. cv-qualifiers and references are ignored. |
| 123 | +template <class _Iter> |
| 124 | +inline constexpr bool __is_contiguous_iterator_or_adaptor_v = |
| 125 | + __is_contiguous_iterator_or_adaptor_impl<::cuda::std::remove_cvref_t<_Iter>>; |
| 126 | + |
| 127 | +_CCCL_END_NAMESPACE_CUDA |
| 128 | + |
| 129 | +#include <cuda/std/__cccl/epilogue.h> |
| 130 | + |
| 131 | +#endif // _CUDA___ITERATOR_CONTIGUOUS_ITERATOR_ADAPTOR_H |
0 commit comments