Skip to content

Commit 60b6f43

Browse files
H-G-HristovZingamhawkinsw
authored
[libc++][ranges] LWG4001: iota_view should provide empty (#79687)
Implements: https://wg21.link/LWG4001 - https://eel.is/c++draft/range.iota.view --------- Co-authored-by: Zingam <[email protected]> Co-authored-by: Will Hawkins <[email protected]>
1 parent 5d42d69 commit 60b6f43

File tree

3 files changed

+120
-1
lines changed

3 files changed

+120
-1
lines changed

libcxx/docs/Status/Cxx2cIssues.csv

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
"`3974 <https://wg21.link/LWG3974>`__","``mdspan::operator[]`` should not copy ``OtherIndexTypes``","Kona November 2023","","",""
3939
"`3987 <https://wg21.link/LWG3987>`__","Including ``<flat_foo>`` doesn't provide ``std::begin``/``end``","Kona November 2023","","","|flat_containers|"
4040
"`3990 <https://wg21.link/LWG3990>`__","Program-defined specializations of ``std::tuple`` and ``std::variant`` can't be properly supported","Kona November 2023","","",""
41-
"`4001 <https://wg21.link/LWG4001>`__","``iota_view`` should provide ``empty``","Kona November 2023","","","|ranges|"
41+
"`4001 <https://wg21.link/LWG4001>`__","``iota_view`` should provide ``empty``","Kona November 2023","|Complete|","19.0","|ranges|"
4242
"","","","","",""
4343
"`3767 <https://wg21.link/LWG3767>`__","``codecvt<charN_t, char8_t, mbstate_t>`` incorrectly added to locale","Tokyo March 2024","","",""
4444
"`3919 <https://wg21.link/LWG3919>`__","``enumerate_view`` may invoke UB for sized common non-forward underlying ranges","Tokyo March 2024","","","|ranges|"

libcxx/include/__ranges/iota_view.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,8 @@ class iota_view : public view_interface<iota_view<_Start, _BoundSentinel>> {
344344
return __iterator{__bound_sentinel_};
345345
}
346346

347+
_LIBCPP_HIDE_FROM_ABI constexpr bool empty() const { return __value_ == __bound_sentinel_; }
348+
347349
_LIBCPP_HIDE_FROM_ABI constexpr auto size() const
348350
requires(same_as<_Start, _BoundSentinel> && __advanceable<_Start>) ||
349351
(integral<_Start> && integral<_BoundSentinel>) || sized_sentinel_for<_BoundSentinel, _Start>
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
// UNSUPPORTED: c++03, c++11, c++14, c++17
10+
11+
// constexpr bool empty() const;
12+
13+
#include <cassert>
14+
#include <concepts>
15+
#include <ranges>
16+
#include <utility>
17+
#include <vector>
18+
19+
#include "types.h"
20+
21+
template <typename R>
22+
concept HasEmpty = requires(const R r) {
23+
std::ranges::empty(r);
24+
{ r.empty() } -> std::same_as<bool>;
25+
};
26+
27+
constexpr void test_empty_iota_sfinae() {
28+
std::vector<int> ev;
29+
30+
auto iv = std::views::iota(std::ranges::begin(ev), std::ranges::end(ev));
31+
32+
static_assert(HasEmpty<decltype(iv)>);
33+
static_assert(HasEmpty<decltype(std::as_const(iv))>);
34+
}
35+
36+
constexpr void test_nonempty_iota_sfinae() {
37+
// Default ctr
38+
{
39+
std::ranges::iota_view<Int42<DefaultTo42>> iv;
40+
41+
static_assert(HasEmpty<decltype(iv)>);
42+
}
43+
// Value pass
44+
{
45+
std::ranges::iota_view<SomeInt> iv(SomeInt(94));
46+
47+
static_assert(HasEmpty<decltype(iv)>);
48+
}
49+
50+
{
51+
std::vector<char> v;
52+
auto it = std::back_inserter(v);
53+
auto iv = std::views::iota(it);
54+
55+
static_assert(HasEmpty<decltype(iv)>);
56+
}
57+
{
58+
std::vector<char> v{'b', 'a', 'b', 'a', 'z', 'm', 't'};
59+
auto it = std::back_inserter(v);
60+
auto iv = std::views::iota(it);
61+
62+
static_assert(HasEmpty<decltype(iv)>);
63+
}
64+
}
65+
66+
constexpr void test_empty_iota() {
67+
std::vector<int> ev;
68+
69+
auto iv = std::views::iota(std::ranges::begin(ev), std::ranges::end(ev));
70+
71+
assert(iv.empty());
72+
assert(std::as_const(iv).empty());
73+
}
74+
75+
constexpr void test_nonempty_iota() {
76+
// Default ctr
77+
{
78+
std::ranges::iota_view<Int42<DefaultTo42>> iv;
79+
80+
assert(!iv.empty());
81+
}
82+
// Value pass
83+
{
84+
std::ranges::iota_view<SomeInt> iv(SomeInt(94));
85+
86+
assert(!iv.empty());
87+
}
88+
89+
{
90+
std::vector<char> v;
91+
auto it = std::back_inserter(v);
92+
auto iv = std::views::iota(it);
93+
94+
assert(!iv.empty());
95+
}
96+
{
97+
std::vector<char> v{'b', 'a', 'b', 'a', 'z', 'm', 't'};
98+
auto it = std::back_inserter(v);
99+
auto iv = std::views::iota(it);
100+
101+
assert(!iv.empty());
102+
}
103+
}
104+
105+
constexpr bool test() {
106+
test_empty_iota();
107+
test_nonempty_iota();
108+
109+
return true;
110+
}
111+
112+
int main(int, char**) {
113+
test();
114+
static_assert(test());
115+
116+
return 0;
117+
}

0 commit comments

Comments
 (0)