Skip to content

Commit 0ecc164

Browse files
authored
[libc++][ranges] Implement LWG4053 and LWG4054 (#88612)
Implement - LWG4053 Unary call to `std::views::repeat` does not decay the argument - LWG4054 Repeating a `repeat_view` should repeat the view Signed-off-by: yronglin <[email protected]>
1 parent 1c979ab commit 0ecc164

File tree

4 files changed

+26
-7
lines changed

4 files changed

+26
-7
lines changed

libcxx/docs/Status/Cxx2cIssues.csv

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,8 @@
5959
"`4038 <https://wg21.link/LWG4038>`__","``std::text_encoding::aliases_view`` should have constexpr iterators","Tokyo March 2024","","",""
6060
"`4043 <https://wg21.link/LWG4043>`__","""ASCII"" is not a registered character encoding","Tokyo March 2024","|Nothing To Do|","",""
6161
"`4045 <https://wg21.link/LWG4045>`__","``tuple`` can create dangling references from ``tuple-like``","Tokyo March 2024","","",""
62-
"`4053 <https://wg21.link/LWG4053>`__","Unary call to ``std::views::repeat`` does not decay the argument","Tokyo March 2024","","","|ranges|"
63-
"`4054 <https://wg21.link/LWG4054>`__","Repeating a ``repeat_view`` should repeat the view","Tokyo March 2024","","","|ranges|"
62+
"`4053 <https://wg21.link/LWG4053>`__","Unary call to ``std::views::repeat`` does not decay the argument","Tokyo March 2024","|Complete|","19.0","|ranges|"
63+
"`4054 <https://wg21.link/LWG4054>`__","Repeating a ``repeat_view`` should repeat the view","Tokyo March 2024","|Complete|","19.0","|ranges|"
6464
"","","","","",""
6565
"`3343 <https://wg21.link/LWG3343>`__","Ordering of calls to ``unlock()`` and ``notify_all()`` in Effects element of ``notify_all_at_thread_exit()`` should be reversed","Not Yet Adopted","|Complete|","16.0",""
6666
"XXXX","","The sys_info range should be affected by save","Not Yet Adopted","|Complete|","19.0"

libcxx/include/__ranges/repeat_view.h

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include <__ranges/iota_view.h>
2323
#include <__ranges/movable_box.h>
2424
#include <__ranges/view_interface.h>
25+
#include <__type_traits/decay.h>
2526
#include <__type_traits/is_object.h>
2627
#include <__type_traits/make_unsigned.h>
2728
#include <__type_traits/remove_cv.h>
@@ -127,8 +128,8 @@ class _LIBCPP_ABI_LLVM18_NO_UNIQUE_ADDRESS repeat_view : public view_interface<r
127128
_LIBCPP_NO_UNIQUE_ADDRESS _Bound __bound_ = _Bound();
128129
};
129130

130-
template <class _Tp, class _Bound>
131-
repeat_view(_Tp, _Bound) -> repeat_view<_Tp, _Bound>;
131+
template <class _Tp, class _Bound = unreachable_sentinel_t>
132+
repeat_view(_Tp, _Bound = _Bound()) -> repeat_view<_Tp, _Bound>;
132133

133134
// [range.repeat.iterator]
134135
template <move_constructible _Tp, semiregular _Bound>
@@ -230,9 +231,9 @@ namespace __repeat {
230231
struct __fn {
231232
template <class _Tp>
232233
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI static constexpr auto operator()(_Tp&& __value)
233-
noexcept(noexcept(ranges::repeat_view(std::forward<_Tp>(__value))))
234-
-> decltype( ranges::repeat_view(std::forward<_Tp>(__value)))
235-
{ return ranges::repeat_view(std::forward<_Tp>(__value)); }
234+
noexcept(noexcept(ranges::repeat_view<decay_t<_Tp>>(std::forward<_Tp>(__value))))
235+
-> decltype( ranges::repeat_view<decay_t<_Tp>>(std::forward<_Tp>(__value)))
236+
{ return ranges::repeat_view<decay_t<_Tp>>(std::forward<_Tp>(__value)); }
236237

237238
template <class _Tp, class _Bound>
238239
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI static constexpr auto operator()(_Tp&& __value, _Bound&& __bound_sentinel)

libcxx/test/std/ranges/range.factories/range.repeat.view/ctad.compile.pass.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,10 @@ static_assert(std::same_as<decltype(std::ranges::repeat_view(std::declval<Empty&
2424
static_assert(std::same_as<decltype(std::ranges::repeat_view(10, 1)), std::ranges::repeat_view<int, int>>);
2525
static_assert(std::same_as<decltype(std::ranges::repeat_view(10, 1U)), std::ranges::repeat_view<int, unsigned>>);
2626
static_assert(std::same_as<decltype(std::ranges::repeat_view(10, 1UL)), std::ranges::repeat_view<int, unsigned long>>);
27+
28+
using RPV = std::ranges::repeat_view<const char*>;
29+
static_assert(std::same_as<decltype(std::ranges::repeat_view("foo", std::unreachable_sentinel)), RPV>); // OK
30+
static_assert(std::same_as<decltype(std::ranges::repeat_view(+"foo", std::unreachable_sentinel)), RPV>); // OK
31+
static_assert(std::same_as<decltype(std::ranges::repeat_view("foo")), RPV>); // OK since LWG4053
32+
static_assert(std::same_as<decltype(std::ranges::repeat_view(+"foo")), RPV>); // OK
2733
// clang-format on

libcxx/test/std/ranges/range.factories/range.repeat.view/views_repeat.pass.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,18 @@ static_assert(!std::is_invocable_v<decltype(std::views::repeat), NonCopyable>);
6060
// Tp is move_constructible
6161
static_assert(std::is_invocable_v<decltype(std::views::repeat), MoveOnly>);
6262

63+
// Test LWG4054 "Repeating a repeat_view should repeat the view"
64+
static_assert(std::is_same_v<decltype(std::views::repeat(std::views::repeat(42))),
65+
std::ranges::repeat_view<std::ranges::repeat_view<int>>>);
66+
67+
// These cases are from LWG4053, but they are actually covered by the resolution of LWG4054,
68+
// and the resolution of LWG4053 only affects CTAD.
69+
using RPV = std::ranges::repeat_view<const char*>;
70+
static_assert(std::same_as<decltype(std::views::repeat("foo", std::unreachable_sentinel)), RPV>); // OK
71+
static_assert(std::same_as<decltype(std::views::repeat(+"foo", std::unreachable_sentinel)), RPV>); // OK
72+
static_assert(std::same_as<decltype(std::views::repeat("foo")), RPV>); // OK since LWG4054
73+
static_assert(std::same_as<decltype(std::views::repeat(+"foo")), RPV>); // OK
74+
6375
constexpr bool test() {
6476
assert(*std::views::repeat(33).begin() == 33);
6577
assert(*std::views::repeat(33, 10).begin() == 33);

0 commit comments

Comments
 (0)