Skip to content

Commit c69a950

Browse files
committed
Implement ranges::reverse_view
1 parent 1b37e20 commit c69a950

14 files changed

Lines changed: 1404 additions & 1 deletion

File tree

libcudacxx/include/cuda/std/__iterator/reverse_iterator.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,15 @@ inline constexpr bool __noexcept_rev_iter_iter_swap<_Iter, _Iter2, enable_if_t<i
7070
is_nothrow_copy_constructible_v<_Iter> && is_nothrow_copy_constructible_v<_Iter2>
7171
&& noexcept(::cuda::std::ranges::iter_swap(--declval<_Iter&>(), --declval<_Iter2&>()));
7272

73+
// MSVC has issues with `is_nothrow_convertible_v` sometimes, so do the noexcept expression
74+
template <class _Iter, class _Iter2, class = void>
75+
inline constexpr bool __noexcept_rev_iter_convertible = false;
76+
77+
template <class _Iter, class _Iter2>
78+
inline constexpr bool
79+
__noexcept_rev_iter_convertible<_Iter, _Iter2, enable_if_t<is_convertible_v<_Iter const&, _Iter2>>> =
80+
noexcept(_Iter2(::cuda::std::declval<const _Iter&>()));
81+
7382
_LIBCUDACXX_BEGIN_HIDDEN_FRIEND_NAMESPACE
7483

7584
_CCCL_SUPPRESS_DEPRECATED_PUSH
@@ -114,7 +123,7 @@ class _CCCL_TYPE_VISIBILITY_DEFAULT reverse_iterator
114123
_CCCL_TEMPLATE(class _Up)
115124
_CCCL_REQUIRES((!is_same_v<_Up, _Iter>) _CCCL_AND is_convertible_v<_Up const&, _Iter>)
116125
_CCCL_API constexpr reverse_iterator(const reverse_iterator<_Up>& __u) noexcept(
117-
is_nothrow_convertible_v<_Up const&, _Iter>)
126+
__noexcept_rev_iter_convertible<_Up, _Iter>)
118127
: current(__u.base())
119128
{}
120129

Lines changed: 259 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,259 @@
1+
// -*- C++ -*-
2+
//===----------------------------------------------------------------------===//
3+
//
4+
// Part of the LLVM Project, 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) 2025 NVIDIA CORPORATION & AFFILIATES
8+
//
9+
//===----------------------------------------------------------------------===//
10+
#ifndef _CUDA_STD___RANGES_REVERSE_VIEW_H
11+
#define _CUDA_STD___RANGES_REVERSE_VIEW_H
12+
13+
#include <cuda/std/detail/__config>
14+
15+
#if defined(_CCCL_IMPLICIT_SYSTEM_HEADER_GCC)
16+
# pragma GCC system_header
17+
#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_CLANG)
18+
# pragma clang system_header
19+
#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_MSVC)
20+
# pragma system_header
21+
#endif // no system header
22+
23+
#include <cuda/std/__concepts/constructible.h>
24+
#include <cuda/std/__iterator/concepts.h>
25+
#include <cuda/std/__iterator/next.h>
26+
#include <cuda/std/__iterator/reverse_iterator.h>
27+
#include <cuda/std/__ranges/access.h>
28+
#include <cuda/std/__ranges/all.h>
29+
#include <cuda/std/__ranges/concepts.h>
30+
#include <cuda/std/__ranges/enable_borrowed_range.h>
31+
#include <cuda/std/__ranges/non_propagating_cache.h>
32+
#include <cuda/std/__ranges/range_adaptor.h>
33+
#include <cuda/std/__ranges/size.h>
34+
#include <cuda/std/__ranges/subrange.h>
35+
#include <cuda/std/__ranges/view_interface.h>
36+
#include <cuda/std/__type_traits/conditional.h>
37+
#include <cuda/std/__type_traits/enable_if.h>
38+
#include <cuda/std/__type_traits/is_nothrow_copy_constructible.h>
39+
#include <cuda/std/__type_traits/is_nothrow_default_constructible.h>
40+
#include <cuda/std/__type_traits/is_nothrow_move_constructible.h>
41+
#include <cuda/std/__type_traits/remove_cvref.h>
42+
#include <cuda/std/__utility/forward.h>
43+
#include <cuda/std/__utility/move.h>
44+
45+
#include <cuda/std/__cccl/prologue.h>
46+
47+
// MSVC complains about [[msvc::no_unique_address]] prior to C++20 as a vendor extension
48+
_CCCL_DIAG_PUSH
49+
_CCCL_DIAG_SUPPRESS_MSVC(4848)
50+
51+
_CCCL_BEGIN_NAMESPACE_CUDA_STD_RANGES
52+
53+
#if _CCCL_HAS_CONCEPTS()
54+
template <view _View>
55+
requires bidirectional_range<_View>
56+
#else // ^^^ _CCCL_HAS_CONCEPTS() ^^^ / vvv !_CCCL_HAS_CONCEPTS() vvv
57+
template <class _View, class = enable_if_t<view<_View>>, class = enable_if_t<bidirectional_range<_View>>>
58+
#endif // !_CCCL_HAS_CONCEPTS()
59+
class reverse_view : public view_interface<reverse_view<_View>>
60+
{
61+
// We cache begin() whenever ranges::next is not guaranteed O(1) to provide an
62+
// amortized O(1) begin() method.
63+
static constexpr bool _UseCache = !random_access_range<_View> && !common_range<_View>;
64+
using _Cache = _If<_UseCache, __non_propagating_cache<reverse_iterator<iterator_t<_View>>>, __empty_cache>;
65+
_CCCL_NO_UNIQUE_ADDRESS _Cache __cached_begin_ = _Cache();
66+
_CCCL_NO_UNIQUE_ADDRESS _View __base_ = _View();
67+
68+
public:
69+
#if _CCCL_HAS_CONCEPTS()
70+
_CCCL_HIDE_FROM_ABI reverse_view()
71+
requires default_initializable<_View>
72+
= default;
73+
#else // ^^^ _CCCL_HAS_CONCEPTS() ^^^ / vvv !_CCCL_HAS_CONCEPTS() vvv
74+
_CCCL_TEMPLATE(class _View2 = _View)
75+
_CCCL_REQUIRES(default_initializable<_View2>)
76+
_CCCL_API constexpr reverse_view() noexcept(is_nothrow_default_constructible_v<_View2>)
77+
: view_interface<reverse_view<_View>>()
78+
{}
79+
#endif // !_CCCL_HAS_CONCEPTS()
80+
81+
_CCCL_API constexpr explicit reverse_view(_View __view)
82+
: __base_(::cuda::std::move(__view))
83+
{}
84+
85+
_CCCL_TEMPLATE(class _View2 = _View)
86+
_CCCL_REQUIRES(copy_constructible<_View2>)
87+
_CCCL_API constexpr _View base() const& noexcept(is_nothrow_copy_constructible_v<_View>)
88+
{
89+
return __base_;
90+
}
91+
92+
_CCCL_API constexpr _View base() && noexcept(is_nothrow_move_constructible_v<_View>)
93+
{
94+
return ::cuda::std::move(__base_);
95+
}
96+
97+
_CCCL_TEMPLATE(class _View2 = _View)
98+
_CCCL_REQUIRES((!common_range<_View2>) )
99+
_CCCL_API constexpr reverse_iterator<iterator_t<_View2>> begin()
100+
{
101+
if constexpr (_UseCache)
102+
{
103+
if (__cached_begin_.__has_value())
104+
{
105+
return *__cached_begin_;
106+
}
107+
}
108+
109+
auto __tmp = ::cuda::std::make_reverse_iterator(
110+
::cuda::std::ranges::next(::cuda::std::ranges::begin(__base_), ::cuda::std::ranges::end(__base_)));
111+
if constexpr (_UseCache)
112+
{
113+
__cached_begin_.__emplace(__tmp);
114+
}
115+
return __tmp;
116+
}
117+
118+
_CCCL_TEMPLATE(class _View2 = _View)
119+
_CCCL_REQUIRES(common_range<_View2>)
120+
_CCCL_API constexpr reverse_iterator<iterator_t<_View2>> begin()
121+
{
122+
return ::cuda::std::make_reverse_iterator(::cuda::std::ranges::end(__base_));
123+
}
124+
125+
_CCCL_TEMPLATE(class _View2 = _View)
126+
_CCCL_REQUIRES(common_range<const _View2>)
127+
_CCCL_API constexpr auto begin() const
128+
{
129+
return ::cuda::std::make_reverse_iterator(::cuda::std::ranges::end(__base_));
130+
}
131+
132+
_CCCL_API constexpr reverse_iterator<iterator_t<_View>> end()
133+
{
134+
return ::cuda::std::make_reverse_iterator(::cuda::std::ranges::begin(__base_));
135+
}
136+
137+
_CCCL_TEMPLATE(class _View2 = _View)
138+
_CCCL_REQUIRES(common_range<const _View2>)
139+
_CCCL_API constexpr auto end() const
140+
{
141+
return ::cuda::std::make_reverse_iterator(::cuda::std::ranges::begin(__base_));
142+
}
143+
144+
_CCCL_TEMPLATE(class _View2 = _View)
145+
_CCCL_REQUIRES(sized_range<_View2>)
146+
_CCCL_API constexpr auto size()
147+
{
148+
return ::cuda::std::ranges::size(__base_);
149+
}
150+
151+
_CCCL_TEMPLATE(class _View2 = _View)
152+
_CCCL_REQUIRES(sized_range<const _View2>)
153+
_CCCL_API constexpr auto size() const
154+
{
155+
return ::cuda::std::ranges::size(__base_);
156+
}
157+
};
158+
159+
template <class _Range>
160+
_CCCL_HOST_DEVICE reverse_view(_Range&&) -> reverse_view<::cuda::std::ranges::views::all_t<_Range>>;
161+
162+
template <class _Tp>
163+
inline constexpr bool enable_borrowed_range<reverse_view<_Tp>> = enable_borrowed_range<_Tp>;
164+
165+
_CCCL_END_NAMESPACE_CUDA_STD_RANGES
166+
167+
_CCCL_BEGIN_NAMESPACE_CUDA_STD_VIEWS
168+
_CCCL_BEGIN_NAMESPACE_CPO(__reverse)
169+
170+
template <class _Tp>
171+
inline constexpr bool __is_reverse_view = false;
172+
173+
template <class _Tp>
174+
inline constexpr bool __is_reverse_view<reverse_view<_Tp>> = true;
175+
176+
template <class _Tp>
177+
inline constexpr bool __is_sized_reverse_subrange = false;
178+
179+
template <class _Iter>
180+
inline constexpr bool __is_sized_reverse_subrange<
181+
::cuda::std::ranges::
182+
subrange<reverse_iterator<_Iter>, reverse_iterator<_Iter>, ::cuda::std::ranges::subrange_kind::sized>> = true;
183+
184+
template <class _Tp>
185+
inline constexpr bool __is_unsized_reverse_subrange = false;
186+
187+
template <class _Iter, subrange_kind _Kind>
188+
inline constexpr bool
189+
__is_unsized_reverse_subrange<::cuda::std::ranges::subrange<reverse_iterator<_Iter>, reverse_iterator<_Iter>, _Kind>> =
190+
_Kind == ::cuda::std::ranges::subrange_kind::unsized;
191+
192+
template <class _Tp>
193+
struct __unwrapped_reverse_subrange
194+
{
195+
using type = void; // avoid SFINAE-ing out the overload below -- let the concept requirements do it for better
196+
// diagnostics
197+
};
198+
199+
template <class _Iter, ::cuda::std::ranges::subrange_kind _Kind>
200+
struct __unwrapped_reverse_subrange<
201+
::cuda::std::ranges::subrange<reverse_iterator<_Iter>, reverse_iterator<_Iter>, _Kind>>
202+
{
203+
using type = ::cuda::std::ranges::subrange<_Iter, _Iter, _Kind>;
204+
};
205+
206+
template <class _Tp>
207+
using __unwrapped_reverse_subrange_t = typename __unwrapped_reverse_subrange<_Tp>::type;
208+
209+
struct __fn : __range_adaptor_closure<__fn>
210+
{
211+
_CCCL_TEMPLATE(class _Range)
212+
_CCCL_REQUIRES(__is_reverse_view<remove_cvref_t<_Range>>)
213+
[[nodiscard]] _CCCL_API constexpr auto operator()(_Range&& __range) const
214+
noexcept(noexcept(::cuda::std::forward<_Range>(__range).base()))
215+
-> decltype(::cuda::std::forward<_Range>(__range).base())
216+
{
217+
return ::cuda::std::forward<_Range>(__range).base();
218+
}
219+
220+
_CCCL_TEMPLATE(class _Range, class _UnwrappedSubrange = __unwrapped_reverse_subrange_t<remove_cvref_t<_Range>>)
221+
_CCCL_REQUIRES(__is_sized_reverse_subrange<remove_cvref_t<_Range>>)
222+
[[nodiscard]] _CCCL_API constexpr auto operator()(_Range&& __range) const
223+
noexcept(noexcept(_UnwrappedSubrange(__range.end().base(), __range.begin().base(), __range.size())))
224+
-> _UnwrappedSubrange
225+
{
226+
return _UnwrappedSubrange(__range.end().base(), __range.begin().base(), __range.size());
227+
}
228+
229+
_CCCL_TEMPLATE(class _Range, class _UnwrappedSubrange = __unwrapped_reverse_subrange_t<remove_cvref_t<_Range>>)
230+
_CCCL_REQUIRES(__is_unsized_reverse_subrange<remove_cvref_t<_Range>>)
231+
[[nodiscard]] _CCCL_API constexpr auto operator()(_Range&& __range) const
232+
noexcept(noexcept(_UnwrappedSubrange(__range.end().base(), __range.begin().base()))) -> _UnwrappedSubrange
233+
{
234+
return _UnwrappedSubrange(__range.end().base(), __range.begin().base());
235+
}
236+
237+
_CCCL_TEMPLATE(class _Range)
238+
_CCCL_REQUIRES(
239+
(!__is_reverse_view<remove_cvref_t<_Range>>) _CCCL_AND(!__is_sized_reverse_subrange<remove_cvref_t<_Range>>)
240+
_CCCL_AND(!__is_unsized_reverse_subrange<remove_cvref_t<_Range>>))
241+
[[nodiscard]] _CCCL_API constexpr auto operator()(_Range&& __range) const
242+
noexcept(noexcept(reverse_view{::cuda::std::forward<_Range>(__range)})) -> reverse_view<all_t<_Range>>
243+
{
244+
return reverse_view{::cuda::std::forward<_Range>(__range)};
245+
}
246+
};
247+
_CCCL_END_NAMESPACE_CPO
248+
249+
inline namespace __cpo
250+
{
251+
_CCCL_GLOBAL_CONSTANT auto reverse = __reverse::__fn{};
252+
} // namespace __cpo
253+
_CCCL_END_NAMESPACE_CUDA_STD_VIEWS
254+
255+
_CCCL_DIAG_POP
256+
257+
#include <cuda/std/__cccl/epilogue.h>
258+
259+
#endif // _CUDA_STD___RANGES_REVERSE_VIEW_H

libcudacxx/include/cuda/std/ranges

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ _CCCL_DIAG_SUPPRESS_MSVC(4848)
4242
#include <cuda/std/__ranges/ref_view.h>
4343
#include <cuda/std/__ranges/rend.h>
4444
#include <cuda/std/__ranges/repeat_view.h>
45+
#include <cuda/std/__ranges/reverse_view.h>
4546
#include <cuda/std/__ranges/single_view.h>
4647
#include <cuda/std/__ranges/size.h>
4748
#include <cuda/std/__ranges/subrange.h>

0 commit comments

Comments
 (0)