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