Skip to content

Commit c1291d0

Browse files
committed
Address most comments
1 parent d2a4080 commit c1291d0

File tree

3 files changed

+115
-75
lines changed

3 files changed

+115
-75
lines changed

libcxx/docs/ReleaseNotes/21.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ Implemented Papers
5454
- P2770R0: Stashing stashing ``iterators`` for proper flattening (`Github <https://github.com/llvm/llvm-project/issues/105250>`__)
5555
- P2655R3: ``common_reference_t`` of ``reference_wrapper`` Should Be a Reference Type (`Github <https://github.com/llvm/llvm-project/issues/105260>`__)
5656
- P3168R2 Give ``std::optional`` Range Support (`Github <https://github.com/llvm/llvm-project/issues/105430>`__)
57+
5758
Improvements and New Features
5859
-----------------------------
5960

libcxx/include/optional

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -199,13 +199,17 @@ namespace std {
199199
# include <__compare/three_way_comparable.h>
200200
# include <__concepts/invocable.h>
201201
# include <__config>
202+
# include <__cstddef/ptrdiff_t.h>
202203
# include <__exception/exception.h>
204+
# include <__format/range_format.h>
203205
# include <__functional/hash.h>
204206
# include <__functional/invoke.h>
205207
# include <__functional/unary_function.h>
206208
# include <__fwd/functional.h>
209+
# include <__iterator/wrap_iter.h>
207210
# include <__memory/addressof.h>
208211
# include <__memory/construct_at.h>
212+
# include <__ranges/enable_view.h>
209213
# include <__tuple/sfinae_helpers.h>
210214
# include <__type_traits/add_pointer.h>
211215
# include <__type_traits/conditional.h>
@@ -246,13 +250,6 @@ namespace std {
246250
# include <initializer_list>
247251
# include <version>
248252

249-
# if _LIBCPP_STD_VER >= 26
250-
# include <__cstddef/ptrdiff_t.h>
251-
# include <__format/range_format.h>
252-
# include <__iterator/wrap_iter.h>
253-
# include <__ranges/enable_view.h>
254-
# endif
255-
256253
// standard-mandated includes
257254

258255
// [optional.syn]

libcxx/test/std/utilities/optional/iterator.pass.cpp

Lines changed: 110 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -11,30 +11,94 @@
1111
// <optional>
1212

1313
// template <class T> class optional::iterator;
14-
15-
// 1: optional::iterator and optional const_iterator satisfy contiguous_iterator and random_access_iterator
16-
// 2. The value types and reference types for optional::iterator and optional::const_iterator are {_Tp, _Tp&} and {_Tp, const _Tp&} respectively
17-
// 3: The optional::begin() and optional::end() are marked noexcept.
18-
// 4: optionals that have a value have begin() != end(), whereas one that doesn't has begin() == end();
19-
// 5: The corresponding size for the following optionals is respected: has_value() == 1, !has_value() == 0
20-
// 6: Dereferencing an engaged optional's iterator returns the correct value.
21-
// 7: std::ranges::enable_view<optional<T>> == true, and std::format_kind<optional<T>> == true
22-
// 8: Verify that an iterator for loop counts only 1 item for an engaged optional, and 0 for an unegaged one.
23-
// 9: An optional with value that is reset will have a begin() == end(), then when it is reassigned a value, begin() != end(), and *begin() will contain the new value.
14+
// template <class T> class optional::const_iterator;
15+
// constexpr iterator optional::begin() noexcept;
16+
// constexpr iterator optional::end() noexcept;
17+
// constexpr const_iterator optional::begin() noexcept;
18+
// constexpr const_iterator optional::end() noexcept;
2419

2520
#include <cassert>
21+
#include <concepts>
22+
#include <iterator>
2623
#include <optional>
24+
#include <ranges>
25+
#include <type_traits>
2726

2827
#include "test_macros.h"
2928
#include "check_assertion.h"
3029

31-
constexpr int test_loop(const std::optional<char> val) {
32-
int size = 0;
33-
for (auto&& v : val) {
34-
std::ignore = v;
35-
size++;
36-
}
37-
return size;
30+
constexpr bool test_concepts() {
31+
const std::optional<char> opt{'a'};
32+
std::optional<char> nonconst_opt{'n'};
33+
34+
assert(std::contiguous_iterator<decltype(nonconst_opt.begin())>);
35+
assert(std::contiguous_iterator<decltype(nonconst_opt.end())>);
36+
assert(std::random_access_iterator<decltype(nonconst_opt.begin())>);
37+
assert(std::random_access_iterator<decltype(nonconst_opt.end())>);
38+
39+
assert(std::contiguous_iterator<decltype(opt.begin())>);
40+
assert(std::contiguous_iterator<decltype(opt.end())>);
41+
assert(std::random_access_iterator<decltype(opt.begin())>);
42+
assert(std::random_access_iterator<decltype(opt.end())>);
43+
44+
return true;
45+
}
46+
47+
constexpr bool test_types() {
48+
const std::optional<char> opt{'a'};
49+
std::optional<char> nonconst_opt{'n'};
50+
51+
assert((std::is_same_v<typename decltype(opt.begin())::value_type, char>));
52+
assert((std::is_same_v<typename decltype(opt.begin())::reference, const char&>));
53+
assert((std::is_same_v<typename decltype(nonconst_opt.begin())::value_type, char>));
54+
assert((std::is_same_v<typename decltype(nonconst_opt.begin())::reference, char&>));
55+
return true;
56+
}
57+
58+
constexpr bool test_size() {
59+
const std::optional<char> opt{'a'};
60+
std::optional<char> unengaged_opt;
61+
62+
assert(std::ranges::size(opt) == 1);
63+
assert(std::ranges::size(unengaged_opt) == 0);
64+
65+
return true;
66+
}
67+
68+
constexpr bool test_begin_end() {
69+
const std::optional<char> opt{'a'};
70+
std::optional<char> unengaged_opt;
71+
72+
assert(opt.begin() != opt.end());
73+
assert(unengaged_opt.begin() == unengaged_opt.end());
74+
return true;
75+
}
76+
77+
constexpr bool test_noexcept() {
78+
const std::optional<char> opt{'a'};
79+
std::optional<char> nonconst_opt{'n'};
80+
81+
ASSERT_NOEXCEPT(opt.begin());
82+
ASSERT_NOEXCEPT(opt.end());
83+
ASSERT_NOEXCEPT(nonconst_opt.begin());
84+
ASSERT_NOEXCEPT(nonconst_opt.end());
85+
86+
return true;
87+
}
88+
89+
constexpr bool test_value() {
90+
const std::optional<char> opt{'a'};
91+
std::optional<char> nonconst_opt{'n'};
92+
93+
assert(*(opt.begin()) == 'a');
94+
assert(*(nonconst_opt.begin()) == 'n');
95+
return true;
96+
}
97+
98+
constexpr bool test_syn() {
99+
assert(std::ranges::enable_view<std::optional<char>> == true);
100+
assert(std::format_kind<std::optional<char>> == std::range_format::disabled);
101+
return true;
38102
}
39103

40104
constexpr bool test_reset() {
@@ -48,76 +112,54 @@ constexpr bool test_reset() {
48112
return true;
49113
}
50114

51-
int main(int, char**) {
52-
constexpr const std::optional<char> opt{'a'};
53-
constexpr std::optional<char> unengaged_opt;
54-
std::optional<char> nonconst_opt{'n'};
55115

56-
// 1
116+
int main(int, char**) {
117+
// 1: optional::iterator and optional const_iterator satisfy contiguous_iterator and random_access_iterator
57118
{
58-
static_assert(std::contiguous_iterator<decltype(nonconst_opt.begin())>);
59-
static_assert(std::contiguous_iterator<decltype(nonconst_opt.end())>);
60-
static_assert(std::random_access_iterator<decltype(nonconst_opt.begin())>);
61-
static_assert(std::random_access_iterator<decltype(nonconst_opt.end())>);
62-
63-
static_assert(std::contiguous_iterator<decltype(opt.begin())>);
64-
static_assert(std::contiguous_iterator<decltype(opt.end())>);
65-
static_assert(std::random_access_iterator<decltype(opt.begin())>);
66-
static_assert(std::random_access_iterator<decltype(opt.end())>);
67-
}
68-
69-
{ // 2
70-
static_assert(std::same_as<typename decltype(opt.begin())::value_type, char>);
71-
static_assert(std::same_as<typename decltype(opt.begin())::reference, const char&>);
72-
static_assert(std::same_as<typename decltype(nonconst_opt.begin())::value_type, char>);
73-
static_assert(std::same_as<typename decltype(nonconst_opt.begin())::reference, char&>);
119+
test_concepts();
120+
static_assert(test_concepts());
74121
}
75122

76-
// 3
123+
// 2: The value types and reference types for optional::iterator and optional::const_iterator are {_Tp, _Tp&} and {_Tp, const _Tp&} respectively
77124
{
78-
ASSERT_NOEXCEPT(opt.begin());
79-
ASSERT_NOEXCEPT(opt.end());
80-
ASSERT_NOEXCEPT(nonconst_opt.begin());
81-
ASSERT_NOEXCEPT(nonconst_opt.end());
125+
test_types();
126+
static_assert(test_types());
82127
}
83128

84-
{ // 4
85-
static_assert(opt.begin() != opt.end());
86-
static_assert(unengaged_opt.begin() == unengaged_opt.end());
87-
assert(unengaged_opt.begin() == unengaged_opt.end());
88-
assert(opt.begin() != opt.end());
89-
assert(nonconst_opt.begin() != opt.end());
129+
// 3: The optional::begin() and optional::end() are marked noexcept.
130+
{
131+
test_noexcept();
132+
static_assert(test_noexcept());
90133
}
91134

92-
// 5
135+
// 4: optionals that have a value have begin() != end(), whereas one that doesn't has begin() == end();
93136
{
94-
static_assert(std::ranges::size(opt) == 1);
95-
static_assert(std::ranges::size(unengaged_opt) == 0);
96-
assert(std::ranges::size(opt) == 1);
97-
assert(std::ranges::size(unengaged_opt) == 0);
137+
test_begin_end();
138+
static_assert(test_begin_end());
98139
}
99140

100-
{ // 6
101-
static_assert(*opt.begin() == 'a');
102-
assert(*(opt.begin()) == 'a');
103-
assert(*(nonconst_opt.begin()) == 'n');
141+
// 5: The corresponding size for the following optionals is respected: has_value() == 1, !has_value() == 0
142+
{
143+
test_size();
144+
static_assert(test_size());
104145
}
105146

106-
{ // 7
107-
static_assert(std::ranges::enable_view<std::optional<char>> == true);
108-
assert(std::format_kind<std::optional<char>> == std::range_format::disabled);
147+
// 6: Dereferencing an engaged optional's iterator returns the correct value.
148+
{
149+
test_value();
150+
static_assert(test_value());
109151
}
110152

111-
{ // 8
112-
static_assert(test_loop(opt) == 1);
113-
static_assert(test_loop(unengaged_opt) == 0);
114-
assert(test_loop(opt) == 1);
115-
assert(test_loop(unengaged_opt) == 0);
153+
// 7: std::ranges::enable_view<optional<T>> == true, and std::format_kind<optional<T>> == true
154+
{
155+
test_syn();
156+
static_assert(test_syn());
116157
}
117158

118-
{ // 9
159+
// 8: An optional with value that is reset will have a begin() == end(), then when it is reassigned a value, begin() != end(), and *begin() will contain the new value.
160+
{
161+
test_reset();
119162
static_assert(test_reset());
120-
assert(test_reset());
121163
}
122164

123165
return 0;

0 commit comments

Comments
 (0)