Skip to content

Commit 6d40257

Browse files
authored
[libc++][ranges] LWG4096: views::iota(views::iota(0)) should be rejected (llvm#152855)
Fixes llvm#105352
1 parent f2d76b5 commit 6d40257

File tree

3 files changed

+17
-4
lines changed

3 files changed

+17
-4
lines changed

libcxx/docs/Status/Cxx2cIssues.csv

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@
7171
"`LWG4079 <https://wg21.link/LWG4079>`__","Missing Preconditions in ``concat_view::iterator``\`s conversion constructor","2024-06 (St. Louis)","","",""
7272
"`LWG4082 <https://wg21.link/LWG4082>`__","``views::concat(r)`` is well-formed when ``r`` is an ``output_range``","2024-06 (St. Louis)","","",""
7373
"`LWG4083 <https://wg21.link/LWG4083>`__","``views::as_rvalue`` should reject non-input ranges","2024-06 (St. Louis)","","",""
74-
"`LWG4096 <https://wg21.link/LWG4096>`__","``views::iota(views::iota(0))`` should be rejected","2024-06 (St. Louis)","","",""
74+
"`LWG4096 <https://wg21.link/LWG4096>`__","``views::iota(views::iota(0))`` should be rejected","2024-06 (St. Louis)","|Complete|","22",""
7575
"`LWG4098 <https://wg21.link/LWG4098>`__","``views::adjacent<0>`` should reject non-forward ranges","2024-06 (St. Louis)","","",""
7676
"`LWG4105 <https://wg21.link/LWG4105>`__","``ranges::ends_with``\`s Returns misses difference casting","2024-06 (St. Louis)","","",""
7777
"`LWG4106 <https://wg21.link/LWG4106>`__","``basic_format_args`` should not be default-constructible","2024-06 (St. Louis)","|Complete|","19",""

libcxx/include/__ranges/iota_view.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include <__ranges/movable_box.h>
3131
#include <__ranges/view_interface.h>
3232
#include <__type_traits/conditional.h>
33+
#include <__type_traits/decay.h>
3334
#include <__type_traits/is_nothrow_constructible.h>
3435
#include <__type_traits/make_unsigned.h>
3536
#include <__type_traits/type_identity.h>
@@ -374,10 +375,10 @@ namespace views {
374375
namespace __iota {
375376
struct __fn {
376377
template <class _Start>
378+
requires(requires(_Start __s) { ranges::iota_view<decay_t<_Start>>(std::forward<_Start>(__s)); })
377379
_LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Start&& __start) const
378-
noexcept(noexcept(ranges::iota_view(std::forward<_Start>(__start))))
379-
-> decltype(ranges::iota_view(std::forward<_Start>(__start))) {
380-
return ranges::iota_view(std::forward<_Start>(__start));
380+
noexcept(noexcept(ranges::iota_view<decay_t<_Start>>(std::forward<_Start>(__start)))) {
381+
return ranges::iota_view<decay_t<_Start>>(std::forward<_Start>(__start));
381382
}
382383

383384
template <class _Start, class _BoundSentinel>

libcxx/test/std/ranges/range.factories/range.iota.view/views_iota.pass.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ constexpr void testType(U u) {
4646

4747
struct X {};
4848

49+
template <typename IntT>
50+
concept CanDoubleWrap = requires(IntT i) { std::views::iota(std::views::iota(i)); };
51+
4952
constexpr bool test() {
5053
testType<SomeInt>(SomeInt(10));
5154
testType<SomeInt>(IntComparableWith(SomeInt(10)));
@@ -68,6 +71,15 @@ constexpr bool test() {
6871
{
6972
static_assert(std::same_as<decltype(std::views::iota), decltype(std::ranges::views::iota)>);
7073
}
74+
{ // LWG4096: views::iota(views::iota(0)) should be rejected
75+
static_assert(!CanDoubleWrap<int>);
76+
static_assert(!CanDoubleWrap<SomeInt>);
77+
78+
static_assert(!std::is_invocable_v<decltype(std::views::iota), decltype(std::views::iota(0))>);
79+
static_assert(!std::is_invocable_v<decltype(std::views::iota), decltype(std::views::iota(82))>);
80+
static_assert(!std::is_invocable_v<decltype(std::views::iota), decltype(std::views::iota(SomeInt(0)))>);
81+
static_assert(!std::is_invocable_v<decltype(std::views::iota), decltype(std::views::iota(SomeInt(94)))>);
82+
}
7183

7284
return true;
7385
}

0 commit comments

Comments
 (0)