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