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// GCC has a issue for `Guaranteed copy elision for potentially-overlapping non-static data members`,
12// please refer to: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108333
13// XFAIL: gcc-13
14
15// <expected>
16
17// template<class F> constexpr auto transform_error(F&& f) &;
18// template<class F> constexpr auto transform_error(F&& f) const &;
19// template<class F> constexpr auto transform_error(F&& f) &&;
20// template<class F> constexpr auto transform_error(F&& f) const &&;
21
22#include <expected>
23#include <concepts>
24#include <cassert>
25#include <type_traits>
26#include <utility>
27
28struct NonCopy {
29 int value;
30 constexpr explicit NonCopy(int val) : value(val) {}
31 NonCopy(const NonCopy&) = delete;
32};
33
34constexpr void test_val_types() {
35 // Test & overload
36 {
37 auto l = [](auto) -> int { return 1; };
38 std::expected<void, int> v(std::unexpected<int>(2));
39 std::same_as<std::expected<void, int>> decltype(auto) val = v.transform_error(l);
40 assert(val.error() == 1);
41 }
42
43 // Test const& overload
44 {
45 auto l = [](auto) -> int { return 1; };
46 const std::expected<void, int> v(std::unexpected<int>(2));
47 std::same_as<std::expected<void, int>> decltype(auto) val = v.transform_error(l);
48 assert(val.error() == 1);
49 }
50
51 // Test && overload
52 {
53 auto l = [](auto) -> int { return 1; };
54 std::expected<void, int> v(std::unexpected<int>(2));
55 std::same_as<std::expected<void, int>> decltype(auto) val = std::move(v).transform_error(l);
56 assert(val.error() == 1);
57 }
58
59 // Test const&& overload
60 {
61 auto l = [](auto) -> int { return 1; };
62 const std::expected<void, int> v(std::unexpected<int>(2));
63 std::same_as<std::expected<void, int>> decltype(auto) val = std::move(v).transform_error(l);
64 assert(val.error() == 1);
65 }
66}
67
68constexpr void test_fail() {
69 // Test & overload
70 {
71 auto l = [](auto) -> int {
72 assert(false);
73 return 0;
74 };
75 std::expected<void, int> v;
76 std::same_as<std::expected<void, int>> decltype(auto) val = v.transform_error(l);
77 assert(val.has_value());
78 }
79
80 // Test const& overload
81 {
82 auto l = [](auto) -> int {
83 assert(false);
84 return 0;
85 };
86 const std::expected<void, int> v;
87 std::same_as<std::expected<void, int>> decltype(auto) val = v.transform_error(l);
88 assert(val.has_value());
89 }
90
91 // Test && overload
92 {
93 auto l = [](auto) -> int {
94 assert(false);
95 return 0;
96 };
97 std::expected<void, int> v;
98 std::same_as<std::expected<void, int>> decltype(auto) val = std::move(v).transform_error(l);
99 assert(val.has_value());
100 }
101
102 // Test const&& overload
103 {
104 auto l = [](auto) -> int {
105 assert(false);
106 return 0;
107 };
108 const std::expected<void, int> v;
109 std::same_as<std::expected<void, int>> decltype(auto) val = std::move(v).transform_error(l);
110 assert(val.has_value());
111 }
112}
113
114// check unex member is direct-non-list-initialized with invoke(std::forward<F>(f))
115constexpr void test_direct_non_list_init() {
116 auto x = [](int i) { return NonCopy(i); };
117 std::expected<void, int> v(std::unexpected<int>(2));
118 std::expected<void, NonCopy> nv = v.transform_error(x);
119 assert(nv.error().value == 2);
120}
121
122constexpr bool test() {
123 test_fail();
124 test_val_types();
125 test_direct_non_list_init();
126 return true;
127}
128
129int main(int, char**) {
130 test();
131 static_assert(test());
132
133 return 0;
134}
135

source code of libcxx/test/std/utilities/expected/expected.void/monadic/transform_error.pass.cpp