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 | // <expected> |
12 | |
13 | // template<class F> constexpr auto and_then(F&& f) &; |
14 | // template<class F> constexpr auto and_then(F&& f) const &; |
15 | // template<class F> constexpr auto and_then(F&& f) &&; |
16 | // template<class F> constexpr auto and_then(F&& f) const &&; |
17 | |
18 | #include <cassert> |
19 | #include <concepts> |
20 | #include <expected> |
21 | #include <memory> |
22 | #include <type_traits> |
23 | #include <utility> |
24 | |
25 | #include "../../types.h" |
26 | |
27 | struct LVal { |
28 | constexpr std::expected<int, int> operator()(int&) { return 1; } |
29 | std::expected<int, int> operator()(const int&) = delete; |
30 | std::expected<int, int> operator()(int&&) = delete; |
31 | std::expected<int, int> operator()(const int&&) = delete; |
32 | }; |
33 | |
34 | struct CLVal { |
35 | std::expected<int, int> operator()(int&) = delete; |
36 | constexpr std::expected<int, int> operator()(const int&) { return 1; } |
37 | std::expected<int, int> operator()(int&&) = delete; |
38 | std::expected<int, int> operator()(const int&&) = delete; |
39 | }; |
40 | |
41 | struct RVal { |
42 | std::expected<int, int> operator()(int&) = delete; |
43 | std::expected<int, int> operator()(const int&) = delete; |
44 | constexpr std::expected<int, int> operator()(int&&) { return 1; } |
45 | std::expected<int, int> operator()(const int&&) = delete; |
46 | }; |
47 | |
48 | struct CRVal { |
49 | std::expected<int, int> operator()(int&) = delete; |
50 | std::expected<int, int> operator()(const int&) = delete; |
51 | std::expected<int, int> operator()(int&&) = delete; |
52 | constexpr std::expected<int, int> operator()(const int&&) { return 1; } |
53 | }; |
54 | |
55 | struct RefQual { |
56 | constexpr std::expected<int, int> operator()(int) & { return 1; } |
57 | std::expected<int, int> operator()(int) const& = delete; |
58 | std::expected<int, int> operator()(int) && = delete; |
59 | std::expected<int, int> operator()(int) const&& = delete; |
60 | }; |
61 | |
62 | struct CRefQual { |
63 | std::expected<int, int> operator()(int) & = delete; |
64 | constexpr std::expected<int, int> operator()(int) const& { return 1; } |
65 | std::expected<int, int> operator()(int) && = delete; |
66 | std::expected<int, int> operator()(int) const&& = delete; |
67 | }; |
68 | |
69 | struct RVRefQual { |
70 | std::expected<int, int> operator()(int) & = delete; |
71 | std::expected<int, int> operator()(int) const& = delete; |
72 | constexpr std::expected<int, int> operator()(int) && { return 1; } |
73 | std::expected<int, int> operator()(int) const&& = delete; |
74 | }; |
75 | |
76 | struct RVCRefQual { |
77 | std::expected<int, int> operator()(int) & = delete; |
78 | std::expected<int, int> operator()(int) const& = delete; |
79 | std::expected<int, int> operator()(int) && = delete; |
80 | constexpr std::expected<int, int> operator()(int) const&& { return 1; } |
81 | }; |
82 | |
83 | struct UnexpectedLVal { |
84 | constexpr std::expected<int, int> operator()(int&) { return std::expected<int, int>(std::unexpected<int>(5)); } |
85 | std::expected<int, int> operator()(const int&) = delete; |
86 | std::expected<int, int> operator()(int&&) = delete; |
87 | std::expected<int, int> operator()(const int&&) = delete; |
88 | }; |
89 | |
90 | struct UnexpectedCLVal { |
91 | std::expected<int, int> operator()(int&) = delete; |
92 | constexpr std::expected<int, int> operator()(const int&) { return std::expected<int, int>(std::unexpected<int>(5)); } |
93 | std::expected<int, int> operator()(int&&) = delete; |
94 | std::expected<int, int> operator()(const int&&) = delete; |
95 | }; |
96 | |
97 | struct UnexpectedRVal { |
98 | std::expected<int, int> operator()(int&) = delete; |
99 | std::expected<int, int> operator()(const int&) = delete; |
100 | constexpr std::expected<int, int> operator()(int&&) { return std::expected<int, int>(std::unexpected<int>(5)); } |
101 | std::expected<int, int> operator()(const int&&) = delete; |
102 | }; |
103 | |
104 | struct UnexpectedCRVal { |
105 | std::expected<int, int> operator()(int&) = delete; |
106 | std::expected<int, int> operator()(const int&) = delete; |
107 | std::expected<int, int> operator()(int&&) = delete; |
108 | constexpr std::expected<int, int> operator()(const int&&) { return std::expected<int, int>(std::unexpected<int>(5)); } |
109 | }; |
110 | |
111 | struct UnexpectedRefQual { |
112 | constexpr std::expected<int, int> operator()(int) & { return std::expected<int, int>(std::unexpected<int>(5)); } |
113 | std::expected<int, int> operator()(int) const& = delete; |
114 | std::expected<int, int> operator()(int) && = delete; |
115 | std::expected<int, int> operator()(int) const&& = delete; |
116 | }; |
117 | |
118 | struct UnexpectedCRefQual { |
119 | std::expected<int, int> operator()(int) & = delete; |
120 | constexpr std::expected<int, int> operator()(int) const& { return std::expected<int, int>(std::unexpected<int>(5)); } |
121 | std::expected<int, int> operator()(int) && = delete; |
122 | std::expected<int, int> operator()(int) const&& = delete; |
123 | }; |
124 | |
125 | struct UnexpectedRVRefQual { |
126 | std::expected<int, int> operator()(int) & = delete; |
127 | std::expected<int, int> operator()(int) const& = delete; |
128 | constexpr std::expected<int, int> operator()(int) && { return std::expected<int, int>(std::unexpected<int>(5)); } |
129 | std::expected<int, int> operator()(int) const&& = delete; |
130 | }; |
131 | |
132 | struct UnexpectedRVCRefQual { |
133 | std::expected<int, int> operator()(int) & = delete; |
134 | std::expected<int, int> operator()(int) const& = delete; |
135 | std::expected<int, int> operator()(int) && = delete; |
136 | constexpr std::expected<int, int> operator()(int) const&& { return std::expected<int, int>(std::unexpected<int>(5)); } |
137 | }; |
138 | |
139 | struct NonCopyable { |
140 | constexpr NonCopyable(int) {} |
141 | NonCopyable(const NonCopyable&) = delete; |
142 | }; |
143 | |
144 | struct NonMovable { |
145 | constexpr NonMovable(int) {} |
146 | NonMovable(NonMovable&&) = delete; |
147 | }; |
148 | |
149 | struct NonConst { |
150 | std::expected<int, int> non_const() { return 1; } |
151 | }; |
152 | |
153 | template <class E, class F> |
154 | concept has_and_then = requires(E&& e, F&& f) { |
155 | {std::forward<E>(e).and_then(std::forward<F>(f))}; |
156 | }; |
157 | |
158 | // clang-format off |
159 | static_assert( has_and_then<std::expected<int, int>&, std::expected<int, int>(int&)>); |
160 | static_assert(!has_and_then<std::expected<int, NonCopyable>&, std::expected<int, NonCopyable>(int&)>); |
161 | static_assert( has_and_then<const std::expected<int, int>&, std::expected<int, int>(const int&)>); |
162 | static_assert(!has_and_then<const std::expected<int, NonCopyable>&, std::expected<int, NonCopyable>(const int&)>); |
163 | static_assert( has_and_then<std::expected<int, int>&&, std::expected<int, int>(int)>); |
164 | static_assert(!has_and_then<std::expected<int, NonMovable>&&, std::expected<int, NonMovable>(int)>); |
165 | static_assert( has_and_then<const std::expected<int, int>&&, std::expected<int, int>(const int)>); |
166 | static_assert(!has_and_then<const std::expected<int, NonMovable>&&, std::expected<int, NonMovable>(const int)>); |
167 | |
168 | // [LWG 3877] https://cplusplus.github.io/LWG/issue3877, check constraint failing but not compile error inside the function body. |
169 | static_assert(!has_and_then<const std::expected<int, std::unique_ptr<int>>&, int()>); |
170 | static_assert(!has_and_then<const std::expected<int, std::unique_ptr<int>>&&, int()>); |
171 | |
172 | // [LWG 3983] https://cplusplus.github.io/LWG/issue3938, check std::expected monadic ops well-formed with move-only error_type. |
173 | // There are no effects for `&` and `const &` overload, because the constraints requires is_constructible_v<E, decltype(error())> is true. |
174 | static_assert(has_and_then<std::expected<int, MoveOnlyErrorType>&&, std::expected<int, MoveOnlyErrorType>(int)>); |
175 | static_assert(has_and_then<const std::expected<int, MoveOnlyErrorType>&&, std::expected<int, MoveOnlyErrorType>(const int)>); |
176 | |
177 | constexpr void test_val_types() { |
178 | // Test & overload |
179 | { |
180 | // Without & qualifier on F's operator() |
181 | { |
182 | std::expected<int, int> e{0}; |
183 | std::same_as<std::expected<int, int>> decltype(auto) val = e.and_then(LVal{}); |
184 | assert(val == 1); |
185 | assert(e.and_then(UnexpectedLVal{}).error() == 5); |
186 | } |
187 | |
188 | // With & qualifier on F's operator() |
189 | { |
190 | std::expected<int, int> e{0}; |
191 | RefQual l{}; |
192 | std::same_as<std::expected<int, int>> decltype(auto) val = e.and_then(l); |
193 | assert(val == 1); |
194 | UnexpectedRefQual nl{}; |
195 | assert(e.and_then(nl).error() == 5); |
196 | } |
197 | } |
198 | |
199 | // Test const& overload |
200 | { |
201 | // Without & qualifier on F's operator() |
202 | { |
203 | const std::expected<int, int> e{0}; |
204 | std::same_as<std::expected<int, int>> decltype(auto) val = e.and_then(CLVal{}); |
205 | assert(val == 1); |
206 | assert(e.and_then(UnexpectedCLVal{}).error() == 5); |
207 | } |
208 | |
209 | // With & qualifier on F's operator() |
210 | { |
211 | const std::expected<int, int> e{0}; |
212 | const CRefQual l{}; |
213 | std::same_as<std::expected<int, int>> decltype(auto) val = e.and_then(l); |
214 | assert(val == 1); |
215 | const UnexpectedCRefQual nl{}; |
216 | assert(e.and_then(nl).error() == 5); |
217 | } |
218 | } |
219 | |
220 | // Test && overload |
221 | { |
222 | // Without & qualifier on F's operator() |
223 | { |
224 | std::expected<int, int> e{0}; |
225 | std::same_as<std::expected<int, int>> decltype(auto) val = std::move(e).and_then(RVal{}); |
226 | assert(val == 1); |
227 | assert(std::move(e).and_then(UnexpectedRVal{}).error() == 5); |
228 | } |
229 | |
230 | // With & qualifier on F's operator() |
231 | { |
232 | std::expected<int, int> e{0}; |
233 | std::same_as<std::expected<int, int>> decltype(auto) val = std::move(e).and_then(RVRefQual{}); |
234 | assert(val == 1); |
235 | assert(e.and_then(UnexpectedRVRefQual{}).error() == 5); |
236 | } |
237 | } |
238 | |
239 | // Test const&& overload |
240 | { |
241 | // Without & qualifier on F's operator() |
242 | { |
243 | const std::expected<int, int> e{0}; |
244 | std::same_as<std::expected<int, int>> decltype(auto) val = std::move(e).and_then(CRVal{}); |
245 | assert(val == 1); |
246 | assert(std::move(e).and_then(UnexpectedCRVal{}).error() == 5); |
247 | } |
248 | |
249 | // With & qualifier on F's operator() |
250 | { |
251 | const std::expected<int, int> e{0}; |
252 | const RVCRefQual l{}; |
253 | std::same_as<std::expected<int, int>> decltype(auto) val = std::move(e).and_then(std::move(l)); |
254 | assert(val == 1); |
255 | const UnexpectedRVCRefQual nl{}; |
256 | assert(std::move(e).and_then(std::move(nl)).error() == 5); |
257 | } |
258 | } |
259 | } |
260 | // clang-format on |
261 | |
262 | // check that the lambda body is not instantiated during overload resolution |
263 | constexpr void test_sfinae() { |
264 | std::expected<NonConst, int> e(std::unexpected<int>(2)); |
265 | auto l = [](auto&& x) { return x.non_const(); }; |
266 | e.and_then(l); |
267 | std::move(e).and_then(l); |
268 | } |
269 | |
270 | constexpr void test_move_only_error_type() { |
271 | // Test && |
272 | { |
273 | std::expected<int, MoveOnlyErrorType> e; |
274 | auto l = [](int) { return std::expected<int, MoveOnlyErrorType>{}; }; |
275 | std::move(e).and_then(l); |
276 | } |
277 | |
278 | // Test const&& |
279 | { |
280 | const std::expected<int, MoveOnlyErrorType> e; |
281 | auto l = [](const int) { return std::expected<int, MoveOnlyErrorType>{}; }; |
282 | std::move(e).and_then(l); |
283 | } |
284 | } |
285 | |
286 | constexpr bool test() { |
287 | test_sfinae(); |
288 | test_val_types(); |
289 | test_move_only_error_type(); |
290 | |
291 | std::expected<int, int> e(std::unexpected<int>(1)); |
292 | const auto& ce = e; |
293 | |
294 | const auto never_called = [](int) { |
295 | assert(false); |
296 | return std::expected<int, int>(); |
297 | }; |
298 | |
299 | e.and_then(never_called); |
300 | std::move(e).and_then(never_called); |
301 | ce.and_then(never_called); |
302 | std::move(ce).and_then(never_called); |
303 | |
304 | return true; |
305 | } |
306 | |
307 | int main(int, char**) { |
308 | test(); |
309 | static_assert(test()); |
310 | |
311 | return 0; |
312 | } |
313 | |