1 // Copyright 2023 The Pigweed Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 // use this file except in compliance with the License. You may obtain a copy of 5 // the License at 6 // 7 // https://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 // License for the specific language governing permissions and limitations under 13 // the License. 14 #pragma once 15 16 #include <cstdlib> 17 #include <functional> 18 #include <optional> 19 #include <type_traits> 20 #include <utility> 21 #include <variant> 22 23 namespace pw::internal { 24 25 // Helper type trait for removing reference and cv-qualification of a type. 26 template <class T> 27 struct remove_cvref { 28 typedef std::remove_cv_t<std::remove_reference_t<T>> type; 29 }; 30 31 // Helper type trait ::type of above struct. 32 template <class T> 33 using remove_cvref_t = typename remove_cvref<T>::type; 34 35 // Helper type trait for enabling/disabling std::expected constructors. 36 template <class T, class W> 37 constexpr bool converts_from_any_cvref = 38 std::disjunction_v<std::is_constructible<T, W&>, 39 std::is_convertible<W&, T>, 40 std::is_constructible<T, W>, 41 std::is_convertible<W, T>, 42 std::is_constructible<T, const W&>, 43 std::is_convertible<const W&, T>, 44 std::is_constructible<T, const W>, 45 std::is_convertible<const W, T>>; 46 47 // Helper type trait for determining if a type is any specialization of a 48 // template class. 49 template <typename T, template <typename...> class Template> 50 constexpr bool is_specialization = false; 51 template <template <typename...> class Template, typename... Ts> 52 constexpr bool is_specialization<Template<Ts...>, Template> = true; 53 54 // Polyfill implementaion of std::unexpected. 55 56 template <class E> 57 class unexpected { 58 public: 59 constexpr unexpected(const unexpected&) = default; 60 constexpr unexpected(unexpected&&) = default; 61 template <class Err = E, 62 std::enable_if_t< 63 !std::is_same_v<remove_cvref_t<Err>, unexpected> && 64 !std::is_same_v<remove_cvref_t<Err>, std::in_place_t> && 65 std::is_constructible_v<E, Err>, 66 bool> = true> unexpected(Err && e)67 constexpr explicit unexpected(Err&& e) : unex_(std::forward<Err>(e)) {} 68 template <class... Args, 69 std::enable_if_t<std::is_constructible_v<E, Args...>, bool> = true> unexpected(std::in_place_t,Args &&...args)70 constexpr explicit unexpected(std::in_place_t, Args&&... args) 71 : unex_(std::forward<Args>(args)...) {} 72 template < 73 class U, 74 class... Args, 75 std::enable_if_t<std::is_constructible_v<E, std::initializer_list<U>>, 76 bool> = true> unexpected(std::in_place_t,std::initializer_list<U> il,Args &&...args)77 constexpr explicit unexpected(std::in_place_t, 78 std::initializer_list<U> il, 79 Args&&... args) 80 : unex_(il, std::forward<Args>(args)...) {} 81 82 constexpr unexpected& operator=(const unexpected&) = default; 83 constexpr unexpected& operator=(unexpected&&) = default; 84 error()85 constexpr const E& error() const& noexcept { return unex_; } error()86 constexpr E& error() & noexcept { return unex_; } error()87 constexpr E&& error() && noexcept { return std::move(unex_); } error()88 constexpr const E&& error() const&& noexcept { return std::move(unex_); } 89 swap(unexpected & other)90 constexpr void swap(unexpected& other) noexcept( 91 std::is_nothrow_swappable<E>::value) { 92 std::swap(unex_, other.unex_); 93 } 94 95 template <class E2> 96 friend constexpr bool operator==(const unexpected& x, 97 const unexpected<E2>& y) { 98 return x.error() == y.error(); 99 } 100 101 private: 102 E unex_; 103 }; 104 105 template <class E> 106 unexpected(E) -> unexpected<E>; 107 108 // Polyfill implementation of std::unexpect_t and std::unexpect. 109 struct unexpect_t { 110 explicit unexpect_t() = default; 111 }; 112 113 inline constexpr unexpect_t unexpect; 114 115 template <class T, class E, typename Enable = void> 116 class expected; 117 118 // Polyfill implementation of std::expected. 119 template <class T, class E> 120 class expected<T, E, std::enable_if_t<!std::is_void_v<T>>> { 121 public: 122 using value_type = T; 123 using error_type = E; 124 using unexpected_type = unexpected<E>; 125 126 template <class U> 127 using rebind = expected<U, error_type>; 128 129 template < 130 class Enable = T, 131 std::enable_if_t<std::is_default_constructible_v<Enable>, bool> = true> expected()132 constexpr expected() : contents_(kInPlaceValue) {} 133 constexpr expected(const expected& rhs) = default; 134 constexpr expected(expected&& rhs) = default; 135 template < 136 class U, 137 class G, 138 // Constraints 139 std::enable_if_t< 140 std::is_constructible_v<T, const U&> && 141 std::is_constructible_v<E, const G&> && 142 !converts_from_any_cvref<T, expected<U, G>> && 143 !std::is_constructible_v<unexpected<E>, expected<U, G>&> && 144 !std::is_constructible_v<unexpected<E>, expected<U, G>> && 145 !std::is_constructible_v<unexpected<E>, const expected<U, G>&> && 146 !std::is_constructible_v<unexpected<E>, const expected<U, G>>, 147 bool> = true, 148 // Explicit 149 std::enable_if_t<!std::is_convertible_v<const U&, T> || 150 !std::is_convertible_v<const G&, E>, 151 bool> = true> expected(const expected<U,G> & rhs)152 constexpr explicit expected(const expected<U, G>& rhs) 153 : contents_(convert_variant( 154 std::forward<const std::variant<U, G>&>(rhs.contents_))) {} 155 template < 156 class U, 157 class G, 158 // Constraints 159 std::enable_if_t< 160 std::is_constructible_v<T, const U&> && 161 std::is_constructible_v<E, const G&> && 162 !converts_from_any_cvref<T, expected<U, G>> && 163 !std::is_constructible_v<unexpected<E>, expected<U, G>&> && 164 !std::is_constructible_v<unexpected<E>, expected<U, G>> && 165 !std::is_constructible_v<unexpected<E>, const expected<U, G>&> && 166 !std::is_constructible_v<unexpected<E>, const expected<U, G>>, 167 bool> = true, 168 // Explicit 169 std::enable_if_t<std::is_convertible_v<const U&, T> && 170 std::is_convertible_v<const G&, E>, 171 bool> = true> expected(const expected<U,G> & rhs)172 constexpr /* implicit */ expected(const expected<U, G>& rhs) 173 : contents_(convert_variant( 174 std::forward<const std::variant<U, G>&>(rhs.contents_))) {} 175 template < 176 class U, 177 class G, 178 // Constraints 179 std::enable_if_t< 180 std::is_constructible_v<T, U&&> && std::is_constructible_v<E, G&&> && 181 !converts_from_any_cvref<T, expected<U, G>> && 182 !std::is_constructible_v<unexpected<E>, expected<U, G>&> && 183 !std::is_constructible_v<unexpected<E>, expected<U, G>> && 184 !std::is_constructible_v<unexpected<E>, const expected<U, G>&> && 185 !std::is_constructible_v<unexpected<E>, const expected<U, G>>, 186 bool> = true, 187 // Explicit 188 std::enable_if_t<!std::is_convertible_v<U&&, T> || 189 !std::is_convertible_v<G&&, E>, 190 bool> = true> expected(expected<U,G> && rhs)191 constexpr explicit expected(expected<U, G>&& rhs) 192 : contents_( 193 std::forward<std::variant<U, G>>(convert_variant(rhs.contents_))) {} 194 template < 195 class U, 196 class G, 197 // Constraints 198 std::enable_if_t< 199 std::is_constructible_v<T, U&&> && std::is_constructible_v<E, G&&> && 200 !converts_from_any_cvref<T, expected<U, G>> && 201 !std::is_constructible_v<unexpected<E>, expected<U, G>&> && 202 !std::is_constructible_v<unexpected<E>, expected<U, G>> && 203 !std::is_constructible_v<unexpected<E>, const expected<U, G>&> && 204 !std::is_constructible_v<unexpected<E>, const expected<U, G>>, 205 bool> = true, 206 // Explicit 207 std::enable_if_t<std::is_convertible_v<U&&, T> && 208 std::is_convertible_v<G&&, E>, 209 bool> = true> expected(expected<U,G> && rhs)210 constexpr /* implicit */ expected(expected<U, G>&& rhs) 211 : contents_( 212 convert_variant(std::forward<std::variant<U, G>>(rhs.contents_))) {} 213 template < 214 class U = T, 215 // Constraints 216 std::enable_if_t<!std::is_same_v<remove_cvref_t<U>, std::in_place_t> && 217 !std::is_same_v<remove_cvref_t<U>, expected> && 218 !is_specialization<U, unexpected> && 219 std::is_constructible_v<T, U>, 220 bool> = true, 221 // Explicit 222 std::enable_if_t<!std::is_convertible_v<U, T>, bool> = true> expected(U && u)223 constexpr explicit expected(U&& u) 224 : contents_(kInPlaceValue, std::forward<U>(u)) {} 225 template < 226 class U = T, 227 // Constraints 228 std::enable_if_t<!std::is_same_v<remove_cvref_t<U>, std::in_place_t> && 229 !std::is_same_v<remove_cvref_t<U>, expected> && 230 !is_specialization<U, unexpected> && 231 std::is_constructible_v<T, U>, 232 bool> = true, 233 // Explicit 234 std::enable_if_t<std::is_convertible_v<U, T>, bool> = true> expected(U && u)235 constexpr /* implicit */ expected(U&& u) 236 : contents_(kInPlaceValue, std::forward<U>(u)) {} 237 template <class G, 238 // Constraints 239 std::enable_if_t<std::is_constructible_v<E, const G&>, bool> = true, 240 // Explicit 241 std::enable_if_t<!std::is_convertible_v<const G&, E>, bool> = true> expected(const unexpected<G> & e)242 constexpr explicit expected(const unexpected<G>& e) 243 : contents_(kInPlaceError, std::forward<const G&>(e.error())) {} 244 template <class G, 245 // Constraints 246 std::enable_if_t<std::is_constructible_v<E, const G&>, bool> = true, 247 // Explicit 248 std::enable_if_t<std::is_convertible_v<const G&, E>, bool> = true> expected(const unexpected<G> & e)249 constexpr /* implicit */ expected(const unexpected<G>& e) 250 : contents_(kInPlaceError, std::forward<const G&>(e.error())) {} 251 template <class G, 252 // Constraints 253 std::enable_if_t<std::is_constructible_v<E, G>, bool> = true, 254 // Explicit 255 std::enable_if_t<!std::is_convertible_v<G, E>, bool> = true> expected(unexpected<G> && e)256 constexpr explicit expected(unexpected<G>&& e) 257 : contents_(kInPlaceError, std::forward<G>(e.error())) {} 258 template <class G, 259 // Constraints 260 std::enable_if_t<std::is_constructible_v<E, G>, bool> = true, 261 // Explicit 262 std::enable_if_t<std::is_convertible_v<G, E>, bool> = true> expected(unexpected<G> && e)263 constexpr /* implicit */ expected(unexpected<G>&& e) 264 : contents_(kInPlaceError, std::forward<G>(e.error())) {} 265 template <class... Args, 266 std::enable_if_t<std::is_constructible_v<T, Args...>, bool> = true> expected(std::in_place_t,Args &&...args)267 constexpr explicit expected(std::in_place_t, Args&&... args) 268 : contents_(kInPlaceValue, std::forward<Args>(args)...) {} 269 template <class U, 270 class... Args, 271 std::enable_if_t< 272 std::is_constructible_v<T, std::initializer_list<U>&, Args...>, 273 bool> = true> expected(std::in_place_t,std::initializer_list<U> il,Args &&...args)274 constexpr explicit expected(std::in_place_t, 275 std::initializer_list<U> il, 276 Args&&... args) 277 : contents_(kInPlaceValue, il, std::forward<Args>(args)...) {} 278 template <class... Args, 279 std::enable_if_t<std::is_constructible_v<E, Args...>, bool> = true> expected(unexpect_t,Args &&...args)280 constexpr explicit expected(unexpect_t, Args&&... args) 281 : contents_(kInPlaceError, std::forward<Args>(args)...) {} 282 template <class U, 283 class... Args, 284 std::enable_if_t< 285 std::is_constructible_v<E, std::initializer_list<U>&, Args...>, 286 bool> = true> expected(unexpect_t,std::initializer_list<U> il,Args &&...args)287 constexpr explicit expected(unexpect_t, 288 std::initializer_list<U> il, 289 Args&&... args) 290 : contents_(kInPlaceError, il, std::forward<Args>(args)...) {} 291 292 constexpr expected& operator=(const expected& rhs) = default; 293 constexpr expected& operator=(expected&& rhs) = default; 294 template < 295 class U = T, 296 std::enable_if_t<!std::is_same_v<expected, remove_cvref_t<U>> && 297 !is_specialization<remove_cvref_t<U>, unexpected>, 298 bool> = true> 299 constexpr expected& operator=(U&& u) { 300 value() = std::forward<U>(u); 301 } 302 template <class G> 303 constexpr expected& operator=(const unexpected<G>& e) { 304 error() = std::forward<const G&>(e.error()); 305 } 306 template <class G> 307 constexpr expected& operator=(unexpected<G>&& e) { 308 error() = std::forward<G>(e.error()); 309 } 310 311 template <class... Args, 312 std::enable_if_t<std::is_nothrow_constructible_v<T, Args...>, 313 bool> = true> emplace(Args &&...args)314 constexpr T& emplace(Args&&... args) noexcept { 315 return contents_.template emplace<kValue>(std::forward<Args>(args)...); 316 } 317 template < 318 class U, 319 class... Args, 320 std::enable_if_t< 321 std::is_nothrow_constructible_v<T, std::initializer_list<U>, Args...>, 322 bool> = true> emplace(std::initializer_list<U> il,Args &&...args)323 constexpr T& emplace(std::initializer_list<U> il, Args&&... args) noexcept { 324 return contents_.template emplace<kValue>(il, std::forward<Args>(args)...); 325 } 326 swap(expected & rhs)327 constexpr void swap(expected& rhs) { std::swap(contents_, rhs.contents_); } 328 329 constexpr T* operator->() noexcept { return std::addressof(value()); } 330 constexpr const T* operator->() const noexcept { 331 return std::addressof(value()); 332 } 333 constexpr T& operator*() & noexcept { return value(); } 334 constexpr T&& operator*() && noexcept { return std::move(value()); } 335 constexpr const T& operator*() const& noexcept { return value(); } 336 constexpr const T&& operator*() const&& noexcept { 337 return std::move(value()); 338 } 339 340 constexpr explicit operator bool() const noexcept { return has_value(); } has_value()341 constexpr bool has_value() const noexcept { 342 return contents_.index() == kValue; 343 } 344 value()345 constexpr T& value() & { return std::get<kValue>(contents_); } value()346 constexpr T&& value() && { return std::move(std::get<kValue>(contents_)); } value()347 constexpr const T& value() const& { return std::get<kValue>(contents_); } value()348 constexpr const T&& value() const&& { 349 return std::move(std::get<kValue>(contents_)); 350 } 351 error()352 constexpr E& error() & { return std::get<kError>(contents_); } error()353 constexpr E&& error() && { return std::move(std::get<kError>(contents_)); } error()354 constexpr const E& error() const& { return std::get<kError>(contents_); } error()355 constexpr const E&& error() const&& { 356 return std::move(std::get<kError>(contents_)); 357 } 358 359 template <class U> value_or(U && u)360 constexpr T value_or(U&& u) && { 361 return has_value() ? std::move(value()) 362 : static_cast<T>(std::forward<U>(u)); 363 } 364 template <class U> value_or(U && u)365 constexpr T value_or(U&& u) const& { 366 return has_value() ? value() : static_cast<T>(std::forward<U>(u)); 367 } 368 369 template <class G> error_or(G && g)370 constexpr E error_or(G&& g) && { 371 return has_value() ? std::forward<G>(g) : std::move(error()); 372 } 373 template <class G> error_or(G && g)374 constexpr E error_or(G&& g) const& { 375 return has_value() ? std::forward<G>(g) : error(); 376 } 377 378 template <class F> and_then(F && f)379 constexpr auto and_then(F&& f) & { 380 using U = remove_cvref_t<std::invoke_result_t<F, decltype(value())>>; 381 if (has_value()) { 382 return std::invoke(std::forward<F>(f), value()); 383 } else { 384 return U(unexpect, error()); 385 } 386 } 387 template <class F> and_then(F && f)388 constexpr auto and_then(F&& f) && { 389 using U = remove_cvref_t<std::invoke_result_t<F, decltype(value())>>; 390 if (has_value()) { 391 return std::invoke(std::forward<F>(f), std::move(value())); 392 } else { 393 return U(unexpect, std::move(error())); 394 } 395 } 396 template <class F> and_then(F && f)397 constexpr auto and_then(F&& f) const& { 398 using U = remove_cvref_t<std::invoke_result_t<F, decltype(value())>>; 399 if (has_value()) { 400 return std::invoke(std::forward<F>(f), value()); 401 } else { 402 return U(unexpect, error()); 403 } 404 } 405 template <class F> and_then(F && f)406 constexpr auto and_then(F&& f) const&& { 407 using U = remove_cvref_t<std::invoke_result_t<F, decltype(value())>>; 408 if (has_value()) { 409 return std::invoke(std::forward<F>(f), std::move(value())); 410 } else { 411 return U(unexpect, std::move(error())); 412 } 413 } 414 415 template <class F> or_else(F && f)416 constexpr auto or_else(F&& f) & { 417 using G = remove_cvref_t<std::invoke_result_t<F, decltype(error())>>; 418 if (has_value()) { 419 return G(std::in_place, value()); 420 } else { 421 return std::invoke(std::forward<F>(f), error()); 422 } 423 } 424 template <class F> or_else(F && f)425 constexpr auto or_else(F&& f) && { 426 using G = remove_cvref_t<std::invoke_result_t<F, decltype(error())>>; 427 if (has_value()) { 428 return G(std::in_place, value()); 429 } else { 430 return std::invoke(std::forward<F>(f), std::move(error())); 431 } 432 } 433 template <class F> or_else(F && f)434 constexpr auto or_else(F&& f) const& { 435 using G = remove_cvref_t<std::invoke_result_t<F, decltype(error())>>; 436 if (has_value()) { 437 return G(std::in_place, value()); 438 } else { 439 return std::invoke(std::forward<F>(f), error()); 440 } 441 } 442 template <class F> or_else(F && f)443 constexpr auto or_else(F&& f) const&& { 444 using G = remove_cvref_t<std::invoke_result_t<F, decltype(error())>>; 445 if (has_value()) { 446 return G(std::in_place, value()); 447 } else { 448 return std::invoke(std::forward<F>(f), std::move(error())); 449 } 450 } 451 452 template <class F> transform(F && f)453 constexpr auto transform(F&& f) & { 454 using U = std::remove_cv_t<std::invoke_result_t<F, decltype(value())>>; 455 if (has_value()) { 456 return transform_helper<U>(std::forward<F>(f)); 457 } else { 458 return expected<U, E>(unexpect, error()); 459 } 460 } 461 template <class F> transform(F && f)462 constexpr auto transform(F&& f) && { 463 using U = std::remove_cv_t<std::invoke_result_t<F, decltype(value())>>; 464 if (has_value()) { 465 return transform_helper<U>(std::forward<F>(f)); 466 } else { 467 return expected<U, E>(unexpect, std::move(error())); 468 } 469 } 470 template <class F> transform(F && f)471 constexpr auto transform(F&& f) const& { 472 using U = std::remove_cv_t<std::invoke_result_t<F, decltype(value())>>; 473 if (has_value()) { 474 return transform_helper<U>(std::forward<F>(f)); 475 } else { 476 return expected<U, E>(unexpect, error()); 477 } 478 } 479 template <class F> transform(F && f)480 constexpr auto transform(F&& f) const&& { 481 using U = std::remove_cv_t<std::invoke_result_t<F, decltype(value())>>; 482 if (has_value()) { 483 return transform_helper<U>(std::forward<F>(f)); 484 } else { 485 return expected<U, E>(unexpect, std::move(error())); 486 } 487 } 488 489 template <class F> transform_error(F && f)490 constexpr auto transform_error(F&& f) & { 491 using G = std::remove_cv_t<std::invoke_result_t<F, decltype(error())>>; 492 if (has_value()) { 493 return expected<T, G>(std::in_place, value()); 494 } else { 495 return expected<T, G>(unexpect, std::invoke(std::forward<F>(f), error())); 496 } 497 } 498 template <class F> transform_error(F && f)499 constexpr auto transform_error(F&& f) && { 500 using G = std::remove_cv_t<std::invoke_result_t<F, decltype(error())>>; 501 if (has_value()) { 502 return expected<T, G>(std::in_place, std::move(value())); 503 } else { 504 return expected<T, G>( 505 unexpect, std::invoke(std::forward<F>(f), std::move(error()))); 506 } 507 } 508 template <class F> transform_error(F && f)509 constexpr auto transform_error(F&& f) const& { 510 using G = std::remove_cv_t<std::invoke_result_t<F, decltype(error())>>; 511 if (has_value()) { 512 return expected<T, G>(std::in_place, value()); 513 } else { 514 return expected<T, G>(unexpect, std::invoke(std::forward<F>(f), error())); 515 } 516 } 517 template <class F> transform_error(F && f)518 constexpr auto transform_error(F&& f) const&& { 519 using G = std::remove_cv_t<std::invoke_result_t<F, decltype(error())>>; 520 if (has_value()) { 521 return expected<T, G>(std::in_place, std::move(value())); 522 } else { 523 return expected<T, G>( 524 unexpect, std::invoke(std::forward<F>(f), std::move(error()))); 525 } 526 } 527 528 private: 529 // Make all specializations of `expected` friends. 530 template <class U, class G, class> 531 friend class expected; 532 533 static constexpr size_t kValue = 0; 534 static constexpr size_t kError = 1; 535 536 static constexpr auto kInPlaceValue = std::in_place_index<kValue>; 537 static constexpr auto kInPlaceError = std::in_place_index<kError>; 538 539 // Helper to convert variant<U, G> -> variant<T, E> 540 template <class U, class G> convert_variant(const std::variant<U,G> & v)541 std::variant<T, E> convert_variant(const std::variant<U, G>& v) { 542 switch (v.index()) { 543 case kValue: 544 return std::variant<T, E>(kInPlaceValue, std::get<kValue>(v)); 545 case kError: 546 return std::variant<T, E>(kInPlaceError, std::get<kError>(v)); 547 default: 548 // Could only happen if valueless_by_exception, which can't be handled 549 // gracefully anyways. 550 std::abort(); 551 } 552 } 553 554 // Helper to convert variant<U, G> -> variant<T, E> 555 template <class U, class G> convert_variant(std::variant<U,G> && v)556 std::variant<T, E> convert_variant(std::variant<U, G>&& v) { 557 switch (v.index()) { 558 case kValue: 559 return std::variant<T, E>(kInPlaceValue, 560 std::forward<U>(std::get<kValue>(v))); 561 case kError: 562 return std::variant<T, E>(kInPlaceError, 563 std::forward<G>(std::get<kError>(v))); 564 default: 565 // Could only happen if valueless_by_exception, which can't be handled 566 // gracefully anyways. 567 std::abort(); 568 } 569 } 570 571 // Helper to handle transform correctly for void(Args...) functions, non-void 572 // case. 573 template <class U, class F, std::enable_if_t<!std::is_void_v<U>, bool> = true> transform_helper(F && f)574 expected<U, E> transform_helper(F&& f) & { 575 return expected<U, E>(std::in_place, 576 std::invoke(std::forward<F>(f), value())); 577 } 578 template <class U, class F, std::enable_if_t<!std::is_void_v<U>, bool> = true> transform_helper(F && f)579 expected<U, E> transform_helper(F&& f) && { 580 return expected<U, E>(std::in_place, 581 std::invoke(std::forward<F>(f), std::move(value()))); 582 } 583 template <class U, class F, std::enable_if_t<!std::is_void_v<U>, bool> = true> transform_helper(F && f)584 expected<U, E> transform_helper(F&& f) const& { 585 return expected<U, E>(std::in_place, 586 std::invoke(std::forward<F>(f), value())); 587 } 588 template <class U, class F, std::enable_if_t<!std::is_void_v<U>, bool> = true> transform_helper(F && f)589 expected<U, E> transform_helper(F&& f) const&& { 590 return expected<U, E>(std::in_place, 591 std::invoke(std::forward<F>(f), std::move(value()))); 592 } 593 594 // Helper to handle transform correctly for void(Args...) functions, void 595 // case. 596 template <class U, class F, std::enable_if_t<std::is_void_v<U>, bool> = true> transform_helper(F && f)597 expected<U, E> transform_helper(F&& f) & { 598 std::invoke(std::forward<F>(f), value()); 599 return expected<U, E>(); 600 } 601 template <class U, class F, std::enable_if_t<std::is_void_v<U>, bool> = true> transform_helper(F && f)602 expected<U, E> transform_helper(F&& f) && { 603 std::invoke(std::forward<F>(f), std::move(value())); 604 return expected<U, E>(); 605 } 606 template <class U, class F, std::enable_if_t<std::is_void_v<U>, bool> = true> transform_helper(F && f)607 expected<U, E> transform_helper(F&& f) const& { 608 std::invoke(std::forward<F>(f), value()); 609 return expected<U, E>(); 610 } 611 template <class U, class F, std::enable_if_t<std::is_void_v<U>, bool> = true> transform_helper(F && f)612 expected<U, E> transform_helper(F&& f) const&& { 613 std::invoke(std::forward<F>(f), std::move(value())); 614 return expected<U, E>(); 615 } 616 617 std::variant<T, E> contents_; 618 }; 619 620 template <class T, 621 class E, 622 class U, 623 class G, 624 std::enable_if_t<!std::is_void_v<U>, bool> = true> 625 constexpr bool operator==(const expected<T, E>& lhs, 626 const expected<U, G>& rhs) { 627 if (lhs.has_value() != rhs.has_value()) { 628 return false; 629 } 630 if (lhs.has_value()) { 631 return lhs.value() == rhs.value(); 632 } else { 633 return lhs.error() == rhs.error(); 634 } 635 } 636 637 template <class T, class E, class U> 638 constexpr bool operator==(const expected<T, E>& x, const U& u) { 639 return x.has_value() && static_cast<bool>(*x == u); 640 } 641 642 template <class T, class E, class G> 643 constexpr bool operator==(const expected<T, E>& x, const unexpected<G> e) { 644 return !x.has_value() && static_cast<bool>(x.error() == e.error()); 645 } 646 647 // Polyfill implementation of std::expected<void, ...> 648 template <class T, class E> 649 class expected<T, E, std::enable_if_t<std::is_void_v<T>>> { 650 public: 651 using value_type = T; 652 using error_type = E; 653 using unexpected_type = unexpected<E>; 654 655 template <class U> 656 using rebind = expected<U, error_type>; 657 expected()658 constexpr expected() noexcept : error_contents_(std::nullopt) {} 659 constexpr expected(const expected& rhs) = default; 660 constexpr expected(expected&& rhs) = default; 661 template < 662 class U, 663 class G, 664 // Constraints 665 std::enable_if_t< 666 std::is_void_v<U> && std::is_constructible_v<E, const G&> && 667 !std::is_constructible_v<unexpected<E>, expected<U, G>&> && 668 !std::is_constructible_v<unexpected<E>, expected<U, G>> && 669 !std::is_constructible_v<unexpected<E>, const expected<U, G>&> && 670 !std::is_constructible_v<unexpected<E>, const expected<U, G>>, 671 bool> = true, 672 // Explicit 673 std::enable_if_t<std::is_convertible_v<const G&, E>, bool> = true> expected(const expected<U,G> & rhs)674 constexpr /* implicit */ expected(const expected<U, G>& rhs) 675 : error_contents_(rhs.error_contents_.has_value() ? rhs.error_contents_ 676 : std::nullopt) {} 677 template < 678 class U, 679 class G, 680 // Constraints 681 std::enable_if_t< 682 std::is_void_v<U> && std::is_constructible_v<E, const G&> && 683 !std::is_constructible_v<unexpected<E>, expected<U, G>&> && 684 !std::is_constructible_v<unexpected<E>, expected<U, G>> && 685 !std::is_constructible_v<unexpected<E>, const expected<U, G>&> && 686 !std::is_constructible_v<unexpected<E>, const expected<U, G>>, 687 bool> = true, 688 // Explicit 689 std::enable_if_t<!std::is_convertible_v<const G&, E>, bool> = true> expected(const expected<U,G> & rhs)690 constexpr explicit expected(const expected<U, G>& rhs) 691 : error_contents_(rhs.error_contents_.has_value() ? rhs.error_contents_ 692 : std::nullopt) {} 693 template < 694 class U, 695 class G, 696 // Constraints 697 std::enable_if_t< 698 std::is_void_v<U> && std::is_constructible_v<E, G> && 699 !std::is_constructible_v<unexpected<E>, expected<U, G>&> && 700 !std::is_constructible_v<unexpected<E>, expected<U, G>> && 701 !std::is_constructible_v<unexpected<E>, const expected<U, G>&> && 702 !std::is_constructible_v<unexpected<E>, const expected<U, G>>, 703 bool> = true, 704 // Explicit 705 std::enable_if_t<std::is_convertible_v<G, E>, bool> = true> expected(expected<U,G> && rhs)706 constexpr /* implicit */ expected(expected<U, G>&& rhs) 707 : error_contents_(rhs.error_contents_.has_value() 708 ? std::move(rhs.error_contents_) 709 : std::nullopt) {} 710 template < 711 class U, 712 class G, 713 // Constraints 714 std::enable_if_t< 715 std::is_void_v<U> && std::is_constructible_v<E, G> && 716 !std::is_constructible_v<unexpected<E>, expected<U, G>&> && 717 !std::is_constructible_v<unexpected<E>, expected<U, G>> && 718 !std::is_constructible_v<unexpected<E>, const expected<U, G>&> && 719 !std::is_constructible_v<unexpected<E>, const expected<U, G>>, 720 bool> = true, 721 // Explicit 722 std::enable_if_t<!std::is_convertible_v<G, E>, bool> = true> expected(expected<U,G> && rhs)723 constexpr explicit expected(expected<U, G>&& rhs) 724 : error_contents_(rhs.error_contents_.has_value() 725 ? std::move(rhs.error_contents_) 726 : std::nullopt) {} 727 template <class G, 728 // Constraints 729 std::enable_if_t<std::is_constructible_v<E, const G&>, bool> = true, 730 // Explicit 731 std::enable_if_t<!std::is_convertible_v<const G&, E>, bool> = true> expected(const unexpected<G> & e)732 constexpr explicit expected(const unexpected<G>& e) 733 : error_contents_(std::in_place, std::forward<const G&>(e.error())) {} 734 template <class G, 735 // Constraints 736 std::enable_if_t<std::is_constructible_v<E, const G&>, bool> = true, 737 // Explicit 738 std::enable_if_t<std::is_convertible_v<const G&, E>, bool> = true> expected(const unexpected<G> & e)739 constexpr /* implicit */ expected(const unexpected<G>& e) 740 : error_contents_(std::in_place, std::forward<const G&>(e.error())) {} 741 template <class... Args, 742 std::enable_if_t<std::is_constructible_v<E, Args...>, bool> = true> expected(unexpect_t,Args &&...args)743 constexpr explicit expected(unexpect_t, Args&&... args) 744 : error_contents_(std::in_place, std::forward<Args>(args)...) {} 745 template <class U, 746 class... Args, 747 std::enable_if_t< 748 std::is_constructible_v<E, std::initializer_list<U>&, Args...>, 749 bool> = true> expected(unexpect_t,std::initializer_list<U> il,Args &&...args)750 constexpr explicit expected(unexpect_t, 751 std::initializer_list<U> il, 752 Args&&... args) 753 : error_contents_(std::in_place, il, std::forward<Args>(args)...) {} 754 template <class G, 755 // Constraints 756 std::enable_if_t<std::is_constructible_v<E, G>, bool> = true, 757 // Explicit 758 std::enable_if_t<!std::is_convertible_v<G, E>, bool> = true> expected(unexpected<G> && e)759 constexpr explicit expected(unexpected<G>&& e) 760 : error_contents_(std::in_place, std::forward<G>(e.error())) {} 761 template <class G, 762 // Constraints 763 std::enable_if_t<std::is_constructible_v<E, G>, bool> = true, 764 // Explicit 765 std::enable_if_t<std::is_convertible_v<G, E>, bool> = true> expected(unexpected<G> && e)766 constexpr /* implicit */ expected(unexpected<G>&& e) 767 : error_contents_(std::in_place, std::forward<G>(e.error())) {} 768 769 constexpr expected& operator=(const expected& rhs) { 770 error_contents_ = rhs.error_contents_; 771 return *this; 772 } noexcept(std::is_nothrow_move_constructible_v<E> && std::is_nothrow_move_assignable_v<E>)773 constexpr expected& operator=(expected&& rhs) noexcept( 774 std::is_nothrow_move_constructible_v<E> && 775 std::is_nothrow_move_assignable_v<E>) { 776 error_contents_ = std::move(rhs.error_contents_); 777 return *this; 778 } 779 template <class G> 780 constexpr expected& operator=(const unexpected<G>& rhs) { 781 error_contents_ = rhs.error(); 782 return *this; 783 } 784 template <class G> 785 constexpr expected& operator=(unexpected<G>&& rhs) { 786 error_contents_ = std::move(rhs.error()); 787 return *this; 788 } 789 swap(expected & rhs)790 constexpr void swap(expected& rhs) { 791 error_contents_.swap(rhs.error_contents_); 792 } 793 794 constexpr explicit operator bool() const noexcept { return has_value(); } has_value()795 constexpr bool has_value() const noexcept { 796 return !error_contents_.has_value(); 797 } 798 799 constexpr void operator*() const noexcept {} value()800 constexpr void value() const& {} value()801 constexpr void value() && {} 802 error()803 constexpr E& error() & { return *error_contents_; } error()804 constexpr E&& error() && { return std::move(*error_contents_); } error()805 constexpr const E& error() const& { return *error_contents_; } error()806 constexpr const E&& error() const&& { return std::move(*error_contents_); } 807 808 template <class G = E> error_or(G && g)809 constexpr E error_or(G&& g) const& { 810 if (has_value()) { 811 return std::forward<G>(g); 812 } else { 813 return error(); 814 } 815 } 816 template <class G = E> error_or(G && g)817 constexpr E error_or(G&& g) const&& { 818 if (has_value()) { 819 return std::forward<G>(g); 820 } else { 821 return std::move(error()); 822 } 823 } 824 825 template <class F> and_then(F && f)826 constexpr auto and_then(F&& f) & { 827 using U = remove_cvref_t<std::invoke_result_t<F>>; 828 if (has_value()) { 829 return std::invoke(std::forward<F>(f)); 830 } else { 831 return U(unexpect, error()); 832 } 833 } 834 template <class F> and_then(F && f)835 constexpr auto and_then(F&& f) && { 836 using U = remove_cvref_t<std::invoke_result_t<F>>; 837 if (has_value()) { 838 return std::invoke(std::forward<F>(f)); 839 } else { 840 return U(unexpect, std::move(error())); 841 } 842 } 843 template <class F> and_then(F && f)844 constexpr auto and_then(F&& f) const& { 845 using U = remove_cvref_t<std::invoke_result_t<F>>; 846 if (has_value()) { 847 return std::invoke(std::forward<F>(f)); 848 } else { 849 return U(unexpect, error()); 850 } 851 } 852 template <class F> and_then(F && f)853 constexpr auto and_then(F&& f) const&& { 854 using U = remove_cvref_t<std::invoke_result_t<F>>; 855 if (has_value()) { 856 return std::invoke(std::forward<F>(f)); 857 } else { 858 return U(unexpect, std::move(error())); 859 } 860 } 861 862 template <class F> or_else(F && f)863 constexpr auto or_else(F&& f) & { 864 using G = remove_cvref_t<std::invoke_result_t<F, decltype(error())>>; 865 if (has_value()) { 866 return G(); 867 } else { 868 return std::invoke(std::forward<F>(f), error()); 869 } 870 } 871 template <class F> or_else(F && f)872 constexpr auto or_else(F&& f) && { 873 using G = remove_cvref_t<std::invoke_result_t<F, decltype(error())>>; 874 if (has_value()) { 875 return G(); 876 } else { 877 return std::invoke(std::forward<F>(f), std::move(error())); 878 } 879 } 880 template <class F> or_else(F && f)881 constexpr auto or_else(F&& f) const& { 882 using G = remove_cvref_t<std::invoke_result_t<F, decltype(error())>>; 883 if (has_value()) { 884 return G(); 885 } else { 886 return std::invoke(std::forward<F>(f), error()); 887 } 888 } 889 template <class F> or_else(F && f)890 constexpr auto or_else(F&& f) const&& { 891 using G = remove_cvref_t<std::invoke_result_t<F, decltype(error())>>; 892 if (has_value()) { 893 return G(); 894 } else { 895 return std::invoke(std::forward<F>(f), std::move(error())); 896 } 897 } 898 899 template <class F> transform(F && f)900 constexpr auto transform(F&& f) & { 901 using U = std::remove_cv_t<std::invoke_result_t<F>>; 902 if (has_value()) { 903 return transform_helper<U>(std::forward<F>(f)); 904 } else { 905 return expected<U, E>(unexpect, error()); 906 } 907 } 908 template <class F> transform(F && f)909 constexpr auto transform(F&& f) && { 910 using U = std::remove_cv_t<std::invoke_result_t<F>>; 911 if (has_value()) { 912 return transform_helper<U>(std::forward<F>(f)); 913 } else { 914 return expected<U, E>(unexpect, std::move(error())); 915 } 916 } 917 template <class F> transform(F && f)918 constexpr auto transform(F&& f) const& { 919 using U = std::remove_cv_t<std::invoke_result_t<F>>; 920 if (has_value()) { 921 return transform_helper<U>(std::forward<F>(f)); 922 } else { 923 return expected<U, E>(unexpect, error()); 924 } 925 } 926 template <class F> transform(F && f)927 constexpr auto transform(F&& f) const&& { 928 using U = std::remove_cv_t<std::invoke_result_t<F>>; 929 if (has_value()) { 930 return transform_helper<U>(std::forward<F>(f)); 931 } else { 932 return expected<U, E>(unexpect, std::move(error())); 933 } 934 } 935 936 template <class F> transform_error(F && f)937 constexpr auto transform_error(F&& f) & { 938 using G = std::remove_cv_t<std::invoke_result_t<F, decltype(error())>>; 939 if (has_value()) { 940 return expected<T, G>(); 941 } else { 942 return expected<T, G>(unexpect, std::invoke(std::forward<F>(f), error())); 943 } 944 } 945 template <class F> transform_error(F && f)946 constexpr auto transform_error(F&& f) && { 947 using G = std::remove_cv_t<std::invoke_result_t<F, decltype(error())>>; 948 if (has_value()) { 949 return expected<T, G>(); 950 } else { 951 return expected<T, G>( 952 unexpect, std::invoke(std::forward<F>(f), std::move(error()))); 953 } 954 } 955 template <class F> transform_error(F && f)956 constexpr auto transform_error(F&& f) const& { 957 using G = std::remove_cv_t<std::invoke_result_t<F, decltype(error())>>; 958 if (has_value()) { 959 return expected<T, G>(); 960 } else { 961 return expected<T, G>(unexpect, std::invoke(std::forward<F>(f), error())); 962 } 963 } 964 template <class F> transform_error(F && f)965 constexpr auto transform_error(F&& f) const&& { 966 using G = std::remove_cv_t<std::invoke_result_t<F, decltype(error())>>; 967 if (has_value()) { 968 return expected<T, G>(); 969 } else { 970 return expected<T, G>( 971 unexpect, std::invoke(std::forward<F>(f), std::move(error()))); 972 } 973 } 974 975 private: 976 // Make all specializations of `expected` friends. 977 template <class U, class G, class> 978 friend class expected; 979 980 // Helper to handle transform correctly for void(Args...) functions, non-void 981 // case. 982 template <class U, class F, std::enable_if_t<!std::is_void_v<U>, bool> = true> transform_helper(F && f)983 expected<U, E> transform_helper(F&& f) const { 984 return expected<U, E>(std::in_place, std::invoke(std::forward<F>(f))); 985 } 986 987 // Helper to handle transform correctly for void(Args...) functions, void 988 // case. 989 template <class U, class F, std::enable_if_t<std::is_void_v<U>, bool> = true> transform_helper(F && f)990 expected<U, E> transform_helper(F&& f) const { 991 std::invoke(std::forward<F>(f)); 992 return expected<U, E>(); 993 } 994 995 std::optional<E> error_contents_; 996 }; 997 998 template <class T, 999 class E, 1000 class U, 1001 class G, 1002 std::enable_if_t<std::is_void_v<U>, bool> = true> 1003 constexpr bool operator==(const expected<T, E>& lhs, 1004 const expected<U, G>& rhs) { 1005 if (lhs.has_value() != rhs.has_value()) 1006 return false; 1007 return lhs.has_value() || static_cast<bool>(lhs.error() == rhs.error()); 1008 } 1009 1010 template <class T, class E, class G> 1011 constexpr bool operator==(const expected<T, E>& lhs, const unexpected<G>& rhs) { 1012 return !lhs.has_value() && static_cast<bool>(lhs.error() == rhs.error()); 1013 } 1014 1015 } // namespace pw::internal 1016