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 transform_error(F&& f) &;
14 // template<class F> constexpr auto transform_error(F&& f) const &;
15 // template<class F> constexpr auto transform_error(F&& f) &&;
16 // template<class F> constexpr auto transform_error(F&& f) const &&;
17
18 #include <expected>
19 #include <concepts>
20 #include <cassert>
21 #include <memory>
22 #include <type_traits>
23 #include <utility>
24
25 template <class E, class F>
26 concept has_transform =
27 requires(E&& e, F&& f) {
28 { std::forward<E>(e).transform(std::forward<F>(f)) };
29 };
30
31 // [LWG 3877] https://cplusplus.github.io/LWG/issue3877, check constraint failing but not compile error inside the function body.
32 static_assert(!has_transform<const std::expected<int, std::unique_ptr<int>>&, int()>);
33 static_assert(!has_transform<const std::expected<int, std::unique_ptr<int>>&&, int()>);
34
test_val_types()35 constexpr void test_val_types() {
36 // Test & overload
37 {
38 auto l = []() -> int { return 1; };
39 std::expected<void, int> v;
40 std::same_as<std::expected<int, int>> decltype(auto) val = v.transform(l);
41 assert(val == 1);
42 }
43
44 // Test const& overload
45 {
46 auto l = []() -> int { return 1; };
47 const std::expected<void, int> v;
48 std::same_as<std::expected<int, int>> decltype(auto) val = v.transform(l);
49 assert(val == 1);
50 }
51
52 // Test && overload
53 {
54 auto l = []() -> int { return 1; };
55 std::expected<void, int> v;
56 std::same_as<std::expected<int, int>> decltype(auto) val = std::move(v).transform(l);
57 assert(val == 1);
58 }
59
60 // Test const&& overload
61 {
62 auto l = []() -> int { return 1; };
63 const std::expected<void, int> v;
64 std::same_as<std::expected<int, int>> decltype(auto) val = std::move(v).transform(l);
65 assert(val == 1);
66 }
67 }
68
test_fail()69 constexpr void test_fail() {
70 // Test & overload
71 {
72 auto l = []() -> int {
73 assert(false);
74 return 0;
75 };
76 std::expected<void, int> v(std::unexpected<int>(5));
77 std::same_as<std::expected<int, int>> decltype(auto) val = v.transform(l);
78 assert(val.error() == 5);
79 }
80
81 // Test const& overload
82 {
83 auto l = []() -> int {
84 assert(false);
85 return 0;
86 };
87 const std::expected<void, int> v(std::unexpected<int>(5));
88 std::same_as<std::expected<int, int>> decltype(auto) val = v.transform(l);
89 assert(val.error() == 5);
90 }
91
92 // Test && overload
93 {
94 auto l = []() -> int {
95 assert(false);
96 return 0;
97 };
98 std::expected<void, int> v(std::unexpected<int>(5));
99 std::same_as<std::expected<int, int>> decltype(auto) val = std::move(v).transform(l);
100 assert(val.error() == 5);
101 }
102
103 // Test const&& overload
104 {
105 auto l = []() -> int {
106 assert(false);
107 return 0;
108 };
109 const std::expected<void, int> v(std::unexpected<int>(5));
110 std::same_as<std::expected<int, int>> decltype(auto) val = std::move(v).transform(l);
111 assert(val.error() == 5);
112 }
113 }
114
test()115 constexpr bool test() {
116 test_fail();
117 test_val_types();
118 return true;
119 }
120
main(int,char **)121 int main(int, char**) {
122 test();
123 static_assert(test());
124
125 return 0;
126 }
127