Skip to content

Commit fe76be2

Browse files
ZingamH-G-Hristov
authored andcommitted
[libc++][ranges] LWG4001: iota_view should provide empty
Implements: https://wg21.link/LWG4001 - https://eel.is/c++draft/range.iota.view
1 parent 737fc35 commit fe76be2

File tree

3 files changed

+139
-1
lines changed

3 files changed

+139
-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
"`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",""
4444
"","","","","",""

libcxx/include/__ranges/iota_view.h

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

348+
_LIBCPP_HIDE_FROM_ABI constexpr bool empty() const { return __value_ == __bound_sentinel_; }
349+
348350
_LIBCPP_HIDE_FROM_ABI constexpr auto size() const
349351
requires(same_as<_Start, _BoundSentinel> && __advanceable<_Start>) ||
350352
(integral<_Start> && integral<_BoundSentinel>) || sized_sentinel_for<_BoundSentinel, _Start>
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
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 HasFreeEmpty = requires(R r) { std::ranges::empty(r); };
23+
24+
template <typename R>
25+
concept HasMemberEmpty = requires(R r) {
26+
{ r.empty() } -> std::same_as<bool>;
27+
};
28+
29+
constexpr void test_empty_iota() {
30+
std::vector<int> ev;
31+
32+
// Both parameters are non-const
33+
{
34+
auto iv = std::views::iota(std::ranges::begin(ev), std::ranges::end(ev));
35+
36+
static_assert(HasFreeEmpty<decltype(iv)>);
37+
static_assert(HasMemberEmpty<decltype(iv)>);
38+
39+
assert(iv.empty());
40+
}
41+
// Left paramter is const
42+
{
43+
auto iv = std::views::iota(std::ranges::begin(std::as_const(ev)), std::ranges::end(ev));
44+
45+
static_assert(HasFreeEmpty<decltype(iv)>);
46+
static_assert(HasMemberEmpty<decltype(iv)>);
47+
48+
assert(iv.empty());
49+
}
50+
// Right paramter is const
51+
{
52+
auto iv = std::views::iota(std::ranges::begin(ev), std::ranges::end(std::as_const(ev)));
53+
54+
static_assert(HasFreeEmpty<decltype(iv)>);
55+
static_assert(HasMemberEmpty<decltype(iv)>);
56+
57+
assert(iv.empty());
58+
}
59+
// Both parameters are const
60+
{
61+
auto iv = std::views::iota(std::ranges::begin(std::as_const(ev)), std::ranges::end(std::as_const(ev)));
62+
63+
static_assert(HasFreeEmpty<decltype(iv)>);
64+
static_assert(HasMemberEmpty<decltype(iv)>);
65+
66+
assert(iv.empty());
67+
}
68+
69+
std::vector<char> v{'b', 'a', 'b', 'a', 'z', 'm', 't'};
70+
auto fv = v | std::views::filter([](auto val) { return val == '0'; });
71+
72+
{
73+
auto iv = std::views::iota(std::ranges::begin(fv), std::ranges::end(fv));
74+
75+
static_assert(HasFreeEmpty<decltype(iv)>);
76+
static_assert(HasMemberEmpty<decltype(iv)>);
77+
78+
assert(iv.empty());
79+
}
80+
}
81+
82+
constexpr void test_nonempty_iota() {
83+
// Default ctr
84+
{
85+
std::ranges::iota_view<Int42<DefaultTo42>> iv;
86+
87+
static_assert(HasFreeEmpty<decltype(iv)>);
88+
static_assert(HasMemberEmpty<decltype(iv)>);
89+
90+
assert(!iv.empty());
91+
}
92+
// Value pass
93+
{
94+
std::ranges::iota_view<SomeInt> iv(SomeInt(94));
95+
96+
static_assert(HasFreeEmpty<decltype(iv)>);
97+
static_assert(HasMemberEmpty<decltype(iv)>);
98+
99+
assert(!iv.empty());
100+
}
101+
102+
{
103+
std::vector<char> v;
104+
auto it = std::back_inserter(v);
105+
auto iv = std::views::iota(it);
106+
107+
static_assert(HasFreeEmpty<decltype(iv)>);
108+
static_assert(HasMemberEmpty<decltype(iv)>);
109+
110+
assert(!iv.empty());
111+
}
112+
{
113+
std::vector<char> v{'b', 'a', 'b', 'a', 'z', 'm', 't'};
114+
auto it = std::back_inserter(v);
115+
auto iv = std::views::iota(it);
116+
117+
static_assert(HasFreeEmpty<decltype(iv)>);
118+
static_assert(HasMemberEmpty<decltype(iv)>);
119+
120+
assert(!iv.empty());
121+
}
122+
}
123+
124+
constexpr bool test() {
125+
test_empty_iota();
126+
test_nonempty_iota();
127+
128+
return true;
129+
}
130+
131+
int main(int, char**) {
132+
test();
133+
static_assert(test());
134+
135+
return 0;
136+
}

0 commit comments

Comments
 (0)