Skip to content

[libc++][ranges] LWG4096: views::iota(views::iota(0)) should be rejected #152855

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
2 changes: 1 addition & 1 deletion libcxx/docs/Status/Cxx2cIssues.csv
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@
"`LWG4079 <https://wg21.link/LWG4079>`__","Missing Preconditions in ``concat_view::iterator``\`s conversion constructor","2024-06 (St. Louis)","","",""
"`LWG4082 <https://wg21.link/LWG4082>`__","``views::concat(r)`` is well-formed when ``r`` is an ``output_range``","2024-06 (St. Louis)","","",""
"`LWG4083 <https://wg21.link/LWG4083>`__","``views::as_rvalue`` should reject non-input ranges","2024-06 (St. Louis)","","",""
"`LWG4096 <https://wg21.link/LWG4096>`__","``views::iota(views::iota(0))`` should be rejected","2024-06 (St. Louis)","","",""
"`LWG4096 <https://wg21.link/LWG4096>`__","``views::iota(views::iota(0))`` should be rejected","2024-06 (St. Louis)","|Complete|","22",""
"`LWG4098 <https://wg21.link/LWG4098>`__","``views::adjacent<0>`` should reject non-forward ranges","2024-06 (St. Louis)","","",""
"`LWG4105 <https://wg21.link/LWG4105>`__","``ranges::ends_with``\`s Returns misses difference casting","2024-06 (St. Louis)","","",""
"`LWG4106 <https://wg21.link/LWG4106>`__","``basic_format_args`` should not be default-constructible","2024-06 (St. Louis)","|Complete|","19",""
Expand Down
4 changes: 3 additions & 1 deletion libcxx/include/__ranges/iota_view.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include <__ranges/movable_box.h>
#include <__ranges/view_interface.h>
#include <__type_traits/conditional.h>
#include <__type_traits/decay.h>
#include <__type_traits/is_nothrow_constructible.h>
#include <__type_traits/make_unsigned.h>
#include <__type_traits/type_identity.h>
Expand Down Expand Up @@ -374,10 +375,11 @@ namespace views {
namespace __iota {
struct __fn {
template <class _Start>
requires(requires(_Start __s) { ranges::iota_view<decay_t<_Start>>(std::forward<_Start>(__s)); })
_LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Start&& __start) const
noexcept(noexcept(ranges::iota_view(std::forward<_Start>(__start))))
-> decltype(ranges::iota_view(std::forward<_Start>(__start))) {
return ranges::iota_view(std::forward<_Start>(__start));
return ranges::iota_view<decay_t<_Start>>(std::forward<_Start>(__start));
}

template <class _Start, class _BoundSentinel>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ constexpr void testType(U u) {

struct X {};

template <typename IntT>
concept CanDoubleWrap = requires(IntT i) { std::views::iota(std::views::iota(i)); };

constexpr bool test() {
testType<SomeInt>(SomeInt(10));
testType<SomeInt>(IntComparableWith(SomeInt(10)));
Expand All @@ -68,6 +71,12 @@ constexpr bool test() {
{
static_assert(std::same_as<decltype(std::views::iota), decltype(std::ranges::views::iota)>);
}
{ // LWG4096: views::iota(views::iota(0)) should be rejected
static_assert(!CanDoubleWrap<int>);
static_assert(!CanDoubleWrap<SomeInt>);

static_assert(!std::is_invocable_v<decltype(std::views::iota), decltype(std::views::iota(82))>);
}

return true;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

// REQUIRES: std-at-least-c++20

// views::iota

#include <ranges>

#include "types.h"

void test() {
// LWG4096
{
[[maybe_unused]] auto i1 = std::views::iota(0); // OK
[[maybe_unused]] auto i2 = std::views::iota(std::views::iota(0));
// expected-error@*:* {{no matching function for call to object of type 'const __iota::__fn'}}
}
{
[[maybe_unused]] auto i1 = std::views::iota(SomeInt(0)); // OK
[[maybe_unused]] auto i2 = std::views::iota(std::views::iota(SomeInt(0)));
//expected-error@*:* {{no matching function for call to object of type 'const __iota::__fn'}}
}
}
Loading