xref: /llvm-project/libcxx/test/std/utilities/expected/expected.expected/monadic/transform.pass.cpp (revision cb4433b677a06ecbb3112f39d24b28f19b0d2626)
1acce2a31Syronglin //===----------------------------------------------------------------------===//
2acce2a31Syronglin //
3acce2a31Syronglin // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4acce2a31Syronglin // See https://llvm.org/LICENSE.txt for license information.
5acce2a31Syronglin // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6acce2a31Syronglin //
7acce2a31Syronglin //===----------------------------------------------------------------------===//
8acce2a31Syronglin 
9acce2a31Syronglin // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
10acce2a31Syronglin 
11acce2a31Syronglin // GCC has a issue for `Guaranteed copy elision for potentially-overlapping non-static data members`,
124f469053SJan Kokemüller // please refer to: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108333
139e940438SNikolas Klauser // XFAIL: gcc-14
14acce2a31Syronglin 
15acce2a31Syronglin // <expected>
16acce2a31Syronglin 
17acce2a31Syronglin // template<class F> constexpr auto transform(F&& f) &;
18acce2a31Syronglin // template<class F> constexpr auto transform(F&& f) const &;
19acce2a31Syronglin // template<class F> constexpr auto transform(F&& f) &&;
20acce2a31Syronglin // template<class F> constexpr auto transform(F&& f) const &&;
21acce2a31Syronglin 
22acce2a31Syronglin #include <expected>
23acce2a31Syronglin #include <concepts>
24acce2a31Syronglin #include <cassert>
25acce2a31Syronglin #include <memory>
26acce2a31Syronglin #include <type_traits>
27acce2a31Syronglin #include <utility>
28acce2a31Syronglin 
299f67143bSyronglin #include "../../types.h"
309f67143bSyronglin 
31acce2a31Syronglin struct LVal {
32acce2a31Syronglin   constexpr int operator()(int&) { return 1; }
33acce2a31Syronglin   int operator()(const int&)  = delete;
34acce2a31Syronglin   int operator()(int&&)       = delete;
35acce2a31Syronglin   int operator()(const int&&) = delete;
36acce2a31Syronglin };
37acce2a31Syronglin 
38acce2a31Syronglin struct CLVal {
39acce2a31Syronglin   int operator()(int&) = delete;
40acce2a31Syronglin   constexpr int operator()(const int&) { return 1; }
41acce2a31Syronglin   int operator()(int&&)       = delete;
42acce2a31Syronglin   int operator()(const int&&) = delete;
43acce2a31Syronglin };
44acce2a31Syronglin 
45acce2a31Syronglin struct RVal {
46acce2a31Syronglin   int operator()(int&)       = delete;
47acce2a31Syronglin   int operator()(const int&) = delete;
48acce2a31Syronglin   constexpr int operator()(int&&) { return 1; }
49acce2a31Syronglin   int operator()(const int&&) = delete;
50acce2a31Syronglin };
51acce2a31Syronglin 
52acce2a31Syronglin struct CRVal {
53acce2a31Syronglin   int operator()(int&)       = delete;
54acce2a31Syronglin   int operator()(const int&) = delete;
55acce2a31Syronglin   int operator()(int&&)      = delete;
56acce2a31Syronglin   constexpr int operator()(const int&&) { return 1; }
57acce2a31Syronglin };
58acce2a31Syronglin 
59acce2a31Syronglin struct RefQual {
60acce2a31Syronglin   constexpr int operator()(int) & { return 1; }
61acce2a31Syronglin   int operator()(int) const&  = delete;
62acce2a31Syronglin   int operator()(int) &&      = delete;
63acce2a31Syronglin   int operator()(int) const&& = delete;
64acce2a31Syronglin };
65acce2a31Syronglin 
66acce2a31Syronglin struct CRefQual {
67acce2a31Syronglin   int operator()(int) & = delete;
68acce2a31Syronglin   constexpr int operator()(int) const& { return 1; }
69acce2a31Syronglin   int operator()(int) &&      = delete;
70acce2a31Syronglin   int operator()(int) const&& = delete;
71acce2a31Syronglin };
72acce2a31Syronglin 
73acce2a31Syronglin struct RVRefQual {
74acce2a31Syronglin   int operator()(int) &      = delete;
75acce2a31Syronglin   int operator()(int) const& = delete;
76acce2a31Syronglin   constexpr int operator()(int) && { return 1; }
77acce2a31Syronglin   int operator()(int) const&& = delete;
78acce2a31Syronglin };
79acce2a31Syronglin 
80acce2a31Syronglin struct RVCRefQual {
81acce2a31Syronglin   int operator()(int) &      = delete;
82acce2a31Syronglin   int operator()(int) const& = delete;
83acce2a31Syronglin   int operator()(int) &&     = delete;
84acce2a31Syronglin   constexpr int operator()(int) const&& { return 1; }
85acce2a31Syronglin };
86acce2a31Syronglin 
87acce2a31Syronglin struct NonCopy {
88acce2a31Syronglin   int value;
89acce2a31Syronglin   constexpr explicit NonCopy(int val) : value(val) {}
90acce2a31Syronglin   NonCopy(const NonCopy&) = delete;
91acce2a31Syronglin };
92acce2a31Syronglin 
93acce2a31Syronglin struct NonConst {
94acce2a31Syronglin   int non_const() { return 1; }
95acce2a31Syronglin };
96acce2a31Syronglin 
97acce2a31Syronglin template <class E, class F>
98acce2a31Syronglin concept has_transform =
99acce2a31Syronglin     requires(E&& e, F&& f) {
100acce2a31Syronglin       { std::forward<E>(e).transform(std::forward<F>(f)) };
101acce2a31Syronglin     };
102acce2a31Syronglin 
1039f67143bSyronglin // clang-format off
104acce2a31Syronglin // [LWG 3877] https://cplusplus.github.io/LWG/issue3877, check constraint failing but not compile error inside the function body.
105acce2a31Syronglin static_assert(!has_transform<const std::expected<int, std::unique_ptr<int>>&, int()>);
106acce2a31Syronglin static_assert(!has_transform<const std::expected<int, std::unique_ptr<int>>&&, int()>);
107acce2a31Syronglin 
1089f67143bSyronglin // [LWG 3983] https://cplusplus.github.io/LWG/issue3938, check std::expected monadic ops well-formed with move-only error_type.
1099f67143bSyronglin // There are no effects for `&` and `const &` overload, because the constraints requires is_constructible_v<E, decltype(error())> is true.
1109f67143bSyronglin static_assert(has_transform<std::expected<int, MoveOnlyErrorType>&&, int(int)>);
1119f67143bSyronglin static_assert(has_transform<const std::expected<int, MoveOnlyErrorType>&&, int(const int)>);
1129f67143bSyronglin 
113acce2a31Syronglin constexpr void test_val_types() {
114acce2a31Syronglin   // Test & overload
115acce2a31Syronglin   {
116acce2a31Syronglin     // Without & qualifier on F's operator()
117acce2a31Syronglin     {
118acce2a31Syronglin       std::expected<int, int> e(0);
119acce2a31Syronglin       std::same_as<std::expected<int, int>> decltype(auto) val = e.transform(LVal{});
120acce2a31Syronglin       assert(val == 1);
121acce2a31Syronglin     }
122acce2a31Syronglin 
123acce2a31Syronglin     // With & qualifier on F's operator()
124acce2a31Syronglin     {
125acce2a31Syronglin       std::expected<int, int> e(0);
126acce2a31Syronglin       RefQual l{};
127acce2a31Syronglin       std::same_as<std::expected<int, int>> decltype(auto) val = e.transform(l);
128acce2a31Syronglin       assert(val == 1);
129acce2a31Syronglin     }
130acce2a31Syronglin   }
131acce2a31Syronglin 
132acce2a31Syronglin   // Test const& overload
133acce2a31Syronglin   {
134acce2a31Syronglin     // Without & qualifier on F's operator()
135acce2a31Syronglin     {
136acce2a31Syronglin       const std::expected<int, int> e(0);
137acce2a31Syronglin       std::same_as<std::expected<int, int>> decltype(auto) val = e.transform(CLVal{});
138acce2a31Syronglin       assert(val == 1);
139acce2a31Syronglin     }
140acce2a31Syronglin 
141acce2a31Syronglin     // With & qualifier on F's operator()
142acce2a31Syronglin     {
143acce2a31Syronglin       const std::expected<int, int> e(0);
144acce2a31Syronglin       const CRefQual l{};
145acce2a31Syronglin       std::same_as<std::expected<int, int>> decltype(auto) val = e.transform(l);
146acce2a31Syronglin       assert(val == 1);
147acce2a31Syronglin     }
148acce2a31Syronglin   }
149acce2a31Syronglin 
150acce2a31Syronglin   // Test && overload
151acce2a31Syronglin   {
152acce2a31Syronglin     // Without & qualifier on F's operator()
153acce2a31Syronglin     {
154acce2a31Syronglin       std::expected<int, int> e(0);
155acce2a31Syronglin       std::same_as<std::expected<int, int>> decltype(auto) val = std::move(e).transform(RVal{});
156acce2a31Syronglin       assert(val == 1);
157acce2a31Syronglin     }
158acce2a31Syronglin 
159acce2a31Syronglin     // With & qualifier on F's operator()
160acce2a31Syronglin     {
161acce2a31Syronglin       std::expected<int, int> e(0);
162acce2a31Syronglin       std::same_as<std::expected<int, int>> decltype(auto) val = std::move(e).transform(RVRefQual{});
163acce2a31Syronglin       assert(val == 1);
164acce2a31Syronglin     }
165acce2a31Syronglin   }
166acce2a31Syronglin 
167acce2a31Syronglin   // Test const&& overload
168acce2a31Syronglin   {
169acce2a31Syronglin     // Without & qualifier on F's operator()
170acce2a31Syronglin     {
171acce2a31Syronglin       const std::expected<int, int> e(0);
172acce2a31Syronglin       std::same_as<std::expected<int, int>> decltype(auto) val = std::move(e).transform(CRVal{});
173acce2a31Syronglin       assert(val == 1);
174acce2a31Syronglin     }
175acce2a31Syronglin 
176acce2a31Syronglin     // With & qualifier on F's operator()
177acce2a31Syronglin     {
178acce2a31Syronglin       const std::expected<int, int> e(0);
179acce2a31Syronglin       const RVCRefQual l{};
180acce2a31Syronglin       std::same_as<std::expected<int, int>> decltype(auto) val = e.transform(std::move(l));
181acce2a31Syronglin       assert(val == 1);
182acce2a31Syronglin     }
183acce2a31Syronglin   }
184acce2a31Syronglin }
185acce2a31Syronglin // clang-format on
186acce2a31Syronglin 
187acce2a31Syronglin constexpr void test_take_val_return_void() {
188acce2a31Syronglin   std::expected<int, int> e(1);
189acce2a31Syronglin   int val = 0;
190*cb4433b6SStephan T. Lavavej   (void)e.transform([&val]<typename T>(T&&) -> void {
191acce2a31Syronglin     static_assert(std::is_same_v<T, int&>);
192acce2a31Syronglin     assert(val == 0);
193acce2a31Syronglin     val = 1;
194acce2a31Syronglin   });
195acce2a31Syronglin   assert(val == 1);
196*cb4433b6SStephan T. Lavavej   (void)std::move(e).transform([&val]<typename T>(T&&) -> void {
197acce2a31Syronglin     static_assert(std::is_same_v<T, int>);
198acce2a31Syronglin     assert(val == 1);
199acce2a31Syronglin     val = 2;
200acce2a31Syronglin   });
201acce2a31Syronglin 
202acce2a31Syronglin   const auto& ce = e;
203acce2a31Syronglin   assert(val == 2);
204*cb4433b6SStephan T. Lavavej   (void)ce.transform([&val]<typename T>(T&&) -> void {
205acce2a31Syronglin     static_assert(std::is_same_v<T, const int&>);
206acce2a31Syronglin     assert(val == 2);
207acce2a31Syronglin     val = 3;
208acce2a31Syronglin   });
209acce2a31Syronglin   assert(val == 3);
210*cb4433b6SStephan T. Lavavej   (void)std::move(ce).transform([&val]<typename T>(T&&) -> void {
211acce2a31Syronglin     static_assert(std::is_same_v<T, const int>);
212acce2a31Syronglin     assert(val == 3);
213acce2a31Syronglin     val = 4;
214acce2a31Syronglin   });
215acce2a31Syronglin   assert(val == 4);
216acce2a31Syronglin }
217acce2a31Syronglin 
218acce2a31Syronglin // check val member is direct-non-list-initialized with invoke(std::forward<F>(f), value())
219acce2a31Syronglin constexpr void test_direct_non_list_init() {
220acce2a31Syronglin   auto xform = [](int i) { return NonCopy(i); };
221acce2a31Syronglin   std::expected<int, int> e(2);
222acce2a31Syronglin   std::expected<NonCopy, int> n = e.transform(xform);
223acce2a31Syronglin   assert(n.value().value == 2);
224acce2a31Syronglin }
225acce2a31Syronglin 
226acce2a31Syronglin // check that the lambda body is not instantiated during overload resolution
227acce2a31Syronglin constexpr void test_sfinae() {
228acce2a31Syronglin   std::expected<NonConst, int> e(std::unexpected<int>(2));
229acce2a31Syronglin   auto l = [](auto&& x) { return x.non_const(); };
230*cb4433b6SStephan T. Lavavej   (void)e.transform(l);
231*cb4433b6SStephan T. Lavavej   (void)std::move(e).transform(l);
232acce2a31Syronglin 
233acce2a31Syronglin   std::expected<int, int> e1(std::unexpected<int>(1));
234acce2a31Syronglin   const auto& ce1         = e1;
235acce2a31Syronglin   const auto never_called = [](int) {
236acce2a31Syronglin     assert(false);
237acce2a31Syronglin     return std::expected<int, int>();
238acce2a31Syronglin   };
239acce2a31Syronglin 
240*cb4433b6SStephan T. Lavavej   (void)e1.transform(never_called);
241*cb4433b6SStephan T. Lavavej   (void)std::move(e1).transform(never_called);
242*cb4433b6SStephan T. Lavavej   (void)ce1.transform(never_called);
243*cb4433b6SStephan T. Lavavej   (void)std::move(ce1).transform(never_called);
244acce2a31Syronglin }
245acce2a31Syronglin 
2469f67143bSyronglin constexpr void test_move_only_error_type() {
2479f67143bSyronglin   // Test &&
2489f67143bSyronglin   {
2499f67143bSyronglin       std::expected<int, MoveOnlyErrorType> e;
2509f67143bSyronglin       auto l = [](int) { return 0; };
251*cb4433b6SStephan T. Lavavej       (void)std::move(e).transform(l);
2529f67143bSyronglin   }
2539f67143bSyronglin 
2549f67143bSyronglin   // Test const&&
2559f67143bSyronglin   {
2569f67143bSyronglin       const std::expected<int, MoveOnlyErrorType> e;
2579f67143bSyronglin       auto l = [](const int) { return 0; };
258*cb4433b6SStephan T. Lavavej       (void)std::move(e).transform(l);
2599f67143bSyronglin   }
2609f67143bSyronglin }
2619f67143bSyronglin 
262acce2a31Syronglin constexpr bool test() {
263acce2a31Syronglin   test_sfinae();
264acce2a31Syronglin   test_val_types();
265acce2a31Syronglin   test_direct_non_list_init();
2669f67143bSyronglin   test_move_only_error_type();
267acce2a31Syronglin   return true;
268acce2a31Syronglin }
269acce2a31Syronglin 
270acce2a31Syronglin int main(int, char**) {
271acce2a31Syronglin   test();
272acce2a31Syronglin   static_assert(test());
273acce2a31Syronglin 
274acce2a31Syronglin   return 0;
275acce2a31Syronglin }
276