Skip to content

Instantly share code, notes, and snippets.

@BreadFish64
Created January 8, 2025 05:47
Show Gist options
  • Select an option

  • Save BreadFish64/453bc4005b2e28578738ed83851d7720 to your computer and use it in GitHub Desktop.

Select an option

Save BreadFish64/453bc4005b2e28578738ed83851d7720 to your computer and use it in GitHub Desktop.

Revisions

  1. BreadFish64 revised this gist Jan 8, 2025. No changes.
  2. BreadFish64 created this gist Jan 8, 2025.
    1,672 changes: 1,672 additions & 0 deletions breaded_expected.hpp
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,1672 @@
    #pragma once

    #include <cassert>
    #include <concepts>
    #include <memory>
    #include <type_traits>
    #include <utility>

    namespace breaded {

    #pragma region Forward Declarations

    template <class E>
    class bad_expected_access;

    template <class E>
    class unexpected;

    template <class T, class E>
    class expected;

    #pragma endregion

    // https://en.cppreference.com/w/cpp/utility/expected/unexpect_t
    struct unexpect_t {
    constexpr explicit unexpect_t() = default;
    };

    // https://en.cppreference.com/w/cpp/utility/expected/unexpect_t
    constexpr unexpect_t unexpect{};

    #pragma region Traits
    namespace details {

    struct in_place_from_return_t {
    constexpr explicit in_place_from_return_t() = default;
    };
    constexpr in_place_from_return_t in_place_from_return{};

    struct unexpect_from_return_t {
    constexpr explicit unexpect_from_return_t() = default;
    };
    constexpr unexpect_from_return_t unexpect_from_return{};

    template <class T>
    struct IsSpecializationOfUnexpected : std::false_type {};
    template <class T, class E>
    struct IsSpecializationOfUnexpected<breaded::expected<T, E>> : std::true_type {};
    template <class T>
    constexpr bool kIsSpecializationOfUnexpected = IsSpecializationOfUnexpected<T>::value;

    template <class T>
    struct IsSpecializationOfExpected : std::false_type {};
    template <class T, class E>
    struct IsSpecializationOfExpected<breaded::expected<T, E>> : std::true_type {};
    template <class T>
    constexpr bool kIsSpecializationOfExpected = IsSpecializationOfExpected<T>::value;

    // https://en.cppreference.com/w/cpp/named_req/Destructible
    // This isn't quite the same as std::is_destructible_v<T>
    // This does not allow arrays or reference types.
    template <class T>
    concept NamedRequirementDestructible =
    std::is_nothrow_destructible_v<T> && !std::is_array_v<T> && !std::is_reference_v<T>;

    template <typename T>
    concept NotTag = !std::is_same_v<std::remove_cvref_t<T>, std::in_place_t> &&
    !std::is_same_v<std::remove_cvref_t<T>, breaded::unexpect_t>;

    template <typename E>
    concept ValidExpectedErrorType =
    std::is_object_v<E> && !std::is_const_v<E> && !std::is_volatile_v<E> && !kIsSpecializationOfExpected<E>;

    template <class T>
    concept ValidExpectedValueType =
    NotTag<T> && !std::is_reference_v<T> && !std::is_function_v<T> && !kIsSpecializationOfUnexpected<T> &&
    (std::is_void_v<T> || NamedRequirementDestructible<T>);

    } // namespace details
    #pragma endregion

    #pragma region bad_expected_access

    // https://en.cppreference.com/w/cpp/utility/expected/bad_expected_access
    template <>
    class bad_expected_access<void> : public std::exception {
    public:
    // https://en.cppreference.com/w/cpp/utility/expected/bad_expected_access#std::bad_expected_access::what
    const char* what() const noexcept override { return "Attempted to access the value of an errored expected type"; }

    protected:
    // https://en.cppreference.com/w/cpp/utility/expected/bad_expected_access#std::bad_expected_access::bad_expected_access
    explicit bad_expected_access() = default;
    bad_expected_access(const bad_expected_access& other) = default;
    bad_expected_access(bad_expected_access&& other) = default;
    ~bad_expected_access() override = default;
    bad_expected_access& operator=(const bad_expected_access& other) = default;
    bad_expected_access& operator=(bad_expected_access&& other) = default;
    };

    // https://en.cppreference.com/w/cpp/utility/expected/bad_expected_access
    template <class E>
    class bad_expected_access : public breaded::bad_expected_access<void> {
    public:
    // https://en.cppreference.com/w/cpp/utility/expected/bad_expected_access#std::bad_expected_access::bad_expected_access
    explicit bad_expected_access(E e) : error_{std::move(e)} {}

    // https://en.cppreference.com/w/cpp/utility/expected/bad_expected_access#std::bad_expected_access::error
    [[nodiscard]] const E& error() const& noexcept { return error_; }

    // https://en.cppreference.com/w/cpp/utility/expected/bad_expected_access#std::bad_expected_access::error
    [[nodiscard]] E& error() & noexcept { return error_; }

    // https://en.cppreference.com/w/cpp/utility/expected/bad_expected_access#std::bad_expected_access::error
    [[nodiscard]] const E&& error() const&& noexcept { return std::move(error_); }

    // https://en.cppreference.com/w/cpp/utility/expected/bad_expected_access#std::bad_expected_access::error
    [[nodiscard]] E&& error() && noexcept { return std::move(error_); }

    private:
    E error_;
    };

    #pragma endregion

    #pragma region Unexpected

    // https://en.cppreference.com/w/cpp/utility/expected/unexpected
    template <class E>
    class unexpected {
    static_assert(details::ValidExpectedErrorType<E>);

    public:
    unexpected() = delete;

    // https://en.cppreference.com/w/cpp/utility/expected/unexpected#ctor
    constexpr unexpected(const unexpected&) noexcept(std::is_nothrow_copy_constructible_v<E>) = default;

    // https://en.cppreference.com/w/cpp/utility/expected/unexpected#ctor
    constexpr unexpected(unexpected&&) noexcept(std::is_nothrow_move_constructible_v<E>) = default;

    // https://en.cppreference.com/w/cpp/utility/expected/unexpected#ctor
    template <class Err = E>
    requires(!std::is_same_v<std::remove_cvref_t<Err>, unexpected> &&
    !std::is_same_v<std::remove_cvref_t<Err>, std::in_place_t> && std::is_constructible_v<E, Err>)
    constexpr explicit unexpected(Err&& e) noexcept(std::is_nothrow_constructible_v<E, Err>)
    : error_(std::forward<Err>(e)) {}

    // https://en.cppreference.com/w/cpp/utility/expected/unexpected#ctor
    template <class... Args>
    requires(std::is_constructible_v<E, Args...>)
    constexpr explicit unexpected(std::in_place_t, Args&&... args) noexcept(std::is_nothrow_constructible_v<E, Args...>)
    : error_(std::forward<Args>(args)...) {}

    // https://en.cppreference.com/w/cpp/utility/expected/unexpected#ctor
    template <class U, class... Args>
    requires(std::is_constructible_v<E, std::initializer_list<U>&, Args...>)
    constexpr explicit unexpected(std::in_place_t, std::initializer_list<U> il, Args&&... args) noexcept(
    std::is_nothrow_constructible_v<E, std::initializer_list<U>&, Args...>)
    : error_(il, std::forward<Args>(args)...) {}

    // https://en.cppreference.com/w/cpp/utility/expected/unexpected#error
    [[nodiscard]] constexpr const E& error() const& noexcept { return error_; }

    // https://en.cppreference.com/w/cpp/utility/expected/unexpected#error
    [[nodiscard]] constexpr E& error() & noexcept { return error_; }

    // https://en.cppreference.com/w/cpp/utility/expected/unexpected#error
    [[nodiscard]] constexpr const E&& error() const&& noexcept { return std::move(error_); }

    // https://en.cppreference.com/w/cpp/utility/expected/unexpected#error
    [[nodiscard]] constexpr E&& error() && noexcept { return std::move(error_); }

    // https://en.cppreference.com/w/cpp/utility/expected/unexpected#swap
    constexpr void swap(unexpected& other) noexcept(std::is_nothrow_swappable_v<E>) {
    // Prefer custom swap friend function, and use move-based std::swap as a fallback
    // https://en.cppreference.com/w/cpp/language/adl
    using std::swap;
    swap(error_, other.error_);
    }

    // https://en.cppreference.com/w/cpp/utility/expected/unexpected#operator.3D.3D.28std::unexpected.29
    template <class E2>
    [[nodiscard]] friend constexpr bool operator==(const unexpected& x,
    const breaded::unexpected<E2>& y) noexcept(noexcept(x.error() ==
    y.error())) {
    return x.error() == y.error();
    }

    // https://en.cppreference.com/w/cpp/utility/expected/unexpected#swap.28std::unexpected.29
    friend constexpr void swap(unexpected& x, unexpected& y) noexcept(std::is_nothrow_swappable_v<E>) { x.swap(y); }

    private:
    E error_;
    };

    // https://en.cppreference.com/w/cpp/utility/expected/unexpected#Deduction_guides
    template <class E>
    unexpected(E) -> unexpected<E>;

    #pragma endregion

    namespace details {

    template <class NewType, class OldType, class... Args>
    constexpr bool kUnionAssignable =
    std::is_constructible_v<NewType, Args...> &&
    (std::is_nothrow_constructible_v<NewType, Args...> || std::is_nothrow_move_constructible_v<NewType> ||
    std::is_nothrow_move_constructible_v<OldType>);

    template <class NewType, class OldType, class... Args>
    constexpr bool kNothrowUnionAssignable =
    kUnionAssignable<NewType, OldType, Args...> && std::is_nothrow_constructible_v<NewType, Args...>;

    // This function allows assigning to an inactive union member,
    // while preserving the old active member if the assignment throws an exception.
    // This is required for std::expected since it can never be value-less
    //
    // "If an exception is thrown, the old value is retained; *this does not become valueless."
    // https://en.cppreference.com/w/cpp/utility/expected/operator%3D#Helper_function_template
    template <class NewType, class OldType, class... Args>
    constexpr void UnionAssign(NewType& newVal, OldType& oldVal,
    Args&&... args) noexcept(kNothrowUnionAssignable<NewType, OldType, Args...>)
    requires(kUnionAssignable<NewType, OldType, Args...>)
    {
    if constexpr (std::is_nothrow_constructible_v<NewType, Args...>) {
    std::destroy_at(std::addressof(oldVal));
    std::construct_at(std::addressof(newVal), std::forward<Args>(args)...);
    } else if constexpr (std::is_nothrow_move_constructible_v<NewType>) {
    NewType temp(std::forward<Args>(args)...);
    std::destroy_at(std::addressof(oldVal));
    std::construct_at(std::addressof(newVal), std::move(temp));
    } else if constexpr (std::is_nothrow_move_constructible_v<OldType>) {
    OldType temp(std::move(oldVal));
    std::destroy_at(std::addressof(oldVal));
    try {
    std::construct_at(std::addressof(newVal), std::forward<Args>(args)...);
    } catch (...) {
    std::construct_at(std::addressof(oldVal), std::move(temp));
    throw;
    }
    } else {
    static_assert(sizeof(NewType) == 0,
    "Sanity check failed. Cannot call without fulfilling one of these conditions");
    }
    }

    template <class T, class U>
    constexpr bool kUnionSwappable = std::is_move_constructible_v<T> && std::is_move_constructible_v<U> &&
    (std::is_nothrow_move_constructible_v<T> || std::is_nothrow_move_constructible_v<U>);

    template <class T, class U>
    constexpr bool kNothrowUnionSwappable =
    std::is_nothrow_move_constructible_v<T> && std::is_nothrow_move_constructible_v<U>;

    // https://en.cppreference.com/w/cpp/utility/expected/swap
    template <class T, class U>
    constexpr void UnionSwap(T& dstT, U& dstU, T&& srcT, U&& srcU) noexcept(kNothrowUnionSwappable<T, U>)
    requires(kUnionSwappable<T, U>)
    {
    if constexpr (std::is_nothrow_move_constructible_v<T>) {
    T tmp(std::move(srcT));
    std::destroy_at(std::addressof(srcT));
    if constexpr (std::is_nothrow_move_constructible_v<U>) {
    std::construct_at(std::addressof(dstU), std::move(srcU));
    } else {
    try {
    std::construct_at(std::addressof(dstU), std::move(srcU));
    } catch (...) {
    std::construct_at(std::addressof(srcT), std::move(tmp));
    throw;
    }
    }
    std::destroy_at(std::addressof(srcU));
    std::construct_at(std::addressof(dstT), std::move(tmp));
    } else {
    static_assert(std::is_nothrow_move_constructible_v<U>,
    "Either T or U must be nothrow_move_constructible to enforce strong exception safety");
    UnionSwap(dstU, dstT, std::move(srcU), std::move(srcT));
    }
    }

    } // namespace details

    #pragma region Expected T
    // https://en.cppreference.com/w/cpp/utility/expected
    template <class T, class E>
    class expected {
    static_assert(details::ValidExpectedValueType<T>);
    static_assert(details::ValidExpectedErrorType<E>);
    static_assert(!std::is_void_v<T>, "Sanity check failed. This should be handled in a specialization");

    template <typename Self, typename F>
    struct AndThenReturn {
    using type = std::remove_cvref_t<std::invoke_result_t<F, decltype(*std::declval<Self>())>>;
    };

    template <typename Self, typename F>
    struct TransformReturn {
    using URaw = std::invoke_result_t<F, decltype(*std::declval<Self>())>;
    using U = std::remove_cvref_t<URaw>;
    using type = breaded::expected<U, E>;
    };

    template <typename Self, typename F>
    struct OrElseReturn {
    using type = std::remove_cvref_t<std::invoke_result_t<F, decltype(std::declval<Self>().error())>>;
    };

    template <typename Self, typename F>
    struct TransformErrorReturn {
    using GRaw = std::invoke_result_t<F, decltype(std::declval<Self>().error())>;
    using G = std::remove_cvref_t<GRaw>;
    using type = breaded::expected<T, G>;
    };

    public:
    #pragma region Member types
    // https://en.cppreference.com/w/cpp/utility/expected#Member_types

    using value_type = T;
    using error_type = E;
    using unexpected_type = breaded::unexpected<E>;
    #pragma endregion

    #pragma region Member alias templates
    // https://en.cppreference.com/w/cpp/utility/expected#Member_alias_templates

    template <class U>
    using rebind = breaded::expected<U, error_type>;
    #pragma endregion

    private:
    template <typename U>
    static constexpr bool kSameAsThis = std::is_same_v<expected, std::remove_cvref_t<U>>;

    static constexpr bool kValueTypeIsBool = std::is_same_v<bool, std::remove_cvref_t<T>>;

    template <class U>
    static constexpr bool kExpectedConvertibleToValueType =
    std::is_constructible_v<T, U&> || std::is_constructible_v<T, U> || std::is_constructible_v<T, const U&> ||
    std::is_constructible_v<T, const U> || std::is_convertible_v<U&, T> || std::is_convertible_v<U, T> ||
    std::is_convertible_v<const U&, T> || std::is_convertible_v<const U, T>;

    template <class U>
    static constexpr bool kExpectedConvertibleToErrorType =
    std::is_constructible_v<unexpected_type, U&> || std::is_constructible_v<unexpected_type, U> ||
    std::is_constructible_v<unexpected_type, const U&> || std::is_constructible_v<unexpected_type, const U>;

    public:
    #pragma region Member functions
    // https://en.cppreference.com/w/cpp/utility/expected#Member_functions

    #pragma region constructor
    // Default value constructor
    // https://en.cppreference.com/w/cpp/utility/expected/expected
    constexpr expected() noexcept(std::is_nothrow_default_constructible_v<T>)
    requires(std::is_default_constructible_v<T>)
    : value_(), hasValue_(true) {}

    // Non-trivial copy constructor
    // https://en.cppreference.com/w/cpp/utility/expected/expected
    constexpr expected(const expected& other) noexcept(std::is_nothrow_copy_constructible_v<T> &&
    std::is_nothrow_copy_constructible_v<E>)
    requires(std::is_copy_constructible_v<T> && std::is_copy_constructible_v<E> &&
    !(std::is_trivially_copy_constructible_v<T> && std::is_trivially_copy_constructible_v<E>))
    {
    constructFromExpected(other);
    }

    // Trivial copy constructor
    // https://en.cppreference.com/w/cpp/utility/expected/expected
    expected(const expected& other)
    requires(std::is_copy_constructible_v<T> && std::is_copy_constructible_v<E> &&
    (std::is_trivially_copy_constructible_v<T> && std::is_trivially_copy_constructible_v<E>))
    = default;

    // This constructor is defined as deleted unless is_copy_constructible_v<T> is true
    // and is_copy_constructible_v<E> is true
    // https://github.com/cplusplus/draft/blob/d29ef68d3c7a1c2317f4670f08bbc8a63828ce35/source/utilities.tex#L7423
    expected(const expected&) = delete;

    // Non-trivial move constructor
    // https://en.cppreference.com/w/cpp/utility/expected/expected
    constexpr expected(expected&& other) noexcept(std::is_nothrow_move_constructible_v<T> &&
    std::is_nothrow_move_constructible_v<E>)
    requires(std::is_move_constructible_v<T> && std::is_move_constructible_v<E> &&
    !(std::is_trivially_move_constructible_v<T> && std::is_trivially_move_constructible_v<E>))
    {
    constructFromExpected(std::move(other));
    }

    // Trivial move constructor
    // https://en.cppreference.com/w/cpp/utility/expected/expected
    expected(expected&& other)
    requires(std::is_move_constructible_v<T> && std::is_move_constructible_v<E> &&
    (std::is_trivially_move_constructible_v<T> && std::is_trivially_move_constructible_v<E>))
    = default;

    // Converting copy construct from expected
    // https://en.cppreference.com/w/cpp/utility/expected/expected
    template <class U, class G>
    requires(!kSameAsThis<breaded::expected<U, G>> && std::is_constructible_v<T, const U&> &&
    (kValueTypeIsBool || !kExpectedConvertibleToValueType<breaded::expected<U, G>>) &&
    !kExpectedConvertibleToErrorType<breaded::expected<U, G>>)
    constexpr explicit(!std::is_convertible_v<const U&, T> || !std::is_convertible_v<const G&, E>)
    expected(const breaded::expected<U, G>& other) noexcept(std::is_nothrow_constructible_v<T, const U&> &&
    std::is_nothrow_constructible_v<E, const G&>) {
    constructFromExpected(other);
    }

    // Converting move construct from expected
    // https://en.cppreference.com/w/cpp/utility/expected/expected
    template <class U, class G>
    requires(!kSameAsThis<breaded::expected<U, G>> && std::is_constructible_v<T, U> &&
    (kValueTypeIsBool || !kExpectedConvertibleToValueType<breaded::expected<U, G>>) &&
    !kExpectedConvertibleToErrorType<breaded::expected<U, G>>)
    constexpr explicit(!std::is_convertible_v<U, T> || !std::is_convertible_v<G, E>)
    expected(breaded::expected<U, G>&& other) noexcept(std::is_nothrow_constructible_v<T, U> &&
    std::is_nothrow_constructible_v<E, G>) {
    constructFromExpected(std::move(other));
    }

    // Constructor from value
    // https://en.cppreference.com/w/cpp/utility/expected/expected
    template <class U = T>
    requires(details::NotTag<T> && !kSameAsThis<U> && std::is_constructible_v<T, U> &&
    !details::kIsSpecializationOfUnexpected<std::remove_cvref_t<U>> &&
    (!kValueTypeIsBool || !details::kIsSpecializationOfUnexpected<std::remove_cvref_t<U>>))
    constexpr explicit(!std::is_convertible_v<U, T>) expected(U&& v) noexcept(std::is_nothrow_constructible_v<T, U>)
    : value_(std::forward<U>(v)), hasValue_(true) {}

    // Copy constructor from unexpected
    // https://en.cppreference.com/w/cpp/utility/expected/expected
    template <class G>
    requires(std::is_constructible_v<E, const G&>)
    constexpr explicit(!std::is_convertible_v<const G&, E>)
    expected(const breaded::unexpected<G>& e) noexcept(std::is_nothrow_constructible_v<E, const G&>)
    : error_(e.error()), hasValue_(false) {}

    // Move constructor from unexpected
    // https://en.cppreference.com/w/cpp/utility/expected/expected
    template <class G>
    requires(std::is_constructible_v<E, G>)
    constexpr explicit(!std::is_convertible_v<G, E>)
    expected(breaded::unexpected<G>&& e) noexcept(std::is_nothrow_constructible_v<E, G>)
    : error_(std::move(e).error()), hasValue_(false) {}

    // In-place value constructor from args
    // https://en.cppreference.com/w/cpp/utility/expected/expected
    template <class... Args>
    requires(std::is_constructible_v<T, Args...>)
    constexpr explicit expected(std::in_place_t, Args&&... args) noexcept(std::is_nothrow_constructible_v<T, Args...>)
    : value_(std::forward<Args>(args)...), hasValue_(true) {}

    // In-place value constructor from initializer list
    // https://en.cppreference.com/w/cpp/utility/expected/expected
    template <class U, class... Args>
    requires(std::is_constructible_v<T, std::initializer_list<U>&, Args...>)
    constexpr explicit expected(std::in_place_t, std::initializer_list<U> il, Args&&... args) noexcept(
    std::is_nothrow_constructible_v<T, std::initializer_list<U>&, Args...>)
    : value_(il, std::forward<Args>(args)...), hasValue_(true) {}

    // In-place error constructor from args
    // https://en.cppreference.com/w/cpp/utility/expected/expected
    template <class... Args>
    requires(std::is_constructible_v<E, Args...>)
    constexpr explicit expected(breaded::unexpect_t,
    Args&&... args) noexcept(std::is_nothrow_constructible_v<E, Args...>)
    : error_(std::forward<Args>(args)...), hasValue_(false) {}

    // In-place error constructor from initializer list
    // https://en.cppreference.com/w/cpp/utility/expected/expected
    template <class U, class... Args>
    requires(std::is_constructible_v<E, std::initializer_list<U>&, Args...>)
    constexpr explicit expected(breaded::unexpect_t, std::initializer_list<U> il, Args&&... args) noexcept(
    std::is_nothrow_constructible_v<E, std::initializer_list<U>&, Args...>)
    : error_(il, std::forward<Args>(args)...), hasValue_(false) {}

    #pragma endregion

    // https://en.cppreference.com/w/cpp/utility/expected/~expected#Main_template_destructor
    constexpr ~expected() noexcept { destroy(); }

    // https://en.cppreference.com/w/cpp/utility/expected/~expected#Main_template_destructor
    ~expected()
    requires(std::is_trivially_destructible_v<T> && std::is_trivially_destructible_v<E>)
    = default;

    #pragma region Assignment

    // Non-trivial copy assignment
    // https://en.cppreference.com/w/cpp/utility/expected/operator%3D
    constexpr expected& operator=(const expected& other) noexcept(std::is_nothrow_copy_assignable_v<T> &&
    std::is_nothrow_copy_assignable_v<E> &&
    details::kNothrowUnionAssignable<T, E, const T&> &&
    details::kNothrowUnionAssignable<E, T, const E&>)
    requires(std::is_copy_assignable_v<T> && std::is_copy_assignable_v<E> &&
    details::kUnionAssignable<T, E, const T&> && details::kUnionAssignable<E, T, const E&> &&
    !(std::is_trivially_copy_assignable_v<T> && std::is_trivially_copy_assignable_v<E>))
    {
    assignFromExpected(other);
    return *this;
    }

    // Trivial copy assignment
    // https://en.cppreference.com/w/cpp/utility/expected/operator%3D
    expected& operator=(const expected& other)
    requires(std::is_copy_assignable_v<T> && std::is_copy_assignable_v<E> &&
    details::kUnionAssignable<T, E, const T&> && details::kUnionAssignable<E, T, const E&> &&
    (std::is_trivially_copy_assignable_v<T> && std::is_trivially_copy_assignable_v<E>))
    = default;

    // This operator is defined as deleted unless is_copy_constructible_v<T> is true and is_copy_assignable_v<T> is true
    // and is_copy_assignable_v<E> is true and is_copy_constructible_v<E> is true and
    // is_nothrow_move_constructible_v<T> || is_nothrow_move_constructible_v<E> is true
    // https://github.com/cplusplus/draft/blob/d29ef68d3c7a1c2317f4670f08bbc8a63828ce35/source/utilities.tex#L7796
    expected& operator=(const expected&) = delete;

    // Non-trivial move assignment
    // https://en.cppreference.com/w/cpp/utility/expected/operator%3D
    constexpr expected& operator=(expected&& other) noexcept(std::is_nothrow_move_assignable_v<T> &&
    std::is_nothrow_move_assignable_v<E> &&
    details::kNothrowUnionAssignable<T, E, T> &&
    details::kNothrowUnionAssignable<E, T, E>)
    requires(std::is_move_assignable_v<T> && std::is_move_assignable_v<E> && details::kUnionAssignable<T, E, T> &&
    details::kUnionAssignable<E, T, E> &&
    !(std::is_trivially_move_assignable_v<T> && std::is_trivially_move_assignable_v<E>))
    {
    assignFromExpected(std::move(other));
    return *this;
    }

    // Trivial move assignment
    // https://en.cppreference.com/w/cpp/utility/expected/operator%3D
    expected& operator=(expected&& other)
    requires(std::is_move_assignable_v<T> && std::is_move_assignable_v<E> && details::kUnionAssignable<T, E, T> &&
    details::kUnionAssignable<E, T, E> &&
    (std::is_trivially_move_assignable_v<T> && std::is_trivially_move_assignable_v<E>))
    = default;

    // Assignment from value
    // https://en.cppreference.com/w/cpp/utility/expected/operator%3D
    template <class U = T>
    constexpr expected& operator=(U&& v) noexcept(std::is_nothrow_assignable_v<T, U> &&
    details::kNothrowUnionAssignable<T, E, U>)
    requires(!kSameAsThis<U> && !details::kIsSpecializationOfExpected<U> && std::is_constructible_v<T, U> &&
    std::is_assignable_v<T&, U> && details::kUnionAssignable<T, E, U>)
    {
    if (hasValue_) {
    value_ = std::forward<U>(v);
    } else {
    details::UnionAssign(value_, error_, std::forward<U>(v));
    hasValue_ = true;
    }
    return *this;
    }

    // Copy assignment from unexpected
    // https://en.cppreference.com/w/cpp/utility/expected/operator%3D
    template <class G>
    constexpr expected& operator=(const breaded::unexpected<G>& other) noexcept(
    std::is_nothrow_assignable_v<E, const G&> && details::kNothrowUnionAssignable<E, T, const G&>)
    requires(std::is_assignable_v<E, const G&> && details::kUnionAssignable<E, T, const G&>)
    {
    if (hasValue_) {
    details::UnionAssign(error_, value_, other.error());
    hasValue_ = false;
    } else {
    error_ = other.error();
    }
    return *this;
    }

    // Move assignment from unexpected
    // https://en.cppreference.com/w/cpp/utility/expected/operator%3D
    template <class G>
    constexpr expected& operator=(breaded::unexpected<G>&& other) noexcept(std::is_nothrow_assignable_v<E, G> &&
    details::kNothrowUnionAssignable<E, T, G>)
    requires(std::is_assignable_v<E, G> && details::kUnionAssignable<E, T, G>)
    {
    if (hasValue_) {
    details::UnionAssign(error_, value_, std::move(other).error());
    hasValue_ = false;
    } else {
    error_ = std::move(other).error();
    }
    return *this;
    }
    #pragma endregion

    #pragma region Observers

    // https://en.cppreference.com/w/cpp/utility/expected/operator*
    constexpr const T* operator->() const noexcept {
    assert(hasValue_ && "Attempted to call expected::operator-> when has_value() == false");
    return std::addressof(value_);
    }

    // https://en.cppreference.com/w/cpp/utility/expected/operator*
    constexpr T* operator->() noexcept {
    assert(hasValue_ && "Attempted to call expected::operator-> when has_value() == false");
    return std::addressof(value_);
    }

    // https://en.cppreference.com/w/cpp/utility/expected/operator*
    [[nodiscard]] constexpr const T& operator*() const& noexcept {
    assert(hasValue_ && "Attempted to call expected::operator* when has_value() == false");
    return value_;
    }

    // https://en.cppreference.com/w/cpp/utility/expected/operator*
    [[nodiscard]] constexpr T& operator*() & noexcept {
    assert(hasValue_ && "Attempted to call expected::operator* when has_value() == false");
    return value_;
    }

    // https://en.cppreference.com/w/cpp/utility/expected/operator*
    [[nodiscard]] constexpr const T&& operator*() const&& noexcept {
    assert(hasValue_ && "Attempted to call expected::operator* when has_value() == false");
    return std::move(value_);
    }

    // https://en.cppreference.com/w/cpp/utility/expected/operator*
    [[nodiscard]] constexpr T&& operator*() && noexcept {
    assert(hasValue_ && "Attempted to call expected::operator* when has_value() == false");
    return std::move(value_);
    }

    // https://en.cppreference.com/w/cpp/utility/expected/operator_bool
    [[nodiscard]] constexpr explicit operator bool() const noexcept { return hasValue_; }

    // https://en.cppreference.com/w/cpp/utility/expected/operator_bool
    [[nodiscard]] constexpr bool has_value() const noexcept { return hasValue_; }

    // https://en.cppreference.com/w/cpp/utility/expected/value
    constexpr T& value() & noexcept(false) {
    if (!hasValue_) {
    throw breaded::bad_expected_access(std::as_const(error_));
    }
    return value_;
    }

    // https://en.cppreference.com/w/cpp/utility/expected/value
    constexpr const T& value() const& noexcept(false) {
    if (!hasValue_) {
    throw breaded::bad_expected_access(std::as_const(error_));
    }
    return value_;
    }

    // https://en.cppreference.com/w/cpp/utility/expected/value
    constexpr T&& value() && noexcept(false) {
    if (!hasValue_) {
    throw breaded::bad_expected_access(std::move(error_));
    }
    return std::move(value_);
    }

    // https://en.cppreference.com/w/cpp/utility/expected/value
    constexpr const T&& value() const&& noexcept(false) {
    if (!hasValue_) {
    throw breaded::bad_expected_access(std::move(error_));
    }
    return std::move(value_);
    }

    // https://en.cppreference.com/w/cpp/utility/expected/error
    [[nodiscard]] constexpr E& error() & noexcept {
    // The behavior is undefined if this->has_value() is true.
    assert(!hasValue_ && "Attempted to call expected::error when has_value() == true");
    return error_;
    }

    // https://en.cppreference.com/w/cpp/utility/expected/error
    [[nodiscard]] constexpr const E& error() const& noexcept {
    // The behavior is undefined if this->has_value() is true.
    assert(!hasValue_ && "Attempted to call expected::error when has_value() == true");
    return error_;
    }

    // https://en.cppreference.com/w/cpp/utility/expected/error
    [[nodiscard]] constexpr E&& error() && noexcept {
    // The behavior is undefined if this->has_value() is true.
    assert(!hasValue_ && "Attempted to call expected::error when has_value() == true");
    return std::move(error_);
    }

    // https://en.cppreference.com/w/cpp/utility/expected/error
    [[nodiscard]] constexpr const E&& error() const&& noexcept {
    // The behavior is undefined if this->has_value() is true.
    assert(!hasValue_ && "Attempted to call expected::error when has_value() == true");
    return std::move(error_);
    }

    // https://en.cppreference.com/w/cpp/utility/expected/value_or
    template <class U>
    requires(std::is_copy_constructible_v<T> && std::is_convertible_v<U, T>)
    [[nodiscard]] constexpr T value_or(U&& default_value) const& noexcept(std::is_nothrow_copy_constructible_v<T> &&
    std::is_nothrow_convertible_v<U, T>) {
    if (hasValue_) {
    return value_;
    }
    return std::forward<U>(default_value);
    }

    // https://en.cppreference.com/w/cpp/utility/expected/value_or
    template <class U>
    requires(std::is_move_constructible_v<T> && std::is_convertible_v<U, T>)
    [[nodiscard]] constexpr T value_or(U&& default_value) && noexcept(std::is_nothrow_move_constructible_v<T> &&
    std::is_nothrow_convertible_v<U, T>) {
    if (hasValue_) {
    return std::move(value_);
    }
    return std::forward<U>(default_value);
    }

    // https://en.cppreference.com/w/cpp/utility/expected/error_or
    template <class G = E>
    requires(std::is_copy_constructible_v<E> && std::is_convertible_v<G, E>)
    [[nodiscard]] constexpr E error_or(G&& default_value) const& noexcept(std::is_nothrow_copy_constructible_v<E> &&
    std::is_nothrow_convertible_v<G, E>) {
    if (!hasValue_) {
    return error_;
    }
    return std::forward<G>(default_value);
    }

    // https://en.cppreference.com/w/cpp/utility/expected/error_or
    template <class G = E>
    requires(std::is_move_constructible_v<E> && std::is_convertible_v<G, E>)
    [[nodiscard]] constexpr E error_or(G&& default_value) && noexcept(std::is_nothrow_move_constructible_v<E> &&
    std::is_nothrow_convertible_v<G, E>) {
    if (!hasValue_) {
    return std::move(error_);
    }
    return std::forward<G>(default_value);
    }

    #pragma endregion

    #pragma region Monadic operations

    // https://en.cppreference.com/w/cpp/utility/expected/and_then
    template <class F>
    constexpr AndThenReturn<expected&, F>::type and_then(F&& f) &
    requires(std::is_constructible_v<E, E&>)
    {
    return andThenImpl(*this, std::forward<F>(f));
    }

    // https://en.cppreference.com/w/cpp/utility/expected/and_then
    template <class F>
    constexpr AndThenReturn<const expected&, F>::type and_then(F&& f) const&
    requires(std::is_constructible_v<E, const E&>)
    {
    return andThenImpl(*this, std::forward<F>(f));
    }

    // https://en.cppreference.com/w/cpp/utility/expected/and_then
    template <class F>
    constexpr AndThenReturn<expected&&, F>::type and_then(F&& f) &&
    requires(std::is_constructible_v<E, E &&>)
    {
    return andThenImpl(std::move(*this), std::forward<F>(f));
    }

    // https://en.cppreference.com/w/cpp/utility/expected/and_then
    template <class F>
    constexpr AndThenReturn<const expected&&, F>::type and_then(F&& f) const&&
    requires(std::is_constructible_v<E, const E &&>)
    {
    return andThenImpl(std::move(*this), std::forward<F>(f));
    }

    // https://en.cppreference.com/w/cpp/utility/expected/transform
    template <class F>
    constexpr TransformReturn<expected&, F>::type transform(F&& f) &
    requires(std::is_constructible_v<E, E&>)
    {
    return transformImpl(*this, std::forward<F>(f));
    }

    // https://en.cppreference.com/w/cpp/utility/expected/transform
    template <class F>
    constexpr TransformReturn<const expected&, F>::type transform(F&& f) const&
    requires(std::is_constructible_v<E, const E&>)
    {
    return transformImpl(*this, std::forward<F>(f));
    }

    // https://en.cppreference.com/w/cpp/utility/expected/transform
    template <class F>
    constexpr TransformReturn<expected&&, F>::type transform(F&& f) &&
    requires(std::is_constructible_v<E, E &&>)
    {
    return transformImpl(std::move(*this), std::forward<F>(f));
    }

    // https://en.cppreference.com/w/cpp/utility/expected/transform
    template <class F>
    constexpr TransformReturn<const expected&&, F>::type transform(F&& f) const&&
    requires(std::is_constructible_v<E, const E &&>)
    {
    return transformImpl(std::move(*this), std::forward<F>(f));
    }

    // https://en.cppreference.com/w/cpp/utility/expected/or_else
    template <class F>
    constexpr OrElseReturn<expected&, F>::type or_else(F&& f) &
    requires(std::is_constructible_v<T, T&>)
    {
    return orElseImpl(*this, std::forward<F>(f));
    }

    // https://en.cppreference.com/w/cpp/utility/expected/or_else
    template <class F>
    constexpr OrElseReturn<const expected&, F>::type or_else(F&& f) const&
    requires(std::is_constructible_v<T, const T&>)
    {
    return orElseImpl(*this, std::forward<F>(f));
    }

    // https://en.cppreference.com/w/cpp/utility/expected/or_else
    template <class F>
    constexpr OrElseReturn<expected&&, F>::type or_else(F&& f) &&
    requires(std::is_constructible_v<T, T &&>)
    {
    return orElseImpl(std::move(*this), std::forward<F>(f));
    }

    // https://en.cppreference.com/w/cpp/utility/expected/or_else
    template <class F>
    constexpr OrElseReturn<const expected&&, F>::type or_else(F&& f) const&&
    requires(std::is_constructible_v<T, const T &&>)
    {
    return orElseImpl(std::move(*this), std::forward<F>(f));
    }

    // https://en.cppreference.com/w/cpp/utility/expected/transform_error
    template <class F>
    constexpr TransformErrorReturn<expected&, F>::type transform_error(F&& f) &
    requires(std::is_constructible_v<T, T&>)
    {
    return transformErrorImpl(*this, std::forward<F>(f));
    }

    // https://en.cppreference.com/w/cpp/utility/expected/transform_error
    template <class F>
    constexpr TransformErrorReturn<const expected&, F>::type transform_error(F&& f) const&
    requires(std::is_constructible_v<T, const T&>)
    {
    return transformErrorImpl(*this, std::forward<F>(f));
    }

    // https://en.cppreference.com/w/cpp/utility/expected/transform_error
    template <class F>
    constexpr TransformErrorReturn<expected&&, F>::type transform_error(F&& f) &&
    requires(std::is_constructible_v<T, T &&>)
    {
    return transformErrorImpl(std::move(*this), std::forward<F>(f));
    }

    // https://en.cppreference.com/w/cpp/utility/expected/transform_error
    template <class F>
    constexpr TransformErrorReturn<const expected&&, F>::type transform_error(F&& f) const&&
    requires(std::is_constructible_v<T, const T &&>)
    {
    return transformErrorImpl(std::move(*this), std::forward<F>(f));
    }

    #pragma endregion

    #pragma region Modifiers

    // https://en.cppreference.com/w/cpp/utility/expected/emplace
    template <class... Args>
    constexpr T& emplace(Args&&... args) noexcept
    requires(std::is_nothrow_constructible_v<T, Args...>)
    {
    destroy();
    std::construct_at(std::addressof(value_), std::forward<Args>(args)...);
    hasValue_ = true;
    return value_;
    }

    // https://en.cppreference.com/w/cpp/utility/expected/emplace
    template <class U, class... Args>
    constexpr T& emplace(std::initializer_list<U> il, Args&&... args) noexcept
    requires(std::is_nothrow_constructible_v<T, std::initializer_list<U>&, Args...>)
    {
    destroy();
    std::construct_at(std::addressof(value_), il, std::forward<Args>(args)...);
    hasValue_ = true;
    return value_;
    }

    // https://en.cppreference.com/w/cpp/utility/expected/swap
    constexpr void swap(expected& other) noexcept(std::is_nothrow_swappable_v<T> && std::is_nothrow_swappable_v<E> &&
    details::kNothrowUnionSwappable<T, E>)
    requires(std::is_swappable_v<T> && std::is_swappable_v<E> && details::kUnionSwappable<T, E>)
    {
    // Prefer custom swap friend function, and use move-based std::swap as a fallback
    // https://en.cppreference.com/w/cpp/language/adl
    using std::swap;
    if (hasValue_) {
    if (other.hasValue_) {
    swap(value_, other.value_);
    } else {
    details::UnionSwap(error_, other.value_, std::move(other.error_), std::move(value_));
    hasValue_ = false;
    other.hasValue_ = true;
    }
    } else {
    if (other.hasValue_) {
    other.swap(*this);
    } else {
    swap(error_, other.error_);
    }
    }
    }

    #pragma endregion Modifiers
    #pragma endregion Member functions

    #pragma region Non-member functions

    // https://en.cppreference.com/w/cpp/utility/expected/operator_cmp
    template <class T2, class E2>
    requires(!std::is_void_v<T2>)
    [[nodiscard]] friend constexpr bool operator==(const expected& lhs, const breaded::expected<T2, E2>& rhs) noexcept(
    noexcept(*lhs == *rhs) && noexcept(lhs.error() == rhs.error())) {
    if (lhs.has_value()) {
    if (rhs.has_value()) {
    return *lhs == *rhs;
    } else {
    return false;
    }
    } else {
    if (rhs.has_value()) {
    return false;
    } else {
    return lhs.error() == rhs.error();
    }
    }
    }

    // https://en.cppreference.com/w/cpp/utility/expected/operator_cmp
    template <class T2>
    [[nodiscard]] friend constexpr bool operator==(const expected& x, const T2& val) noexcept(noexcept(*x == val)) {
    if (x.hasValue_) {
    return x.value_ == val;
    } else {
    return false;
    }
    }

    // https://en.cppreference.com/w/cpp/utility/expected/operator_cmp
    template <class E2>
    [[nodiscard]] friend constexpr bool operator==(const expected& x,
    const breaded::unexpected<E2>& e) noexcept(noexcept(x.error() ==
    e.error())) {
    if (x.hasValue_) {
    return false;
    } else {
    return x.error_ == e.error();
    }
    }

    // https://en.cppreference.com/w/cpp/utility/expected/swap2
    friend constexpr void swap(expected& lhs, expected& rhs) noexcept(noexcept(lhs.swap(rhs)))
    requires(std::is_swappable_v<T> && std::is_swappable_v<E> && details::kUnionSwappable<T, E>)
    {
    lhs.swap(rhs);
    }
    #pragma endregion

    // ⚠️ Implementation detail.
    // A constructor to initialize via RVO in the monadic function implementation
    // This works even for non-moveable types
    template <class F, class... Args>
    requires(std::is_invocable_v<F, Args...>)
    constexpr explicit expected(details::in_place_from_return_t, F&& f, Args&&... args)
    : value_(std::invoke(std::forward<F>(f), std::forward<Args>(args)...)), hasValue_(true) {}

    // ⚠️ Implementation detail.
    // A constructor to initialize via RVO in the monadic function implementation
    // This works even for non-moveable types
    template <class F, class... Args>
    requires(std::is_invocable_v<F, Args...>)
    constexpr explicit expected(details::unexpect_from_return_t, F&& f, Args&&... args)
    : error_(std::invoke(std::forward<F>(f), std::forward<Args>(args)...)), hasValue_(false) {}

    private:
    template <class Other>
    constexpr void constructFromExpected(Other&& other) {
    if (other.has_value()) {
    std::construct_at(std::addressof(value_), *std::forward<Other>(other));
    } else {
    std::construct_at(std::addressof(error_), std::forward<Other>(other).error());
    }
    hasValue_ = other.has_value();
    }

    template <class Other>
    constexpr void assignFromExpected(Other&& other) {
    if (other.has_value()) {
    if (hasValue_) {
    // If this->has_value() equals other.has_value(), assigns the value contained in other.
    value_ = *std::forward<Other>(other);
    } else {
    details::UnionAssign(value_, error_, *std::forward<Other>(other));
    }
    } else {
    if (hasValue_) {
    details::UnionAssign(error_, value_, std::forward<Other>(other).error());
    } else {
    // If this->has_value() equals other.has_value(), assigns the value contained in other.
    error_ = std::forward<Other>(other).error();
    }
    }
    // If no exception was thrown, after assignment, has_value() is equal to other.has_value().
    hasValue_ = other.has_value();
    }

    constexpr void destroy() noexcept {
    if (hasValue_) {
    std::destroy_at(std::addressof(value_));
    } else {
    std::destroy_at(std::addressof(error_));
    }
    }

    template <class Self, class F>
    constexpr static AndThenReturn<Self, F>::type andThenImpl(Self&& self, F&& f) {
    if (self.hasValue_) {
    return std::invoke(std::forward<F>(f), *std::forward<Self>(self));
    } else {
    return AndThenReturn<Self, F>::type(breaded::unexpect, std::forward<Self>(self).error());
    }
    }

    template <class Self, class F>
    constexpr static TransformReturn<Self, F>::type transformImpl(Self&& self, F&& f) {
    if (self.hasValue_) {
    return TransformReturn<Self, F>::type(details::in_place_from_return, std::forward<F>(f),
    *std::forward<Self>(self));
    } else {
    return TransformReturn<Self, F>::type(breaded::unexpect, std::forward<Self>(self).error());
    }
    }

    template <class Self, class F>
    constexpr static OrElseReturn<Self, F>::type orElseImpl(Self&& self, F&& f) {
    if (self.hasValue_) {
    return OrElseReturn<Self, F>::type(*std::forward<Self>(self));
    } else {
    return std::invoke(std::forward<F>(f), std::forward<Self>(self).error());
    }
    }

    template <class Self, class F>
    constexpr static TransformErrorReturn<Self, F>::type transformErrorImpl(Self&& self, F&& f) {
    if (self.hasValue_) {
    return TransformErrorReturn<Self, F>::type(*std::forward<Self>(self));
    } else {
    return TransformErrorReturn<Self, F>::type(details::unexpect_from_return, std::forward<F>(f),
    std::forward<Self>(self).error());
    }
    }

    union {
    T value_;
    E error_;
    };
    bool hasValue_;
    };

    #pragma endregion

    #pragma region Expected void
    template <class T, class E>
    requires(std::is_void_v<T>)
    class expected<T, E> {
    // partial specialization of expected for void types
    // https://github.com/cplusplus/draft/blob/d29ef68d3c7a1c2317f4670f08bbc8a63828ce35/source/utilities.tex#L6909

    static_assert(details::ValidExpectedErrorType<E>);

    template <typename Self, typename F>
    struct AndThenReturn {
    using type = std::remove_cvref_t<std::invoke_result_t<F>>;
    };

    template <typename Self, typename F>
    struct TransformReturn {
    using URaw = std::invoke_result_t<F>;
    using U = std::remove_cvref_t<URaw>;
    using type = breaded::expected<U, E>;
    };

    template <typename Self, typename F>
    struct OrElseReturn {
    using type = std::remove_cvref_t<std::invoke_result_t<F, decltype(std::declval<Self>().error())>>;
    };

    template <typename Self, typename F>
    struct TransformErrorReturn {
    using GRaw = std::invoke_result_t<F, decltype(std::declval<Self>().error())>;
    using G = std::remove_cvref_t<GRaw>;
    using type = breaded::expected<T, G>;
    };

    public:
    #pragma region Member types
    using value_type = T;
    using error_type = E;
    using unexpected_type = breaded::unexpected<E>;
    #pragma endregion

    #pragma region Member alias templates
    // Member alias templates
    template <class U>
    using rebind = breaded::expected<U, error_type>;
    #pragma endregion

    private:
    template <class U>
    static constexpr bool kExpectedConvertibleToErrorType =
    std::is_constructible_v<unexpected_type, U&> || std::is_constructible_v<unexpected_type, U> ||
    std::is_constructible_v<unexpected_type, const U&> || std::is_constructible_v<unexpected_type, const U>;

    public:
    // Default empty constructor
    // https://en.cppreference.com/w/cpp/utility/expected/expected
    constexpr expected() noexcept : hasValue_(true) {}

    // Non-trivial copy constructor
    // https://en.cppreference.com/w/cpp/utility/expected/expected
    constexpr expected(const expected& other) noexcept(std::is_nothrow_copy_constructible_v<E>)
    requires(std::is_copy_constructible_v<E> && !std::is_trivially_copy_constructible_v<E>)
    {
    constructFromExpected(other);
    }

    // Trivial copy constructor
    // https://en.cppreference.com/w/cpp/utility/expected/expected
    expected(const expected& other)
    requires(std::is_copy_constructible_v<E> && std::is_trivially_copy_constructible_v<E>)
    = default;

    // This constructor is defined as deleted unless is_copy_constructible_v<E> is true
    // https://github.com/cplusplus/draft/blob/d29ef68d3c7a1c2317f4670f08bbc8a63828ce35/source/utilities.tex#L3373
    expected(const expected&) = delete;

    // Non-trivial move constructor
    // https://en.cppreference.com/w/cpp/utility/expected/expected
    constexpr expected(expected&& other) noexcept(std::is_nothrow_move_constructible_v<E>)
    requires(std::is_move_constructible_v<E> && !std::is_trivially_move_constructible_v<E>)
    {
    constructFromExpected(std::move(other));
    }

    // Trivial move constructor
    // https://en.cppreference.com/w/cpp/utility/expected/expected
    expected(expected&& other)
    requires(std::is_move_constructible_v<E> && std::is_trivially_move_constructible_v<E>)
    = default;

    // Converting copy constructor from expected
    // https://en.cppreference.com/w/cpp/utility/expected/expected
    template <class U, class G>
    requires(!std::is_same_v<expected, breaded::expected<U, G>> && std::is_void_v<U> &&
    std::is_constructible_v<E, const G&> && !kExpectedConvertibleToErrorType<breaded::expected<U, G>>)
    constexpr explicit(!std::is_convertible_v<const G&, E>)
    expected(const breaded::expected<U, G>& other) noexcept(std::is_nothrow_constructible_v<E, const G&>) {
    constructFromExpected(other);
    }

    // Converting move constructor from expected
    // https://en.cppreference.com/w/cpp/utility/expected/expected
    template <class U, class G>
    requires(!std::is_same_v<expected, breaded::expected<U, G>> && std::is_void_v<U> &&
    std::is_constructible_v<E, G> && !kExpectedConvertibleToErrorType<breaded::expected<U, G>>)
    constexpr explicit(!std::is_convertible_v<G, E>)
    expected(breaded::expected<U, G>&& other) noexcept(std::is_nothrow_constructible_v<E, G>) {
    constructFromExpected(std::move(other));
    }

    // Copy constructor from unexpected
    // https://en.cppreference.com/w/cpp/utility/expected/expected
    template <class G>
    requires(std::is_constructible_v<E, const G&>)
    constexpr explicit(!std::is_convertible_v<const G&, E>)
    expected(const breaded::unexpected<G>& e) noexcept(std::is_nothrow_constructible_v<E, const G&>)
    : error_(e.error()), hasValue_(false) {}

    // Move constructor from unexpected
    // https://en.cppreference.com/w/cpp/utility/expected/expected
    template <class G>
    requires(std::is_constructible_v<E, G>)
    constexpr explicit(!std::is_convertible_v<G, E>)
    expected(breaded::unexpected<G>&& e) noexcept(std::is_nothrow_constructible_v<E, G>)
    : error_(std::move(e).error()), hasValue_(false) {}

    // In-place empty constructor
    // https://en.cppreference.com/w/cpp/utility/expected/expected
    constexpr explicit expected(std::in_place_t) noexcept : hasValue_(true) {}

    // In-place error constructor from args
    // https://en.cppreference.com/w/cpp/utility/expected/expected
    template <class... Args>
    requires(std::is_constructible_v<E, Args...>)
    constexpr explicit expected(breaded::unexpect_t,
    Args&&... args) noexcept(std::is_nothrow_constructible_v<E, Args...>)
    : error_(std::forward<Args>(args)...), hasValue_(false) {}

    // In-place error constructor from initializer list
    // https://en.cppreference.com/w/cpp/utility/expected/expected
    template <class U, class... Args>
    requires(std::is_constructible_v<E, std::initializer_list<U>&, Args...>)
    constexpr explicit expected(breaded::unexpect_t, std::initializer_list<U> il, Args&&... args) noexcept(
    std::is_nothrow_constructible_v<E, std::initializer_list<U>&, Args...>)
    : error_(il, std::forward<Args>(args)...), hasValue_(false) {}

    // Non-trivial destructor
    // https://en.cppreference.com/w/cpp/utility/expected/~expected#void_partial_specialization_destructor
    constexpr ~expected() noexcept { destroy(); }

    // Trivial destructor
    // https://en.cppreference.com/w/cpp/utility/expected/~expected#void_partial_specialization_destructor
    ~expected()
    requires(std::is_trivially_destructible_v<E>)
    = default;

    #pragma region Assignment

    // Non-trivial copy assignment
    // https://en.cppreference.com/w/cpp/utility/expected/operator%3D
    constexpr expected& operator=(const expected& other) noexcept(std::is_nothrow_copy_assignable_v<E> &&
    std::is_nothrow_copy_constructible_v<E>)
    requires(std::is_copy_assignable_v<E> && std::is_copy_constructible_v<E> &&
    !std::is_trivially_copy_assignable_v<E>)
    {
    assignFromExpected(other);
    return *this;
    }

    // Trivial copy assignment
    // https://en.cppreference.com/w/cpp/utility/expected/operator%3D
    expected& operator=(const expected& other)
    requires(std::is_copy_assignable_v<E> && std::is_copy_constructible_v<E> &&
    std::is_trivially_copy_assignable_v<E>)
    = default;

    // This operator is defined as deleted unless is_copy_assignable_v<E> is true and is_copy_constructible_v<E> is true
    // https://github.com/cplusplus/draft/blob/d29ef68d3c7a1c2317f4670f08bbc8a63828ce35/source/utilities.tex#L9007
    expected& operator=(const expected&) = delete;

    // Non-trivial move assignment
    // https://en.cppreference.com/w/cpp/utility/expected/operator%3D
    constexpr expected& operator=(expected&& other) noexcept(std::is_nothrow_move_assignable_v<E> &&
    std::is_nothrow_move_constructible_v<E>)
    requires(std::is_move_assignable_v<E> && std::is_move_constructible_v<E> &&
    !std::is_trivially_move_assignable_v<E>)
    {
    assignFromExpected(std::move(other));
    return *this;
    }

    // Trivial move assignment
    // https://en.cppreference.com/w/cpp/utility/expected/operator%3D
    expected& operator=(expected&& other)
    requires(std::is_move_assignable_v<E> && std::is_move_constructible_v<E> &&
    std::is_trivially_move_assignable_v<E>)
    = default;

    // Copy assignment from unexpected
    // https://en.cppreference.com/w/cpp/utility/expected/operator%3D
    template <class G>
    constexpr expected& operator=(const breaded::unexpected<G>& other) noexcept(
    std::is_nothrow_constructible_v<E, const G&> && std::is_nothrow_assignable_v<E, const G&>)
    requires(std::is_constructible_v<E, const G&> && std::is_assignable_v<E, const G&>)
    {
    if (hasValue_) {
    std::construct_at(std::addressof(error_), other.error());
    hasValue_ = false;
    } else {
    error_ = other.error();
    }
    return *this;
    }

    // Move assignment from unexpected
    // https://en.cppreference.com/w/cpp/utility/expected/operator%3D
    template <class G>
    constexpr expected& operator=(breaded::unexpected<G>&& other) noexcept(std::is_nothrow_constructible_v<E, G> &&
    std::is_nothrow_assignable_v<E, G>)
    requires(std::is_constructible_v<E, G> && std::is_assignable_v<E, G>)
    {
    if (hasValue_) {
    std::construct_at(std::addressof(error_), std::move(other).error());
    hasValue_ = false;
    } else {
    error_ = std::move(other).error();
    }
    return *this;
    }
    #pragma endregion

    #pragma region Observers

    // https://en.cppreference.com/w/cpp/utility/expected/operator*
    constexpr void operator*() const noexcept {
    assert(hasValue_ && "Attempted to call expected::operator* when has_value() == false");
    }

    // https://en.cppreference.com/w/cpp/utility/expected/operator_bool
    [[nodiscard]] constexpr explicit operator bool() const noexcept { return hasValue_; }

    // https://en.cppreference.com/w/cpp/utility/expected/operator_bool
    [[nodiscard]] constexpr bool has_value() const noexcept { return hasValue_; }

    // https://en.cppreference.com/w/cpp/utility/expected/value
    constexpr void value() const& noexcept(false) {
    if (!hasValue_) {
    throw breaded::bad_expected_access(std::as_const(error_));
    }
    }

    // https://en.cppreference.com/w/cpp/utility/expected/value
    constexpr void value() && noexcept(false) {
    if (!hasValue_) {
    throw breaded::bad_expected_access(std::move(error_));
    }
    }

    // https://en.cppreference.com/w/cpp/utility/expected/error
    [[nodiscard]] constexpr E& error() & noexcept {
    // The behavior is undefined if this->has_value() is true.
    assert(!hasValue_ && "Attempted to call expected::error when has_value() == true");
    return error_;
    }

    // https://en.cppreference.com/w/cpp/utility/expected/error
    [[nodiscard]] constexpr const E& error() const& noexcept {
    // The behavior is undefined if this->has_value() is true.
    assert(!hasValue_ && "Attempted to call expected::error when has_value() == true");
    return error_;
    }

    // https://en.cppreference.com/w/cpp/utility/expected/error
    [[nodiscard]] constexpr E&& error() && noexcept {
    // The behavior is undefined if this->has_value() is true.
    assert(!hasValue_ && "Attempted to call expected::error when has_value() == true");
    return std::move(error_);
    }

    // https://en.cppreference.com/w/cpp/utility/expected/error
    [[nodiscard]] constexpr const E&& error() const&& noexcept {
    // The behavior is undefined if this->has_value() is true.
    assert(!hasValue_ && "Attempted to call expected::error when has_value() == true");
    return std::move(error_);
    }

    // https://en.cppreference.com/w/cpp/utility/expected/error_or
    template <class G = E>
    requires(std::is_copy_constructible_v<E> && std::is_convertible_v<G, E>)
    [[nodiscard]] constexpr E error_or(G&& default_value) const& noexcept(std::is_nothrow_copy_constructible_v<E> &&
    std::is_nothrow_convertible_v<G, E>) {
    if (!hasValue_) {
    return error_;
    }
    return std::forward<G>(default_value);
    }

    // https://en.cppreference.com/w/cpp/utility/expected/error_or
    template <class G = E>
    requires(std::is_move_constructible_v<E> && std::is_convertible_v<G, E>)
    [[nodiscard]] constexpr E error_or(G&& default_value) && noexcept(std::is_nothrow_move_constructible_v<E> &&
    std::is_nothrow_convertible_v<G, E>) {
    if (!hasValue_) {
    return std::move(error_);
    }
    return std::forward<G>(default_value);
    }

    #pragma endregion

    #pragma region Monadic operations

    // https://en.cppreference.com/w/cpp/utility/expected/and_then
    template <class F>
    constexpr AndThenReturn<expected&, F>::type and_then(F&& f) &
    requires(std::is_constructible_v<E, E&>)
    {
    return andThenImpl(*this, std::forward<F>(f));
    }

    // https://en.cppreference.com/w/cpp/utility/expected/and_then
    template <class F>
    constexpr AndThenReturn<const expected&, F>::type and_then(F&& f) const&
    requires(std::is_constructible_v<E, const E&>)
    {
    return andThenImpl(*this, std::forward<F>(f));
    }

    // https://en.cppreference.com/w/cpp/utility/expected/and_then
    template <class F>
    constexpr AndThenReturn<expected&&, F>::type and_then(F&& f) &&
    requires(std::is_constructible_v<E, E &&>)
    {
    return andThenImpl(std::move(*this), std::forward<F>(f));
    }

    // https://en.cppreference.com/w/cpp/utility/expected/and_then
    template <class F>
    constexpr AndThenReturn<const expected&&, F>::type and_then(F&& f) const&&
    requires(std::is_constructible_v<E, const E &&>)
    {
    return andThenImpl(std::move(*this), std::forward<F>(f));
    }

    // https://en.cppreference.com/w/cpp/utility/expected/transform
    template <class F>
    constexpr TransformReturn<expected&, F>::type transform(F&& f) &
    requires(std::is_constructible_v<E, E&>)
    {
    return transformImpl(*this, std::forward<F>(f));
    }

    // https://en.cppreference.com/w/cpp/utility/expected/transform
    template <class F>
    constexpr TransformReturn<const expected&, F>::type transform(F&& f) const&
    requires(std::is_constructible_v<E, const E&>)
    {
    return transformImpl(*this, std::forward<F>(f));
    }

    // https://en.cppreference.com/w/cpp/utility/expected/transform
    template <class F>
    constexpr TransformReturn<expected&&, F>::type transform(F&& f) &&
    requires(std::is_constructible_v<E, E &&>)
    {
    return transformImpl(std::move(*this), std::forward<F>(f));
    }

    // https://en.cppreference.com/w/cpp/utility/expected/transform
    template <class F>
    constexpr TransformReturn<const expected&&, F>::type transform(F&& f) const&&
    requires(std::is_constructible_v<E, const E &&>)
    {
    return transformImpl(std::move(*this), std::forward<F>(f));
    }

    // https://en.cppreference.com/w/cpp/utility/expected/or_else
    template <class F>
    constexpr OrElseReturn<expected&, F>::type or_else(F&& f) & {
    return orElseImpl(*this, std::forward<F>(f));
    }

    // https://en.cppreference.com/w/cpp/utility/expected/or_else
    template <class F>
    constexpr OrElseReturn<const expected&, F>::type or_else(F&& f) const& {
    return orElseImpl(*this, std::forward<F>(f));
    }

    // https://en.cppreference.com/w/cpp/utility/expected/or_else
    template <class F>
    constexpr OrElseReturn<expected&&, F>::type or_else(F&& f) && {
    return orElseImpl(std::move(*this), std::forward<F>(f));
    }

    // https://en.cppreference.com/w/cpp/utility/expected/or_else
    template <class F>
    constexpr OrElseReturn<const expected&&, F>::type or_else(F&& f) const&& {
    return orElseImpl(std::move(*this), std::forward<F>(f));
    }

    // https://en.cppreference.com/w/cpp/utility/expected/transform_error
    template <class F>
    constexpr TransformErrorReturn<expected&, F>::type transform_error(F&& f) & {
    return transformErrorImpl(*this, std::forward<F>(f));
    }

    // https://en.cppreference.com/w/cpp/utility/expected/transform_error
    template <class F>
    constexpr TransformErrorReturn<const expected&, F>::type transform_error(F&& f) const& {
    return transformErrorImpl(*this, std::forward<F>(f));
    }

    // https://en.cppreference.com/w/cpp/utility/expected/transform_error
    template <class F>
    constexpr TransformErrorReturn<expected&&, F>::type transform_error(F&& f) && {
    return transformErrorImpl(std::move(*this), std::forward<F>(f));
    }

    // https://en.cppreference.com/w/cpp/utility/expected/transform_error
    template <class F>
    constexpr TransformErrorReturn<const expected&&, F>::type transform_error(F&& f) const&& {
    return transformErrorImpl(std::move(*this), std::forward<F>(f));
    }

    #pragma endregion

    #pragma region Modifiers

    // https://en.cppreference.com/w/cpp/utility/expected/emplace
    constexpr void emplace() noexcept {
    destroy();
    hasValue_ = true;
    }

    // https://en.cppreference.com/w/cpp/utility/expected/swap
    constexpr void swap(expected& other) noexcept(std::is_nothrow_swappable_v<E> &&
    std::is_nothrow_move_constructible_v<E>)
    requires(std::is_swappable_v<E> && std::is_move_constructible_v<E>)
    {
    // Prefer custom swap friend function, and use move-based std::swap as a fallback
    // https://en.cppreference.com/w/cpp/language/adl
    using std::swap;
    if (hasValue_) {
    if (!other.hasValue_) {
    std::construct_at(std::addressof(error_), std::move(other.error_));
    std::destroy_at(std::addressof(other.error_));
    hasValue_ = false;
    other.hasValue_ = true;
    }
    } else {
    if (other.hasValue_) {
    other.swap(*this);
    } else {
    swap(error_, other.error_);
    }
    }
    }

    #pragma endregion

    #pragma region Non-member functions

    // https://en.cppreference.com/w/cpp/utility/expected/operator_cmp
    template <class T2, class E2>
    requires(std::is_void_v<T2>)
    [[nodiscard]] friend constexpr bool operator==(const expected& lhs, const breaded::expected<T2, E2>& rhs) noexcept(
    noexcept(lhs.error() == rhs.error())) {
    if (lhs.hasValue_) {
    return rhs.hasValue_;
    } else {
    if (rhs.hasValue_) {
    return false;
    } else {
    return lhs.error_ == rhs.error_;
    }
    }
    }

    // https://en.cppreference.com/w/cpp/utility/expected/operator_cmp
    template <class E2>
    [[nodiscard]] friend constexpr bool operator==(const expected& x,
    const breaded::unexpected<E2>& e) noexcept(noexcept(x.error() ==
    e.error())) {
    if (x.hasValue_) {
    return false;
    } else {
    return x.error_ == e.error();
    }
    }

    // https://en.cppreference.com/w/cpp/utility/expected/operator_cmp
    [[nodiscard]] friend constexpr void swap(expected& lhs, expected& rhs) noexcept(noexcept(lhs.swap(rhs)))
    requires(std::is_swappable_v<E> && std::is_move_constructible_v<E>)
    {
    lhs.swap(rhs);
    }

    #pragma endregion

    // ⚠️ Implementation detail.
    // A constructor to initialize via RVO in the monadic function implementation
    // This works even for non-moveable types
    template <class F, class... Args>
    requires(std::is_invocable_v<F, Args...>)
    constexpr explicit expected(details::in_place_from_return_t, F&& f, Args&&... args) : hasValue_(true) {
    std::invoke(std::forward<F>(f), std::forward<Args>(args)...);
    }

    // ⚠️ Implementation detail.
    // A constructor to initialize via RVO in the monadic function implementation
    // This works even for non-moveable types
    template <class F, class... Args>
    requires(std::is_invocable_v<F, Args...>)
    constexpr explicit expected(details::unexpect_from_return_t, F&& f, Args&&... args)
    : error_(std::invoke(std::forward<F>(f), std::forward<Args>(args)...)), hasValue_(false) {}

    private:
    template <class Other>
    constexpr void constructFromExpected(Other&& other) {
    if (!other.has_value()) {
    std::construct_at(std::addressof(error_), std::forward<Other>(other).error());
    }
    hasValue_ = other.has_value();
    }

    template <class Other>
    constexpr void assignFromExpected(Other&& other) {
    if (other.has_value()) {
    std::destroy_at(std::addressof(error_));
    } else {
    if (hasValue_) {
    std::construct_at(std::addressof(error_), std::forward<Other>(other).error());
    } else {
    // If this->has_value() equals other.has_value(), assigns the value contained in other.
    error_ = std::forward<Other>(other).error();
    }
    }
    // If no exception was thrown, after assignment, has_value() is equal to other.has_value().
    hasValue_ = other.has_value();
    }

    constexpr void destroy() noexcept {
    if (!hasValue_) {
    std::destroy_at(std::addressof(error_));
    }
    }

    template <class Self, class F>
    constexpr static AndThenReturn<Self, F>::type andThenImpl(Self&& self, F&& f) {
    if (self.hasValue_) {
    return std::invoke(std::forward<F>(f));
    } else {
    return AndThenReturn<Self, F>::type(breaded::unexpect, std::forward<Self>(self).error());
    }
    }

    template <class Self, class F>
    constexpr static TransformReturn<Self, F>::type transformImpl(Self&& self, F&& f) {
    if (self.hasValue_) {
    return TransformReturn<Self, F>::type(details::in_place_from_return, std::forward<F>(f));
    } else {
    return TransformReturn<Self, F>::type(breaded::unexpect, std::forward<Self>(self).error());
    }
    }

    template <class Self, class F>
    constexpr static OrElseReturn<Self, F>::type orElseImpl(Self&& self, F&& f) {
    if (self.hasValue_) {
    return OrElseReturn<Self, F>::type();
    } else {
    return std::invoke(std::forward<F>(f), std::forward<Self>(self).error());
    }
    }

    template <class Self, class F>
    constexpr static TransformErrorReturn<Self, F>::type transformErrorImpl(Self&& self, F&& f) {
    if (self.hasValue_) {
    return TransformErrorReturn<Self, F>::type();
    } else {
    return TransformErrorReturn<Self, F>::type(details::unexpect_from_return, std::forward<F>(f),
    std::forward<Self>(self).error());
    }
    }

    union {
    E error_;
    };
    bool hasValue_;
    };

    #pragma endregion

    }; // namespace breaded