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