xref: /llvm-project/libcxx/test/std/utilities/expected/expected.expected/monadic/or_else.pass.cpp (revision cb4433b677a06ecbb3112f39d24b28f19b0d2626)
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 or_else(F&& f) &;
14 // template<class F> constexpr auto or_else(F&& f) const &;
15 // template<class F> constexpr auto or_else(F&& f) &&;
16 // template<class F> constexpr auto or_else(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 template <class E, class F>
84 concept has_or_else =
85     requires(E&& e, F&& f) {
86       { std::forward<E>(e).or_else(std::forward<F>(f)) };
87     };
88 // clang-format off
89 // [LWG 3877] https://cplusplus.github.io/LWG/issue3877, check constraint failing but not compile error inside the function body.
90 static_assert(!has_or_else<const std::expected<std::unique_ptr<int>, int>&, int()>);
91 static_assert(!has_or_else<const std::expected<std::unique_ptr<int>, int>&&, int()>);
92 
93 // [LWG 3983] https://cplusplus.github.io/LWG/issue3938, check std::expected monadic ops well-formed with move-only error_type.
94 static_assert(has_or_else<std::expected<int, MoveOnlyErrorType>&, std::expected<int, int>(MoveOnlyErrorType &)>);
95 static_assert(has_or_else<const std::expected<int, MoveOnlyErrorType>&, std::expected<int, int>(const MoveOnlyErrorType &)>);
96 static_assert(has_or_else<std::expected<int, MoveOnlyErrorType>&&, std::expected<int, int>(MoveOnlyErrorType&&)>);
97 static_assert(has_or_else<const std::expected<int, MoveOnlyErrorType>&&, std::expected<int, int>(const MoveOnlyErrorType&&)>);
98 
99 constexpr void test_val_types() {
100   // Test & overload
101   {
102     // Without & qualifier on F's operator()
103     {
104       std::expected<int, int> e(std::unexpected<int>(0));
105       std::same_as<std::expected<int, int>> decltype(auto) val = e.or_else(LVal{});
106       assert(val == 1);
107     }
108 
109     // With & qualifier on F's operator
110     {
111       std::expected<int, int> e(std::unexpected<int>(0));
112       RefQual l{};
113       std::same_as<std::expected<int, int>> decltype(auto) val = e.or_else(l);
114       assert(val == 1);
115     }
116   }
117 
118   // Test const& overload
119   {
120     // Without const& qualifier on F's operator()
121     {
122       const std::expected<int, int> e(std::unexpected<int>(0));
123       std::same_as<std::expected<int, int>> decltype(auto) val = e.or_else(CLVal{});
124       assert(val == 1);
125     }
126 
127     // With const& qualifier on F's operator()
128     {
129       const std::expected<int, int> e(std::unexpected<int>(0));
130       const CRefQual l{};
131       std::same_as<std::expected<int, int>> decltype(auto) val = e.or_else(l);
132       assert(val == 1);
133     }
134   }
135 
136   // Test && overload
137   {
138     // Without && qualifier on F's operator()
139     {
140       std::expected<int, int> e(std::unexpected<int>(0));
141       std::same_as<std::expected<int, int>> decltype(auto) val = std::move(e).or_else(RVal{});
142       assert(val == 1);
143     }
144 
145     // With && qualifier on F's operator()
146     {
147       std::expected<int, int> e(std::unexpected<int>(0));
148       std::same_as<std::expected<int, int>> decltype(auto) val = std::move(e).or_else(RVRefQual{});
149       assert(val == 1);
150     }
151   }
152 
153   // Test const&& overload
154   {
155     // Without const&& qualifier on F's operator()
156     {
157       const std::expected<int, int> e(std::unexpected<int>(0));
158       std::same_as<std::expected<int, int>> decltype(auto) val = std::move(e).or_else(CRVal{});
159       assert(val == 1);
160     }
161 
162     // With const&& qualifier on F's operator()
163     {
164       const std::expected<int, int> e(std::unexpected<int>(0));
165       const RVCRefQual l{};
166       std::same_as<std::expected<int, int>> decltype(auto) val = std::move(e).or_else(std::move(l));
167       assert(val == 1);
168     }
169   }
170 }
171 // clang-format on
172 
173 struct NonConst {
174   std::expected<int, int> non_const() { return std::expected<int, int>(std::unexpect, 1); }
175 };
176 
177 // check that the lambda body is not instantiated during overload resolution
178 constexpr void test_sfinae() {
179   std::expected<int, NonConst> e{1};
180   auto l = [](auto&& x) { return x.non_const(); };
181   (void)e.or_else(l);
182   (void)std::move(e).or_else(l);
183 }
184 
185 constexpr void test_move_only_error_type() {
186   // Test &
187   {
188       std::expected<int, MoveOnlyErrorType> e;
189       auto l = [](MoveOnlyErrorType&) { return std::expected<int, int>{}; };
190       (void)e.or_else(l);
191   }
192 
193   // Test const&
194   {
195       const std::expected<int, MoveOnlyErrorType> e;
196       auto l = [](const MoveOnlyErrorType&) { return std::expected<int, int>{}; };
197       (void)e.or_else(l);
198   }
199 
200   // Test &&
201   {
202       std::expected<int, MoveOnlyErrorType> e;
203       auto l = [](MoveOnlyErrorType&&) { return std::expected<int, int>{}; };
204       (void)std::move(e).or_else(l);
205   }
206 
207   // Test const&&
208   {
209       const std::expected<int, MoveOnlyErrorType> e;
210       auto l = [](const MoveOnlyErrorType&&) { return std::expected<int, int>{}; };
211       (void)std::move(e).or_else(l);
212   }
213 }
214 
215 constexpr bool test() {
216   test_sfinae();
217   test_val_types();
218   test_move_only_error_type();
219 
220   std::expected<int, int> e(1);
221   const auto& ce = e;
222 
223   const auto never_called = [](int) {
224     assert(false);
225     return std::expected<int, int>();
226   };
227 
228   (void)e.or_else(never_called);
229   (void)std::move(e).or_else(never_called);
230   (void)ce.or_else(never_called);
231   (void)std::move(ce).or_else(never_called);
232   return true;
233 }
234 
235 int main(int, char**) {
236   test();
237   static_assert(test());
238 
239   return 0;
240 }
241