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 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 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 115 constexpr bool test() { 116 test_fail(); 117 test_val_types(); 118 return true; 119 } 120 121 int main(int, char**) { 122 test(); 123 static_assert(test()); 124 125 return 0; 126 } 127