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, c++20 |
10 | |
11 | // <optional> |
12 | |
13 | // template<class F> constexpr auto and_then(F&&) &; |
14 | // template<class F> constexpr auto and_then(F&&) &&; |
15 | // template<class F> constexpr auto and_then(F&&) const&; |
16 | // template<class F> constexpr auto and_then(F&&) const&&; |
17 | |
18 | #include <cassert> |
19 | #include <optional> |
20 | |
21 | #include "test_macros.h" |
22 | |
23 | struct LVal { |
24 | constexpr std::optional<int> operator()(int&) { return 1; } |
25 | std::optional<int> operator()(const int&) = delete; |
26 | std::optional<int> operator()(int&&) = delete; |
27 | std::optional<int> operator()(const int&&) = delete; |
28 | }; |
29 | |
30 | struct CLVal { |
31 | std::optional<int> operator()(int&) = delete; |
32 | constexpr std::optional<int> operator()(const int&) { return 1; } |
33 | std::optional<int> operator()(int&&) = delete; |
34 | std::optional<int> operator()(const int&&) = delete; |
35 | }; |
36 | |
37 | struct RVal { |
38 | std::optional<int> operator()(int&) = delete; |
39 | std::optional<int> operator()(const int&) = delete; |
40 | constexpr std::optional<int> operator()(int&&) { return 1; } |
41 | std::optional<int> operator()(const int&&) = delete; |
42 | }; |
43 | |
44 | struct CRVal { |
45 | std::optional<int> operator()(int&) = delete; |
46 | std::optional<int> operator()(const int&) = delete; |
47 | std::optional<int> operator()(int&&) = delete; |
48 | constexpr std::optional<int> operator()(const int&&) { return 1; } |
49 | }; |
50 | |
51 | struct RefQual { |
52 | constexpr std::optional<int> operator()(int) & { return 1; } |
53 | std::optional<int> operator()(int) const& = delete; |
54 | std::optional<int> operator()(int) && = delete; |
55 | std::optional<int> operator()(int) const&& = delete; |
56 | }; |
57 | |
58 | struct CRefQual { |
59 | std::optional<int> operator()(int) & = delete; |
60 | constexpr std::optional<int> operator()(int) const& { return 1; } |
61 | std::optional<int> operator()(int) && = delete; |
62 | std::optional<int> operator()(int) const&& = delete; |
63 | }; |
64 | |
65 | struct RVRefQual { |
66 | std::optional<int> operator()(int) & = delete; |
67 | std::optional<int> operator()(int) const& = delete; |
68 | constexpr std::optional<int> operator()(int) && { return 1; } |
69 | std::optional<int> operator()(int) const&& = delete; |
70 | }; |
71 | |
72 | struct RVCRefQual { |
73 | std::optional<int> operator()(int) & = delete; |
74 | std::optional<int> operator()(int) const& = delete; |
75 | std::optional<int> operator()(int) && = delete; |
76 | constexpr std::optional<int> operator()(int) const&& { return 1; } |
77 | }; |
78 | |
79 | struct NOLVal { |
80 | constexpr std::optional<int> operator()(int&) { return std::nullopt; } |
81 | std::optional<int> operator()(const int&) = delete; |
82 | std::optional<int> operator()(int&&) = delete; |
83 | std::optional<int> operator()(const int&&) = delete; |
84 | }; |
85 | |
86 | struct NOCLVal { |
87 | std::optional<int> operator()(int&) = delete; |
88 | constexpr std::optional<int> operator()(const int&) { return std::nullopt; } |
89 | std::optional<int> operator()(int&&) = delete; |
90 | std::optional<int> operator()(const int&&) = delete; |
91 | }; |
92 | |
93 | struct NORVal { |
94 | std::optional<int> operator()(int&) = delete; |
95 | std::optional<int> operator()(const int&) = delete; |
96 | constexpr std::optional<int> operator()(int&&) { return std::nullopt; } |
97 | std::optional<int> operator()(const int&&) = delete; |
98 | }; |
99 | |
100 | struct NOCRVal { |
101 | std::optional<int> operator()(int&) = delete; |
102 | std::optional<int> operator()(const int&) = delete; |
103 | std::optional<int> operator()(int&&) = delete; |
104 | constexpr std::optional<int> operator()(const int&&) { return std::nullopt; } |
105 | }; |
106 | |
107 | struct NORefQual { |
108 | constexpr std::optional<int> operator()(int) & { return std::nullopt; } |
109 | std::optional<int> operator()(int) const& = delete; |
110 | std::optional<int> operator()(int) && = delete; |
111 | std::optional<int> operator()(int) const&& = delete; |
112 | }; |
113 | |
114 | struct NOCRefQual { |
115 | std::optional<int> operator()(int) & = delete; |
116 | constexpr std::optional<int> operator()(int) const& { return std::nullopt; } |
117 | std::optional<int> operator()(int) && = delete; |
118 | std::optional<int> operator()(int) const&& = delete; |
119 | }; |
120 | |
121 | struct NORVRefQual { |
122 | std::optional<int> operator()(int) & = delete; |
123 | std::optional<int> operator()(int) const& = delete; |
124 | constexpr std::optional<int> operator()(int) && { return std::nullopt; } |
125 | std::optional<int> operator()(int) const&& = delete; |
126 | }; |
127 | |
128 | struct NORVCRefQual { |
129 | std::optional<int> operator()(int) & = delete; |
130 | std::optional<int> operator()(int) const& = delete; |
131 | std::optional<int> operator()(int) && = delete; |
132 | constexpr std::optional<int> operator()(int) const&& { return std::nullopt; } |
133 | }; |
134 | |
135 | struct NoCopy { |
136 | NoCopy() = default; |
137 | NoCopy(const NoCopy&) { assert(false); } |
138 | std::optional<int> operator()(const NoCopy&&) { return 1; } |
139 | }; |
140 | |
141 | struct NonConst { |
142 | std::optional<int> non_const() { return 1; } |
143 | }; |
144 | |
145 | constexpr void test_val_types() { |
146 | // Test & overload |
147 | { |
148 | // Without & qualifier on F's operator() |
149 | { |
150 | std::optional<int> i{0}; |
151 | assert(i.and_then(LVal{}) == 1); |
152 | assert(i.and_then(NOLVal{}) == std::nullopt); |
153 | ASSERT_SAME_TYPE(decltype(i.and_then(LVal{})), std::optional<int>); |
154 | } |
155 | |
156 | //With & qualifier on F's operator() |
157 | { |
158 | std::optional<int> i{0}; |
159 | RefQual l{}; |
160 | assert(i.and_then(l) == 1); |
161 | NORefQual nl{}; |
162 | assert(i.and_then(nl) == std::nullopt); |
163 | ASSERT_SAME_TYPE(decltype(i.and_then(l)), std::optional<int>); |
164 | } |
165 | } |
166 | |
167 | // Test const& overload |
168 | { |
169 | // Without & qualifier on F's operator() |
170 | { |
171 | const std::optional<int> i{0}; |
172 | assert(i.and_then(CLVal{}) == 1); |
173 | assert(i.and_then(NOCLVal{}) == std::nullopt); |
174 | ASSERT_SAME_TYPE(decltype(i.and_then(CLVal{})), std::optional<int>); |
175 | } |
176 | |
177 | //With & qualifier on F's operator() |
178 | { |
179 | const std::optional<int> i{0}; |
180 | const CRefQual l{}; |
181 | assert(i.and_then(l) == 1); |
182 | const NOCRefQual nl{}; |
183 | assert(i.and_then(nl) == std::nullopt); |
184 | ASSERT_SAME_TYPE(decltype(i.and_then(l)), std::optional<int>); |
185 | } |
186 | } |
187 | |
188 | // Test && overload |
189 | { |
190 | // Without & qualifier on F's operator() |
191 | { |
192 | std::optional<int> i{0}; |
193 | assert(std::move(i).and_then(RVal{}) == 1); |
194 | assert(std::move(i).and_then(NORVal{}) == std::nullopt); |
195 | ASSERT_SAME_TYPE(decltype(std::move(i).and_then(RVal{})), std::optional<int>); |
196 | } |
197 | |
198 | //With & qualifier on F's operator() |
199 | { |
200 | std::optional<int> i{0}; |
201 | assert(i.and_then(RVRefQual{}) == 1); |
202 | assert(i.and_then(NORVRefQual{}) == std::nullopt); |
203 | ASSERT_SAME_TYPE(decltype(i.and_then(RVRefQual{})), std::optional<int>); |
204 | } |
205 | } |
206 | |
207 | // Test const&& overload |
208 | { |
209 | // Without & qualifier on F's operator() |
210 | { |
211 | const std::optional<int> i{0}; |
212 | assert(std::move(i).and_then(CRVal{}) == 1); |
213 | assert(std::move(i).and_then(NOCRVal{}) == std::nullopt); |
214 | ASSERT_SAME_TYPE(decltype(std::move(i).and_then(CRVal{})), std::optional<int>); |
215 | } |
216 | |
217 | //With & qualifier on F's operator() |
218 | { |
219 | const std::optional<int> i{0}; |
220 | const RVCRefQual l{}; |
221 | assert(i.and_then(std::move(l)) == 1); |
222 | const NORVCRefQual nl{}; |
223 | assert(i.and_then(std::move(nl)) == std::nullopt); |
224 | ASSERT_SAME_TYPE(decltype(i.and_then(std::move(l))), std::optional<int>); |
225 | } |
226 | } |
227 | } |
228 | |
229 | // check that the lambda body is not instantiated during overload resolution |
230 | constexpr void test_sfinae() { |
231 | std::optional<NonConst> opt{}; |
232 | auto l = [](auto&& x) { return x.non_const(); }; |
233 | opt.and_then(l); |
234 | std::move(opt).and_then(l); |
235 | } |
236 | |
237 | constexpr bool test() { |
238 | test_val_types(); |
239 | std::optional<int> opt{}; |
240 | const auto& copt = opt; |
241 | |
242 | const auto never_called = [](int) { |
243 | assert(false); |
244 | return std::optional<int>{}; |
245 | }; |
246 | |
247 | opt.and_then(never_called); |
248 | std::move(opt).and_then(never_called); |
249 | copt.and_then(never_called); |
250 | std::move(copt).and_then(never_called); |
251 | |
252 | std::optional<NoCopy> nc; |
253 | const auto& cnc = nc; |
254 | std::move(cnc).and_then(NoCopy{}); |
255 | std::move(nc).and_then(NoCopy{}); |
256 | |
257 | return true; |
258 | } |
259 | |
260 | int main(int, char**) { |
261 | test(); |
262 | static_assert(test()); |
263 | return 0; |
264 | } |
265 | |