// libfn — single-header amalgamation of https://github.com/libfn/functional
//
// # ISC License
//
// Copyright (c) 2024, Bronek Kozicki, Alex Kremer, Gašper Ažman
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
//
// GENERATED FILE — DO NOT EDIT. Regenerate with scripts/amalgamate.py.
// Version: 0.1.0
// Revision: v0.1.0

#ifndef INCLUDE_LIBFN_AMALGAMATED
#define INCLUDE_LIBFN_AMALGAMATED

#include <algorithm>
#include <array>
#include <cassert>
#include <compare>
#include <complex>
#include <concepts>
#include <cstddef>
#include <cstring>
#include <exception>
#include <functional>
#include <initializer_list>
#include <memory>
#include <ranges>
#include <string>
#include <string_view>
#include <tuple>
#include <type_traits>
#include <utility>
#include <version>

// ---------- BEGIN fn/and_then.hpp ----------
#ifndef INCLUDE_FN_AND_THEN
#define INCLUDE_FN_AND_THEN

// ---------- BEGIN fn/choice.hpp ----------
#ifndef INCLUDE_FN_CHOICE
#define INCLUDE_FN_CHOICE

// ---------- BEGIN fn/copack.hpp ----------
#ifndef INCLUDE_FN_COPACK
#define INCLUDE_FN_COPACK

// ---------- BEGIN fn/detail/functional.hpp ----------
#ifndef INCLUDE_FN_DETAIL_FUNCTIONAL
#define INCLUDE_FN_DETAIL_FUNCTIONAL

// ---------- BEGIN fn/detail/fwd.hpp ----------
#ifndef INCLUDE_FN_DETAIL_FWD
#define INCLUDE_FN_DETAIL_FWD

// ---------- BEGIN libfn_version.hpp ----------
#ifndef INCLUDE_LIBFN_VERSION
#define INCLUDE_LIBFN_VERSION

// Mode-less version for pfn, which never uses C++26 features.
#define LIBFN_VERSION_BASE v0_1

#ifdef LIBFN_CXX26
#define LIBFN_VERSION v0_1_cxx26
#else
#define LIBFN_VERSION v0_1
#endif

#endif // INCLUDE_LIBFN_VERSION
// ---------- END libfn_version.hpp ----------

// ---------- RESUME fn/detail/fwd.hpp ----------

namespace fn {
inline namespace LIBFN_VERSION {
// NOTE Some forward declarations can lead to hard to troubleshoot compilation
//      errors. Only declare select, useful datatypes here.

// functors
struct and_then_t;
struct discard_t;
struct transform_t;
struct transform_error_t;
struct or_else_t;
struct recover_t;
struct fail_t;
struct filter_t;
struct inspect_t;

// expected monad (Either a | b)
template <typename T, typename Err> class expected;
namespace detail {
template <typename T> constexpr bool _is_some_expected = false;
template <typename T, typename Err> constexpr bool _is_some_expected<::fn::expected<T, Err> &> = true;
template <typename T, typename Err> constexpr bool _is_some_expected<::fn::expected<T, Err> const &> = true;
template <typename T>
concept _some_expected = _is_some_expected<T &>;
} // namespace detail

// optional monad (Maybe a)
template <typename T> class optional;
namespace detail {
template <typename T> constexpr bool _is_some_optional = false;
template <typename T> constexpr bool _is_some_optional<::fn::optional<T> &> = true;
template <typename T> constexpr bool _is_some_optional<::fn::optional<T> const &> = true;
template <typename T>
concept _some_optional = _is_some_optional<T &>;
} // namespace detail

// choice monad (Copack a | ...)
template <typename... Ts> struct choice;
namespace detail {
template <typename... Ts> constexpr bool _is_some_choice = false;
template <typename... Ts> constexpr bool _is_some_choice<::fn::choice<Ts...> &> = true;
template <typename... Ts> constexpr bool _is_some_choice<::fn::choice<Ts...> const &> = true;
template <typename T>
concept _some_choice = _is_some_choice<T &>;
} // namespace detail

// identity carrier (Just a)
template <typename T> struct just;
namespace detail {
template <typename T> constexpr bool _is_some_just = false;
template <typename T> constexpr bool _is_some_just<::fn::just<T> &> = true;
template <typename T> constexpr bool _is_some_just<::fn::just<T> const &> = true;
template <typename T>
concept _some_just = _is_some_just<T &>;
} // namespace detail

// product of types
template <typename... Ts> struct pack;
namespace detail {
template <typename... Ts> constexpr bool _is_some_pack = false;
template <typename... Ts> constexpr bool _is_some_pack<::fn::pack<Ts...> &> = true;
template <typename... Ts> constexpr bool _is_some_pack<::fn::pack<Ts...> const &> = true;
template <typename T>
concept _some_pack = detail::_is_some_pack<T &>;
} // namespace detail

// co-product of types
template <typename... Ts> struct copack;
namespace detail {
template <typename... Ts> constexpr bool _is_copack = false;
template <typename... Ts> constexpr bool _is_copack<::fn::copack<Ts...> &> = true;
template <typename... Ts> constexpr bool _is_copack<::fn::copack<Ts...> const &> = true;
template <typename T>
concept _some_copack = detail::_is_copack<T &>;
} // namespace detail
} // namespace LIBFN_VERSION
} // namespace fn

#endif // INCLUDE_FN_DETAIL_FWD
// ---------- END fn/detail/fwd.hpp ----------

// ---------- RESUME fn/detail/functional.hpp ----------

// ---------- BEGIN fn/detail/meta.hpp ----------
#ifndef INCLUDE_FN_DETAIL_META
#define INCLUDE_FN_DETAIL_META

// ---------- RESUME fn/detail/meta.hpp ----------

#ifdef LIBFN_CXX26
#include <compare>
#ifndef __cpp_lib_type_order
#error "LIBFN_CXX26 requires std::type_order (C++26, feature-test macro __cpp_lib_type_order); see CONTRIBUTING.md"
#endif
#endif

namespace fn::inline LIBFN_VERSION::detail {

// TODO Remove `select_nth` when our compilers start supporting pack indexing https://wg21.link/P2662
template <::std::size_t, typename...> struct select_nth;
template <::std::size_t N> struct select_nth<N>; // Intentionally incomplete type

// MSVC has no __type_pack_element and its preprocessor rejects __has_builtin, so gate _MSC_VER first.
#if defined(_MSC_VER)
#define FN_DETAIL_HAS_TYPE_PACK_ELEMENT 0
#elif __has_builtin(__type_pack_element)
#define FN_DETAIL_HAS_TYPE_PACK_ELEMENT 1
#else
#define FN_DETAIL_HAS_TYPE_PACK_ELEMENT 0
#endif
#if FN_DETAIL_HAS_TYPE_PACK_ELEMENT
template <::std::size_t N, typename... Ts>
  requires(sizeof...(Ts) > 0)
struct select_nth<N, Ts...> {
  static_assert(N < (sizeof...(Ts)));
  using type = __type_pack_element<N, Ts...>;
};
#else
template <::std::size_t N, typename... Ts>
  requires(sizeof...(Ts) > 0)
struct select_nth<N, Ts...> {
  static_assert(N < (sizeof...(Ts)));
  using type = ::std::tuple_element_t<N, ::std::tuple<Ts...>>;
};
#endif
#undef FN_DETAIL_HAS_TYPE_PACK_ELEMENT

template <::std::size_t N, typename... Ts> using select_nth_t = select_nth<N, Ts...>::type;

// NOTE Reverse to above, i.e. mapping of a type to position in a list of types.
template <typename T> struct _indexed_type {
  ::std::size_t index;
};
template <typename... Ts> struct _indexed_type_list : _indexed_type<Ts>... {
  constexpr explicit _indexed_type_list(::std::size_t i = 0) : _indexed_type<Ts>{i++}... {}
};
template <typename T, typename... Ts>
  requires(... || ::std::is_same_v<Ts, T>)
constexpr inline ::std::size_t type_index = static_cast<_indexed_type<T> const &>(_indexed_type_list<Ts...>()).index;

template <typename T, typename... Ts> constexpr inline bool type_one_of = (... || ::std::is_same_v<Ts, T>);

#if defined(__clang__) || defined(__GNUC__)

#ifdef __clang__
static constexpr ::std::string_view _normalized_name_anon{"(anonymous namespace)"};
static constexpr ::std::string_view _normalized_name_prefix{"sortkey() [T = "};
#else
static constexpr ::std::string_view _normalized_name_anon{"{anonymous}"};
static constexpr ::std::string_view _normalized_name_prefix{"sortkey() [with T = "};
#endif
static constexpr ::std::size_t _normalized_name_TU_name_bound = 30;

template <auto TU_name, auto Input> struct _normalized_name final {
  template <::std::size_t N> static constexpr auto apply() noexcept
  {
    ::std::string_view const sv{Input.data(), Input.size()};
    ::std::size_t s = sv.find(_normalized_name_prefix);
    ::std::string_view file{TU_name.size() <= _normalized_name_TU_name_bound
                                ? TU_name.data()
                                : TU_name.data() + (TU_name.size() - _normalized_name_TU_name_bound - 1),
                            ::std::min(TU_name.size() - 1, _normalized_name_TU_name_bound)};

    ::std::string result;
    s += _normalized_name_prefix.size();
    while (true) {
      ::std::size_t i = sv.find(_normalized_name_anon, s);
      if (i != ::std::string_view::npos) {
        result.append(sv.substr(s, i - s));
        result.append(::std::string_view("(anonymous namespace in "));
        result.append(file);
        result.append(::std::string_view(")"));
      } else {
        result.append(sv.substr(s, sv.size() - s - 2));
        break;
      }
      s = i + _normalized_name_anon.size();
    };

    if constexpr (N == 0)
      return result.size();
    else {
      ::std::array<char, N> a;
      for (::std::size_t i = 0; i < result.size(); ++i) {
        a[i] = result[i];
      }
      return a;
    }
  }

  static constexpr auto _slice = apply<apply<0>()>();
  static constexpr ::std::string_view value{_slice.data(), _slice.size()};
};

namespace sortkey {
template <typename T> [[nodiscard]] static constexpr auto _make_sortkey()
{
  return _normalized_name<::std::to_array(__BASE_FILE__), ::std::to_array(__PRETTY_FUNCTION__)>::value;
}
} // namespace sortkey

#elif defined(_MSC_VER)

namespace sortkey {
// MSVC __FUNCSIG__ is "auto __cdecl fn::detail::sortkey::_make_sortkey<TYPE>(void)"; the type is the
// balanced substring between "_make_sortkey<" and the trailing ">(void)". Only used as a stable per-type
// ordering key (no anon/TU rewriting like the GCC/Clang path), so a view into __FUNCSIG__ suffices.
template <typename T> [[nodiscard]] static constexpr auto _make_sortkey() -> ::std::string_view
{
  ::std::string_view const sv{__FUNCSIG__};
  constexpr ::std::string_view prefix{"_make_sortkey<"};
  ::std::size_t const b = sv.find(prefix) + prefix.size();
  ::std::size_t const e = sv.rfind(">(void)");
  return sv.substr(b, e - b);
}
} // namespace sortkey

#else
#error "fn/detail/meta.hpp: type ordering needs __PRETTY_FUNCTION__ (GCC/Clang) or __FUNCSIG__ (MSVC)"
#endif

template <typename T> constexpr inline ::std::string_view type_sortkey_v = sortkey::_make_sortkey<T>();

// How many distinct types (by identity, not by key): a type counts unless it recurs later.
template <typename... Ts> constexpr inline ::std::size_t _distinct_types = 0;
template <typename T, typename... Ts>
constexpr inline ::std::size_t _distinct_types<T, Ts...> = _distinct_types<Ts...> + (type_one_of<T, Ts...> ? 0 : 1);

#ifdef LIBFN_CXX26
// T's rank within Ts: how many pack members order strictly below it under std::type_order.
// Ranks of distinct types differ (the order is strong and total), identical types share theirs —
// an ordering key injective by identity, where the sortkey scrape is injective only by spelling.
template <typename T, typename... Ts>
constexpr inline ::std::size_t _type_order_rank
    = (::std::size_t{0} + ... + (::std::type_order_v<Ts, T> == ::std::strong_ordering::less ? 1 : 0));
#endif

// NOTE Normalized order of types - order based on type_sortkey_v, or std::type_order in the
// LIBFN_CXX26 mode (the orders may differ, which is why the mode is a distinct ABI namespace)
template <typename... Ts> struct normalized final {
  static constexpr ::std::size_t N = sizeof...(Ts);

  struct _uniqued final {
    ::std::array<::std::size_t, N> indices;
    ::std::size_t count;
  };

  [[nodiscard]] static constexpr auto _indices() noexcept
  {
#ifdef LIBFN_CXX26
    ::std::array<::std::size_t, sizeof...(Ts)> keys{_type_order_rank<Ts, Ts...>...};
#else
    ::std::array<::std::string_view, sizeof...(Ts)> keys{type_sortkey_v<Ts>...};
#endif
    ::std::array<::std::size_t, sizeof...(Ts)> indices{};
    ::std::ranges::generate(indices, [n = 0]() mutable -> ::std::size_t { return n++; });
    auto const less = [v = &keys](::std::size_t i, ::std::size_t j) constexpr { return (*v)[i] < (*v)[j]; };
    ::std::ranges::sort(indices, less);
    auto const equal = [v = &keys](::std::size_t i, ::std::size_t j) constexpr { return (*v)[i] == (*v)[j]; };
    auto const end = ::std::ranges::unique(indices, equal).begin();
    return _uniqued{indices, static_cast<::std::size_t>(end - indices.begin())};
  }

  static constexpr _uniqued _indices_v = _indices();

  // The collision floor (#326): dedup and canonical order both rest on key injectivity, so
  // count mismatch is exactly two distinct types sharing one. Known colliders: same-scope lambdas
  // (no positional disambiguator in gcc), same-named function-local types (clang prints no scope).
  // If this assert fires, the user project should rename one of the colliding types to a unique
  // name (or move it to a different scope); or enable the LIBFN_CXX26 mode, whose rank keys
  // cannot collide
  static_assert(_distinct_types<Ts...> == _indices_v.count, "distinct types must not share a sort key");

  template <template <typename...> typename F, ::std::size_t... Is>
  static constexpr auto _normalized_f(::std::index_sequence<Is...> const &)
      -> F<select_nth_t<_indices_v.indices[Is], Ts...>...>;

  // How many unique types
  static constexpr ::std::size_t size = _indices_v.count;

  // Apply a given template on a normalized list of types
  template <template <typename...> typename F>
  using apply = decltype(_normalized_f<F>(::std::make_index_sequence<size>()));
};

template <typename... T> static constexpr bool is_superset_of = false;
template <template <typename...> typename F, typename... Ts, typename... Tu>
static constexpr bool is_superset_of<F<Ts...>, F<Tu...>> = (... && type_one_of<Tu, Ts...>);

template <typename... Tx> struct _ts final {};

template <typename... Ts> struct is_normal final {
  static constexpr auto value = ::std::is_same_v<typename normalized<Ts...>::template apply<_ts>, _ts<Ts...>>;
};

template <typename... Ts> static constexpr bool is_normal_v = is_normal<Ts...>::value;

} // namespace fn::inline LIBFN_VERSION::detail

#endif // INCLUDE_FN_DETAIL_META
// ---------- END fn/detail/meta.hpp ----------

// ---------- RESUME fn/detail/functional.hpp ----------

// ---------- RESUME fn/detail/functional.hpp ----------

// ---------- BEGIN pfn/functional.hpp ----------
#ifndef INCLUDE_PFN_FUNCTIONAL
#define INCLUDE_PFN_FUNCTIONAL

// ---------- RESUME pfn/functional.hpp ----------

namespace pfn {
inline namespace LIBFN_VERSION_BASE {

/**
 * @brief Invokes a callable and implicitly converts its result to `R`: `std::invoke_r` as
 *        specified for C++23 ([func.invoke]), for C++20 compilers
 *
 * When `R` is `void` the result is discarded, so any invocable can be called for its effects
 * alone.
 *
 * @tparam R Type the result converts to; must be spelled explicitly
 * @param f Callable to invoke
 * @param args Arguments to pass
 * @return The callable's result, converted to `R`
 */
template <class R, class F, class... Args>
  requires ::std::is_invocable_r_v<R, F, Args...>
constexpr R invoke_r(F &&f, Args &&...args) noexcept(::std::is_nothrow_invocable_r_v<R, F, Args...>)
{
  if constexpr (::std::is_void_v<R>)
    static_cast<void>(::std::invoke(static_cast<F &&>(f), static_cast<Args &&>(args)...));
  else
    return ::std::invoke(static_cast<F &&>(f), static_cast<Args &&>(args)...);
}

} // namespace LIBFN_VERSION_BASE
} // namespace pfn

#endif // INCLUDE_PFN_FUNCTIONAL
// ---------- END pfn/functional.hpp ----------

// ---------- RESUME fn/detail/functional.hpp ----------

// ---------- BEGIN pfn/tuple.hpp ----------
#ifndef INCLUDE_PFN_TUPLE
#define INCLUDE_PFN_TUPLE

// ---------- RESUME pfn/tuple.hpp ----------

namespace pfn {
inline namespace LIBFN_VERSION_BASE {
namespace detail {

// [tuple.like] is enumerative - a specialization of array, complex, pair, tuple or
// ranges::subrange - not the tuple protocol: a user type modelling the protocol does not qualify.
template <typename T> constexpr bool _is_tuple_like_specialization = false;
template <typename T, ::std::size_t N> constexpr bool _is_tuple_like_specialization<::std::array<T, N>> = true;
template <typename T> constexpr bool _is_tuple_like_specialization<::std::complex<T>> = true;
template <typename T, typename U> constexpr bool _is_tuple_like_specialization<::std::pair<T, U>> = true;
template <typename... Ts> constexpr bool _is_tuple_like_specialization<::std::tuple<Ts...>> = true;
template <typename It, typename S, ::std::ranges::subrange_kind K>
constexpr bool _is_tuple_like_specialization<::std::ranges::subrange<It, S, K>> = true;

template <typename Tuple>
concept _tuple_like = _is_tuple_like_specialization<::std::remove_cvref_t<Tuple>>;

// `complex` is enumerated tuple-like, but its tuple protocol is C++26 (P2819): where the
// underlying standard library does not provide it, the traits below answer false rather than
// error, and open up when it appears.
template <typename Tuple>
constexpr bool _tuple_sized = requires { ::std::tuple_size<::std::remove_reference_t<Tuple>>::value; };

template <typename Fn, typename Tuple, typename Ix> struct _apply_probe;
template <typename Fn, typename Tuple, ::std::size_t... Ix>
struct _apply_probe<Fn, Tuple, ::std::index_sequence<Ix...>> {
  static constexpr bool _applicable = ::std::is_invocable_v<Fn, decltype(::std::get<Ix>(::std::declval<Tuple>()))...>;
  static constexpr bool _nothrow
      = ::std::is_nothrow_invocable_v<Fn, decltype(::std::get<Ix>(::std::declval<Tuple>()))...>;
  using _apply_result = ::std::invoke_result<Fn, decltype(::std::get<Ix>(::std::declval<Tuple>()))...>;
};

template <bool, typename Fn, typename Tuple> struct _apply_gate { // not tuple-like, or protocol unavailable
  static constexpr bool _applicable = false;
  static constexpr bool _nothrow = false;
  struct _apply_result {}; // no member `type`, [meta.trans.other]
};
template <typename Fn, typename Tuple>
struct _apply_gate<true, Fn, Tuple>
    : _apply_probe<Fn, Tuple, ::std::make_index_sequence<::std::tuple_size_v<::std::remove_reference_t<Tuple>>>> {};

template <typename Fn, typename Tuple>
using _apply_traits = _apply_gate<_tuple_like<Tuple> && _tuple_sized<Tuple>, Fn, Tuple>;

template <typename Fn, typename Tuple, ::std::size_t... Ix>
constexpr decltype(auto) _apply_impl(Fn &&fn, Tuple &&t, ::std::index_sequence<Ix...>) //
    noexcept(noexcept(::std::invoke(::std::forward<Fn>(fn), ::std::get<Ix>(::std::forward<Tuple>(t))...)))
{
  return ::std::invoke(::std::forward<Fn>(fn), ::std::get<Ix>(::std::forward<Tuple>(t))...);
}

} // namespace detail

/**
 * @brief Checks if `Fn` is invocable with the elements of the tuple-like `Tuple`
 *
 * `std::is_applicable` as adopted for C++26 by P1317R2 ([meta.rel]), for C++20 compilers.
 * `Tuple` must be one of the enumerated tuple-like specializations ([tuple.like]); where the
 * underlying standard library does not provide `std::complex`'s C++26 tuple protocol (P2819),
 * a `std::complex` operand answers `false` rather than failing to compile.
 *
 * @tparam Fn Callable to probe
 * @tparam Tuple Tuple-like operand type, possibly cv-ref qualified
 */
template <typename Fn, typename Tuple>
struct is_applicable : ::std::bool_constant<detail::_apply_traits<Fn, Tuple>::_applicable> {};
/**
 * @brief Variable form of `pfn::is_applicable`
 */
template <typename Fn, typename Tuple> constexpr inline bool is_applicable_v = is_applicable<Fn, Tuple>::value;

/**
 * @brief Checks if the `pfn::is_applicable` invocation is additionally known not to throw
 *
 * `std::is_nothrow_applicable` as adopted for C++26 by P1317R2 ([meta.rel]), for C++20 compilers.
 *
 * @tparam Fn Callable to probe
 * @tparam Tuple Tuple-like operand type, possibly cv-ref qualified
 */
template <typename Fn, typename Tuple>
struct is_nothrow_applicable : ::std::bool_constant<detail::_apply_traits<Fn, Tuple>::_nothrow> {};
/**
 * @brief Variable form of `pfn::is_nothrow_applicable`
 */
template <typename Fn, typename Tuple>
constexpr inline bool is_nothrow_applicable_v = is_nothrow_applicable<Fn, Tuple>::value;

/**
 * @brief The result type of applying `Fn` to the elements of the tuple-like `Tuple`
 *
 * `std::apply_result` as adopted for C++26 by P1317R2 ([meta.trans.other]), for C++20 compilers.
 * SFINAE-friendly: no member `type` where `pfn::is_applicable` answers `false`.
 *
 * @tparam Fn Callable to probe
 * @tparam Tuple Tuple-like operand type, possibly cv-ref qualified
 */
template <typename Fn, typename Tuple> struct apply_result : detail::_apply_traits<Fn, Tuple>::_apply_result {};
/**
 * @brief Alias form of `pfn::apply_result`
 */
template <typename Fn, typename Tuple> using apply_result_t = typename apply_result<Fn, Tuple>::type;

/**
 * @brief Invokes a callable with a tuple-like operand's elements as its arguments:
 *        `std::apply` in its C++26 shape ([tuple.apply]), for C++20 compilers
 *
 * The C++26 revision (P1317R2) declares the return type as `apply_result_t` - making the
 * overload SFINAE-friendly where a deduced return is a hard error outside the immediate
 * context - and derives the exception specification from `is_nothrow_applicable`; both are
 * provided here. Accepts the enumerated tuple-like types ([tuple.like]), not the general
 * tuple protocol.
 *
 * @param fn Callable to invoke
 * @param t Tuple-like operand supplying the arguments
 * @return The callable's result
 */
template <typename Fn, detail::_tuple_like Tuple>
constexpr apply_result_t<Fn, Tuple> apply(Fn &&fn, Tuple &&t) noexcept(is_nothrow_applicable_v<Fn, Tuple>)
{
  return detail::_apply_impl(::std::forward<Fn>(fn), ::std::forward<Tuple>(t),
                             ::std::make_index_sequence<::std::tuple_size_v<::std::remove_reference_t<Tuple>>>{});
}

} // namespace LIBFN_VERSION_BASE
} // namespace pfn

#endif // INCLUDE_PFN_TUPLE
// ---------- END pfn/tuple.hpp ----------

// ---------- RESUME fn/detail/functional.hpp ----------

// ---------- BEGIN fn/detail/macro_begin.hpp ----------
// Deliberately no include guard: this header and fn/detail/macro_end.hpp bracket the section of a
// header that uses the macros below; push_macro/pop_macro make the bracketing safe under nesting
// and preserve any prior user definition.

#pragma push_macro("FWD")
#undef FWD // NOSONAR cpp:S959 saved by push_macro above

// This FWD macro is a functional equivalent to std::forward<decltype(v)>(v),
// but it saves compilation time (and typing) when used frequently.
#define FWD(...) static_cast<decltype(__VA_ARGS__) &&>(__VA_ARGS__)

#pragma push_macro("DEDUCED_RETURN")
#undef DEDUCED_RETURN // NOSONAR cpp:S959 saved by push_macro above

// Spell a function's deduced return type explicitly on MSVC only. MSVC mis-resolves a deduced
// (`auto`/`decltype(auto)`) return whose type derives from a body-local alias, leaking it as an
// opaque dependent type; an explicit trailing return type is the fix. Every other compiler keeps
// `decltype(auto)` — the natural spelling — which by construction deduces `decltype(EXPR)` on
// `return EXPR;`, so the two are the same type and this is a no-op off MSVC.
//
// Confining `decltype(EXPR)` to MSVC also keeps it off clang <= 20, which in C++23 substitutes a
// non-viable constrained overload's trailing return type BEFORE its requires-clause rejects it
// (fixed clang 21), so the explicit form would fail to compile instead of removing the non-viable
// function from the overload set.
#ifndef _MSC_VER
#define DEDUCED_RETURN(...) decltype(auto)
#else
#define DEDUCED_RETURN(...) decltype(__VA_ARGS__)
#endif
// ---------- END fn/detail/macro_begin.hpp ----------

// ---------- RESUME fn/detail/functional.hpp ----------

namespace fn::inline LIBFN_VERSION::detail {

namespace _fold_detail {
// The branch the fold takes is chosen by `if constexpr`, so a single expression cannot state its
// specification: the two untaken spellings would be ill-formed. Hence one specialization per branch.
template <typename L, typename R, typename Lv, typename Rv>
struct _nothrow_fold : ::std::bool_constant<noexcept(::fn::pack<L, R>{::std::declval<Lv>(), ::std::declval<Rv>()})> {};
template <typename L, typename R, typename Lv, typename Rv>
  requires _some_pack<L>
struct _nothrow_fold<L, R, Lv, Rv>
    : ::std::bool_constant<noexcept(::std::declval<Lv>().append(::std::in_place_type_t<R>{}, ::std::declval<Rv>()))> {};
template <typename L, typename R, typename Lv, typename Rv>
  requires(not _some_pack<L>) && _some_pack<R>
struct _nothrow_fold<L, R, Lv, Rv> : ::std::bool_constant<noexcept(::fn::pack<L>{::std::declval<Lv>()}.append(
                                         ::std::in_place_type_t<R>{}, ::std::declval<Rv>()))> {};

template <typename L, typename R>
[[nodiscard]] constexpr auto _fold(auto &&l, auto &&r) //
    noexcept(_nothrow_fold<L, R, decltype(l), decltype(r)>::value)
{
  if constexpr (_some_pack<L>) {
    return FWD(l).append(::std::in_place_type_t<R>{}, FWD(r));
  } else {
    if constexpr (_some_pack<R>) {
      return ::fn::pack<L>{FWD(l)}.append(::std::in_place_type_t<R>{}, FWD(r));
    } else {
      return ::fn::pack<L, R>{FWD(l), FWD(r)};
    }
  }
}

// Named types, not lambdas: `fold` and everything above it specify themselves in terms of what
// dispatching through these promises, and a lambda can be named neither in a noexcept-specifier nor
// (before clang 17) in any unevaluated operand at all.
template <typename R, typename Rv> struct _fold_rh final {
  Rv rv;

  template <typename L>
  [[nodiscard]] constexpr auto operator()(::std::in_place_type_t<L>, auto &&l) const
      noexcept(noexcept(_fold<L, R>(FWD(l), ::std::declval<Rv>())))
  {
    return _fold<L, R>(FWD(l), static_cast<Rv &&>(rv));
  }
};

template <typename L, typename Lv> struct _fold_lh final {
  Lv lv;

  template <typename R>
  [[nodiscard]] constexpr auto operator()(::std::in_place_type_t<R>, auto &&r) const
      noexcept(noexcept(_fold<L, R>(::std::declval<Lv>(), FWD(r))))
  {
    return _fold<L, R>(static_cast<Lv &&>(lv), FWD(r));
  }
};

template <typename Rv> struct _fold_rh_copack final {
  Rv rv;

  template <typename L>
  [[nodiscard]] constexpr auto operator()(::std::in_place_type_t<L>, auto &&l) const
      noexcept(noexcept(::std::declval<Rv>()._transform(_fold_lh<L, decltype(l)>{FWD(l)})))
  {
    return static_cast<Rv &&>(rv)._transform(_fold_lh<L, decltype(l)>{FWD(l)});
  }
};

template <typename Lh, typename Rh>
  requires _some_copack<Lh> && _some_copack<Rh>
[[nodiscard]] constexpr auto fold(auto &&lv, auto &&rv) //
    noexcept(noexcept(FWD(lv)._transform(_fold_rh_copack<decltype(rv)>{FWD(rv)})))
{
  return FWD(lv)._transform(_fold_rh_copack<decltype(rv)>{FWD(rv)});
}

template <typename Lh, typename Rh>
  requires _some_copack<Lh> && (not _some_copack<Rh>)
[[nodiscard]] constexpr auto fold(auto &&lv, auto &&rv) //
    noexcept(noexcept(FWD(lv)._transform(_fold_rh<Rh, decltype(rv)>{FWD(rv)})))
{
  return FWD(lv)._transform(_fold_rh<Rh, decltype(rv)>{FWD(rv)});
}

template <typename Lh, typename Rh>
  requires(not _some_copack<Lh>) && _some_copack<Rh>
[[nodiscard]] constexpr auto fold(auto &&lv, auto &&rv) //
    noexcept(noexcept(FWD(rv)._transform(_fold_lh<Lh, decltype(lv)>{FWD(lv)})))
{
  return FWD(rv)._transform(_fold_lh<Lh, decltype(lv)>{FWD(lv)});
}

template <typename Lh, typename Rh>
  requires(not _some_copack<Lh>) && (not _some_copack<Rh>)
[[nodiscard]] constexpr auto fold(auto &&lv, auto &&rv) //
    noexcept(noexcept(_fold<Lh, Rh>(FWD(lv), FWD(rv))))
{
  return _fold<Lh, Rh>(FWD(lv), FWD(rv));
}
} // namespace _fold_detail

namespace _apply_detail {
// Each overload's noexcept is the noexcept of what it does: `std::invoke` at the bottom, the pack's
// or copack's own `apply` when dispatching into one, and folding-then-recursing when several operands
// must be joined first (that fold constructs a pack, which can throw). The chain terminates because
// every step strictly reduces the number of pack/copack operands.
template <typename Fn, typename... Args>
  requires(not(... || (_some_pack<Args> || _some_copack<Args>))) && ::std::is_invocable_v<Fn, Args...>
[[nodiscard]] constexpr auto apply(Fn &&fn, Args &&...args) noexcept(::std::is_nothrow_invocable_v<Fn, Args...>)
    -> DEDUCED_RETURN(::std::invoke(FWD(fn), FWD(args)...))
{
  return ::std::invoke(FWD(fn), FWD(args)...);
}

// A lone tuple-like argument takes std::apply's meaning, through the machinery shared with
// pfn::apply - so fn::apply and pfn::apply agree on the entire std domain by construction, and
// the elements are terminal: they do not re-enter pack or copack dispatch (a copack element is handed
// over whole). Exactly std::apply's shape - one tuple-like argument, nothing else; composition
// with packs, copacks or further arguments is not offered. Where both this and the pass-whole
// terminal above are viable (a generic callable), this non-variadic overload wins partial
// ordering: std::apply's meaning prevails on std::apply's own domain.
template <typename Fn, typename Arg>
  requires ::pfn::detail::_tuple_like<Arg> && (::pfn::is_applicable_v<Fn, Arg>)
[[nodiscard]] constexpr auto apply(Fn &&fn, Arg &&arg) noexcept(::pfn::is_nothrow_applicable_v<Fn, Arg>)
    -> ::pfn::apply_result_t<Fn, Arg>
{
  return ::pfn::apply(FWD(fn), FWD(arg));
}

template <typename Fn, typename Arg, typename... Args>
  requires(_some_pack<Arg> || _some_copack<Arg>)
          && ((sizeof...(Args) == 0) || (not(... || (_some_pack<Args> || _some_copack<Args>))))
          && requires(Fn &&fn, Arg &&arg, Args &&...args) { FWD(arg).apply(FWD(fn), FWD(args)...); }
[[nodiscard]] constexpr auto apply(Fn &&fn, Arg &&arg, Args &&...args) //
    noexcept(noexcept(FWD(arg).apply(FWD(fn), FWD(args)...))) -> DEDUCED_RETURN(FWD(arg).apply(FWD(fn), FWD(args)...))
{
  return FWD(arg).apply(FWD(fn), FWD(args)...);
}

template <typename Fn, typename Arg, typename Arg0, typename... Args>
  requires((_some_pack<Arg0> || _some_copack<Arg0>) || ... || (_some_pack<Args> || _some_copack<Args>))
          && requires(Fn &&fn, Arg &&arg, Arg0 &&arg0, Args &&...args) {
               apply<Fn, decltype(::fn::detail::_fold_detail::fold<Arg, Arg0>(FWD(arg), FWD(arg0))), Args...>(
                   FWD(fn), ::fn::detail::_fold_detail::fold<Arg, Arg0>(FWD(arg), FWD(arg0)), FWD(args)...);
             }
// Deduced return: a trailing return type is substituted before constraints are checked, so an
// explicit one would instantiate `fold` for non-viable candidates and static_assert (a `pack` of
// rvalue refs). The body's `using type` alias is inlined only to dodge MSVC's body-local-alias leak.
[[nodiscard]] constexpr auto apply(Fn &&fn, Arg &&arg, Arg0 &&arg0, Args &&...args) //
    noexcept(noexcept(apply<Fn, decltype(::fn::detail::_fold_detail::fold<Arg, Arg0>(FWD(arg), FWD(arg0))), Args...>(
        FWD(fn), ::fn::detail::_fold_detail::fold<Arg, Arg0>(FWD(arg), FWD(arg0)), FWD(args)...))) -> decltype(auto)
{
  return apply<Fn, decltype(::fn::detail::_fold_detail::fold<Arg, Arg0>(FWD(arg), FWD(arg0))), Args...>(
      FWD(fn), ::fn::detail::_fold_detail::fold<Arg, Arg0>(FWD(arg), FWD(arg0)), FWD(args)...);
}

template <typename Ret, typename Fn, typename... Args>
  requires(not(... || (_some_pack<Args> || _some_copack<Args>))) && ::std::is_invocable_r_v<Ret, Fn, Args...>
[[nodiscard]] constexpr auto apply_r(Fn &&fn, Args &&...args) //
    noexcept(::std::is_nothrow_invocable_r_v<Ret, Fn, Args...>)
        -> DEDUCED_RETURN(::pfn::invoke_r<Ret>(FWD(fn), FWD(args)...))
{
  return ::pfn::invoke_r<Ret>(FWD(fn), FWD(args)...);
}

// The tuple-like arm of apply_r, mirroring apply's: INVOKE<R> over the elements, followed by any
// trailing arguments. Constrained so a non-viable call is a substitution failure before the
// noexcept-specifier can instantiate.
template <typename Ret, typename Fn, typename Tuple, ::std::size_t... Ix, typename... Args>
  requires ::std::is_invocable_r_v<Ret, Fn, decltype(::std::get<Ix>(::std::declval<Tuple>()))..., Args...>
constexpr Ret _apply_r_elems(Fn &&fn, Tuple &&t, ::std::index_sequence<Ix...>, Args &&...args) //
    noexcept(noexcept(::pfn::invoke_r<Ret>(FWD(fn), ::std::get<Ix>(FWD(t))..., FWD(args)...)))
{
  return ::pfn::invoke_r<Ret>(FWD(fn), ::std::get<Ix>(FWD(t))..., FWD(args)...);
}

// The INVOKE twin, serving the tagged dispatchers' tuple-like arms below.
template <typename Fn, typename Tuple, ::std::size_t... Ix, typename... Args>
  requires ::std::is_invocable_v<Fn, decltype(::std::get<Ix>(::std::declval<Tuple>()))..., Args...>
constexpr auto _apply_elems(Fn &&fn, Tuple &&t, ::std::index_sequence<Ix...>, Args &&...args) //
    noexcept(::std::is_nothrow_invocable_v<Fn, decltype(::std::get<Ix>(::std::declval<Tuple>()))..., Args...>)
        -> DEDUCED_RETURN(::std::invoke(FWD(fn), ::std::get<Ix>(FWD(t))..., FWD(args)...))
{
  return ::std::invoke(FWD(fn), ::std::get<Ix>(FWD(t))..., FWD(args)...);
}

// SFINAE-friendly elements-and-trailing-arguments traits, gated like pfn's _apply_traits: the
// tuple-like arms below must not name tuple_size raw in their declarations, which MSVC
// substitutes eagerly even for a constrained-out candidate - through the gate a non-tuple
// subject answers false (and yields no result type) instead of hard-erroring.
template <typename Fn, typename Tuple, typename Ix, typename... Args> struct _elems_probe;
template <typename Fn, typename Tuple, ::std::size_t... Ix, typename... Args>
struct _elems_probe<Fn, Tuple, ::std::index_sequence<Ix...>, Args...> {
  static constexpr bool _invocable
      = ::std::is_invocable_v<Fn, decltype(::std::get<Ix>(::std::declval<Tuple>()))..., Args...>;
  static constexpr bool _nothrow
      = ::std::is_nothrow_invocable_v<Fn, decltype(::std::get<Ix>(::std::declval<Tuple>()))..., Args...>;
  using _result = ::std::invoke_result<Fn, decltype(::std::get<Ix>(::std::declval<Tuple>()))..., Args...>;
};

template <bool, typename Fn, typename Tuple, typename... Args> struct _elems_gate { // not tuple-like
  static constexpr bool _invocable = false;
  static constexpr bool _nothrow = false;
  struct _result {}; // no member `type`, [meta.trans.other]
};
template <typename Fn, typename Tuple, typename... Args>
struct _elems_gate<true, Fn, Tuple, Args...>
    : _elems_probe<Fn, Tuple, ::std::make_index_sequence<::std::tuple_size_v<::std::remove_reference_t<Tuple>>>,
                   Args...> {};

template <typename Fn, typename Tuple, typename... Args>
using _elems_traits
    = _elems_gate<::pfn::detail::_tuple_like<Tuple> && ::pfn::detail::_tuple_sized<Tuple>, Fn, Tuple, Args...>;

template <typename Ret, typename Fn, typename Tuple, typename Ix, typename... Args> struct _elems_probe_r;
template <typename Ret, typename Fn, typename Tuple, ::std::size_t... Ix, typename... Args>
struct _elems_probe_r<Ret, Fn, Tuple, ::std::index_sequence<Ix...>, Args...> {
  static constexpr bool _invocable
      = ::std::is_invocable_r_v<Ret, Fn, decltype(::std::get<Ix>(::std::declval<Tuple>()))..., Args...>;
  static constexpr bool _nothrow
      = ::std::is_nothrow_invocable_r_v<Ret, Fn, decltype(::std::get<Ix>(::std::declval<Tuple>()))..., Args...>;
};

template <bool, typename Ret, typename Fn, typename Tuple, typename... Args> struct _elems_gate_r {
  static constexpr bool _invocable = false;
  static constexpr bool _nothrow = false;
};
template <typename Ret, typename Fn, typename Tuple, typename... Args>
struct _elems_gate_r<true, Ret, Fn, Tuple, Args...>
    : _elems_probe_r<Ret, Fn, Tuple, ::std::make_index_sequence<::std::tuple_size_v<::std::remove_reference_t<Tuple>>>,
                     Args...> {};

template <typename Ret, typename Fn, typename Tuple, typename... Args>
using _elems_traits_r
    = _elems_gate_r<::pfn::detail::_tuple_like<Tuple> && ::pfn::detail::_tuple_sized<Tuple>, Ret, Fn, Tuple, Args...>;

template <typename Ret, typename Fn, typename Arg>
  requires ::pfn::detail::_tuple_like<Arg> //
           && requires(Fn &&fn, Arg &&arg) {
                _apply_r_elems<Ret>(FWD(fn), FWD(arg),
                                    ::std::make_index_sequence<::std::tuple_size_v<::std::remove_reference_t<Arg>>>{});
              }
[[nodiscard]] constexpr auto apply_r(Fn &&fn, Arg &&arg) //
    noexcept(noexcept(_apply_r_elems<Ret>(
        FWD(fn), FWD(arg), ::std::make_index_sequence<::std::tuple_size_v<::std::remove_reference_t<Arg>>>{}))) -> Ret
{
  return _apply_r_elems<Ret>(FWD(fn), FWD(arg),
                             ::std::make_index_sequence<::std::tuple_size_v<::std::remove_reference_t<Arg>>>{});
}

template <typename Ret, typename Fn, typename Arg, typename... Args>
  requires(_some_pack<Arg> || _some_copack<Arg>)
          && ((sizeof...(Args) == 0) || (not(... || (_some_pack<Args> || _some_copack<Args>))))
          && requires(Fn &&fn, Arg &&arg, Args &&...args) { FWD(arg).template apply_r<Ret>(FWD(fn), FWD(args)...); }
[[nodiscard]] constexpr auto apply_r(Fn &&fn, Arg &&arg, Args &&...args) //
    noexcept(noexcept(FWD(arg).template apply_r<Ret>(FWD(fn), FWD(args)...)))
        -> DEDUCED_RETURN(FWD(arg).template apply_r<Ret>(FWD(fn), FWD(args)...))
{
  return FWD(arg).template apply_r<Ret>(FWD(fn), FWD(args)...);
}

template <typename Ret, typename Fn, typename Arg, typename Arg0, typename... Args>
  requires((_some_pack<Arg0> || _some_copack<Arg0>) || ... || (_some_pack<Args> || _some_copack<Args>))
          && requires(Fn &&fn, Arg &&arg, Arg0 &&arg0, Args &&...args) {
               apply_r<Ret, Fn, decltype(::fn::detail::_fold_detail::fold<Arg, Arg0>(FWD(arg), FWD(arg0))), Args...>(
                   FWD(fn), ::fn::detail::_fold_detail::fold<Arg, Arg0>(FWD(arg), FWD(arg0)), FWD(args)...);
             }
// Same as the fold-recursing `apply` above: deduced return, alias inlined.
[[nodiscard]] constexpr auto apply_r(Fn &&fn, Arg &&arg, Arg0 &&arg0, Args &&...args) //
    noexcept(
        noexcept(apply_r<Ret, Fn, decltype(::fn::detail::_fold_detail::fold<Arg, Arg0>(FWD(arg), FWD(arg0))), Args...>(
            FWD(fn), ::fn::detail::_fold_detail::fold<Arg, Arg0>(FWD(arg), FWD(arg0)), FWD(args)...))) -> decltype(auto)
{
  return apply_r<Ret, Fn, decltype(::fn::detail::_fold_detail::fold<Arg, Arg0>(FWD(arg), FWD(arg0))), Args...>(
      FWD(fn), ::fn::detail::_fold_detail::fold<Arg, Arg0>(FWD(arg), FWD(arg0)), FWD(args)...);
}
} // namespace _apply_detail

// apply_result
template <typename Fn, typename... Args>
constexpr auto _apply_result_result(Fn &&, Args &&...)
    -> ::std::type_identity<decltype(_apply_detail::apply(::std::declval<Fn>(), ::std::declval<Args>()...))>;
template <typename Fn, typename... Args> constexpr auto _apply_result_result(auto &&...) -> ::std::type_identity<void>;

template <typename Fn, typename... Args> struct _apply_result {
  using type = decltype(_apply_result_result<Fn, Args...>(::std::declval<Fn>(), ::std::declval<Args>()...))::type;
};

// is_applicable
template <typename Fn, typename... Args>
constexpr auto _is_applicable_result(Fn &&, Args &&...,
                                     ::std::type_identity<decltype(::fn::detail::_apply_detail::apply<Fn, Args...>(
                                         ::std::declval<Fn>(), ::std::declval<Args>()...))> = {}) -> ::std::true_type;
template <typename Fn, typename... Args> constexpr auto _is_applicable_result(auto &&...) -> ::std::false_type;

template <typename Fn, typename... Args> struct _is_applicable {
  static constexpr bool value
      = decltype(_is_applicable_result<Fn, Args...>(::std::declval<Fn>(), ::std::declval<Args>()...))::value;
};

// Partial-specialization gate around `_is_applicable`: MSVC doesn't short-circuit a requires-clause
// `&&`, so a guarded `_is_applicable<Fn, copack>` conjunct gets instantiated even when an earlier guard
// is already false, tripping copack's uniform-result static_assert; selecting the false_type primary
// keeps the probe out of its reach (no-op on compilers that do short-circuit).
template <bool Enable, typename Fn, typename... Args> struct _is_applicable_if : ::std::false_type {};
template <typename Fn, typename... Args> struct _is_applicable_if<true, Fn, Args...> : _is_applicable<Fn, Args...> {};

// is_applicable_r
template <typename Ret, typename Fn, typename... Args>
constexpr auto _is_applicable_r_result(
    Fn &&, Args &&...,
    ::std::type_identity<decltype(_apply_detail::apply_r<Ret>(::std::declval<Fn>(), ::std::declval<Args>()...))> = {})
    -> ::std::true_type;
template <typename Ret, typename Fn, typename... Args>
constexpr auto _is_applicable_r_result(auto &&...) -> ::std::false_type;
template <typename Ret, typename Fn, typename... Args> struct _is_applicable_r {
  static constexpr bool value
      = decltype(_is_applicable_r_result<Ret, Fn, Args...>(::std::declval<Fn>(), ::std::declval<Args>()...))::value;
};

// is_nothrow_applicable and is_nothrow_applicable_v. The apply chain above carries its own spec, so
// the question is asked of the call itself and composes through pack and copack dispatch: the answer
// for a copack operand is that every alternative's call is nothrow, and for a pack that the call over
// its elements is. The bool parameter keeps the noexcept operand out of reach when the call is not
// viable at all, where it would be ill-formed rather than false.
template <bool Enable, typename Fn, typename... Args> struct _is_nothrow_applicable_impl : ::std::false_type {};
template <typename Fn, typename... Args>
struct _is_nothrow_applicable_impl<true, Fn, Args...>
    : ::std::bool_constant<noexcept(_apply_detail::apply(::std::declval<Fn>(), ::std::declval<Args>()...))> {};

template <typename Fn, typename... Args>
struct _is_nothrow_applicable : _is_nothrow_applicable_impl<_is_applicable<Fn, Args...>::value, Fn, Args...> {};

// is_nothrow_applicable_r and is_nothrow_applicable_r_v
template <bool Enable, typename Ret, typename Fn, typename... Args>
struct _is_nothrow_applicable_r_impl : ::std::false_type {};
template <typename Ret, typename Fn, typename... Args>
struct _is_nothrow_applicable_r_impl<true, Ret, Fn, Args...>
    : ::std::bool_constant<noexcept(_apply_detail::apply_r<Ret>(::std::declval<Fn>(), ::std::declval<Args>()...))> {};

template <typename Ret, typename Fn, typename... Args>
struct _is_nothrow_applicable_r
    : _is_nothrow_applicable_r_impl<_is_applicable_r<Ret, Fn, Args...>::value, Ret, Fn, Args...> {};

// apply
template <typename Fn, typename... Args>
  requires(_is_applicable<Fn, Args...>::value)
constexpr auto _apply(Fn &&fn, Args &&...args) noexcept(_is_nothrow_applicable<Fn, Args...>::value)
    -> _apply_result<Fn, Args...>::type
{
  return _apply_detail::apply(FWD(fn), FWD(args)...);
}

// apply_r
template <typename Ret, typename Fn, typename... Args>
  requires(_is_applicable_r<Ret, Fn, Args...>::value)
constexpr auto _apply_r(Fn &&fn, Args &&...args) noexcept(_is_nothrow_applicable_r<Ret, Fn, Args...>::value) -> Ret
{
  return _apply_detail::apply_r<Ret>(FWD(fn), FWD(args)...);
}

// Named (a lambda cannot appear in a noexcept-specifier): prepends a default-constructed tag to
// the unpacked elements, one shape for every tagged surface - copack/choice apply_type below, and
// the tagged members of optional and expected.
template <typename Fn, typename Tag> struct _apply_tag_elems final {
  Fn &&fn;

  template <typename... Args>
    requires ::std::is_invocable_v<Fn, Tag, Args...>
  constexpr auto operator()(Args &&...args) && //
      noexcept(::std::is_nothrow_invocable_v<Fn, Tag, Args...>)
          -> DEDUCED_RETURN(::std::invoke(FWD(fn), Tag{}, FWD(args)...))
  {
    return ::std::invoke(FWD(fn), Tag{}, FWD(args)...);
  }
};

template <typename Fn, typename T> using _apply_type_elems = _apply_tag_elems<Fn, ::std::in_place_type_t<T>>;

// The tagged elimination of one value - the engaged/error arm of optional's and expected's
// apply_type. The tag is prepended to the value unpacked as _apply would unpack it (trailing
// arguments follow the elements), except that a tuple-like value's elements form is the row's one
// signature (no pass-whole fallback), as on copack::apply_type; a pack or copack consumes through its
// own member apply, and anything else - including a choice, a nominal boundary - is handed over
// whole.
template <typename Tag, typename Fn, typename V, typename... Args>
  requires(_some_pack<V> || _some_copack<V>) && requires(Fn &&fn, V &&v, Args &&...args) {
    FWD(v).apply(_apply_tag_elems<Fn, Tag>{FWD(fn)}, FWD(args)...);
  }
[[nodiscard]] constexpr auto _apply_tagged(Fn &&fn, V &&v, Args &&...args) //
    noexcept(noexcept(FWD(v).apply(_apply_tag_elems<Fn, Tag>{FWD(fn)}, FWD(args)...)))
        -> DEDUCED_RETURN(FWD(v).apply(_apply_tag_elems<Fn, Tag>{FWD(fn)}, FWD(args)...))
{
  return FWD(v).apply(_apply_tag_elems<Fn, Tag>{FWD(fn)}, FWD(args)...);
}

template <typename Tag, typename Fn, typename V, typename... Args>
  requires(not _some_pack<V>) && (not _some_copack<V>) && ::pfn::detail::_tuple_like<V>
          && (_apply_detail::_elems_traits<_apply_tag_elems<Fn, Tag>, V, Args...>::_invocable)
[[nodiscard]] constexpr auto _apply_tagged(Fn &&fn, V &&v, Args &&...args) //
    noexcept(_apply_detail::_elems_traits<_apply_tag_elems<Fn, Tag>, V, Args...>::_nothrow) ->
    typename _apply_detail::_elems_traits<_apply_tag_elems<Fn, Tag>, V, Args...>::_result::type
{
  return _apply_detail::_apply_elems(_apply_tag_elems<Fn, Tag>{FWD(fn)}, FWD(v),
                                     ::std::make_index_sequence<::std::tuple_size_v<::std::remove_reference_t<V>>>{},
                                     FWD(args)...);
}

// The tag is passed as a prvalue, the exact shape the traits above ask about (a named parameter
// would be an lvalue, splitting the probe from the deed).
template <typename Tag, typename Fn, typename V, typename... Args>
  requires(not _some_pack<V>) && (not _some_copack<V>) && (not ::pfn::detail::_tuple_like<V>)
          && ::std::is_invocable_v<Fn, Tag, V, Args...>
[[nodiscard]] constexpr auto _apply_tagged(Fn &&fn, V &&v, Args &&...args) //
    noexcept(::std::is_nothrow_invocable_v<Fn, Tag, V, Args...>)
        -> DEDUCED_RETURN(::std::invoke(FWD(fn), Tag{}, FWD(v), FWD(args)...))
{
  return ::std::invoke(FWD(fn), Tag{}, FWD(v), FWD(args)...);
}

template <typename Ret, typename Tag, typename Fn, typename V, typename... Args>
  requires(_some_pack<V> || _some_copack<V>) && requires(Fn &&fn, V &&v, Args &&...args) {
    FWD(v).template apply_r<Ret>(_apply_tag_elems<Fn, Tag>{FWD(fn)}, FWD(args)...);
  }
[[nodiscard]] constexpr auto _apply_tagged_r(Fn &&fn, V &&v, Args &&...args) //
    noexcept(noexcept(FWD(v).template apply_r<Ret>(_apply_tag_elems<Fn, Tag>{FWD(fn)}, FWD(args)...))) -> Ret
{
  return FWD(v).template apply_r<Ret>(_apply_tag_elems<Fn, Tag>{FWD(fn)}, FWD(args)...);
}

template <typename Ret, typename Tag, typename Fn, typename V, typename... Args>
  requires(not _some_pack<V>) && (not _some_copack<V>) && ::pfn::detail::_tuple_like<V>
          && (_apply_detail::_elems_traits_r<Ret, _apply_tag_elems<Fn, Tag>, V, Args...>::_invocable)
[[nodiscard]] constexpr auto _apply_tagged_r(Fn &&fn, V &&v, Args &&...args) //
    noexcept(_apply_detail::_elems_traits_r<Ret, _apply_tag_elems<Fn, Tag>, V, Args...>::_nothrow) -> Ret
{
  return _apply_detail::_apply_r_elems<Ret>(
      _apply_tag_elems<Fn, Tag>{FWD(fn)}, FWD(v),
      ::std::make_index_sequence<::std::tuple_size_v<::std::remove_reference_t<V>>>{}, FWD(args)...);
}

template <typename Ret, typename Tag, typename Fn, typename V, typename... Args>
  requires(not _some_pack<V>) && (not _some_copack<V>) && (not ::pfn::detail::_tuple_like<V>)
          && ::std::is_invocable_r_v<Ret, Fn, Tag, V, Args...>
[[nodiscard]] constexpr auto _apply_tagged_r(Fn &&fn, V &&v, Args &&...args) //
    noexcept(::std::is_nothrow_invocable_r_v<Ret, Fn, Tag, V, Args...>) -> Ret
{
  return ::pfn::invoke_r<Ret>(FWD(fn), Tag{}, FWD(v), FWD(args)...);
}

// The apply_type arm adapter: the type-indexed dispatch hands (tag, whole value, trailing
// arguments); this re-invokes the user's arm set with the alternative unpacked exactly as
// value-path apply would unpack it, the trailing arguments after the elements.
template <typename Fn> struct _apply_type_fn final {
  Fn &&fn;

  template <typename T, typename V, typename... Args>
  constexpr auto operator()(::std::in_place_type_t<T>, V &&v, Args &&...args) && //
      noexcept(noexcept(::std::remove_cvref_t<V>::_impl::_apply(FWD(v), _apply_type_elems<Fn, T>{FWD(fn)},
                                                                FWD(args)...)))
          -> DEDUCED_RETURN(::std::remove_cvref_t<V>::_impl::_apply(FWD(v), _apply_type_elems<Fn, T>{FWD(fn)},
                                                                    FWD(args)...))
    requires _some_pack<T> && requires {
      ::std::remove_cvref_t<V>::_impl::_apply(FWD(v), _apply_type_elems<Fn, T>{FWD(fn)}, FWD(args)...);
    }
  {
    return ::std::remove_cvref_t<V>::_impl::_apply(FWD(v), _apply_type_elems<Fn, T>{FWD(fn)}, FWD(args)...);
  }

  template <typename T, typename V, typename... Args>
  constexpr auto operator()(::std::in_place_type_t<T>, V &&v, Args &&...args) && //
      noexcept(_apply_detail::_elems_traits<_apply_type_elems<Fn, T>, V, Args...>::_nothrow) ->
      typename _apply_detail::_elems_traits<_apply_type_elems<Fn, T>, V, Args...>::_result::type
    requires(not _some_pack<T>) && ::pfn::detail::_tuple_like<T>
            && (_apply_detail::_elems_traits<_apply_type_elems<Fn, T>, V, Args...>::_invocable)
  {
    return _apply_detail::_apply_elems(_apply_type_elems<Fn, T>{FWD(fn)}, FWD(v),
                                       ::std::make_index_sequence<::std::tuple_size_v<::std::remove_reference_t<V>>>{},
                                       FWD(args)...);
  }

  // The tag is passed as a prvalue, the exact shape the traits above ask about (a named parameter
  // would be an lvalue, splitting the probe from the deed).
  template <typename T, typename V, typename... Args>
  constexpr auto operator()(::std::in_place_type_t<T>, V &&v, Args &&...args) && //
      noexcept(::std::is_nothrow_invocable_v<Fn, ::std::in_place_type_t<T>, V, Args...>)
          -> DEDUCED_RETURN(::std::invoke(FWD(fn), ::std::in_place_type_t<T>{}, FWD(v), FWD(args)...))
    requires(not _some_pack<T>) && (not ::pfn::detail::_tuple_like<T>)
            && ::std::is_invocable_v<Fn, ::std::in_place_type_t<T>, V, Args...>
  {
    return ::std::invoke(FWD(fn), ::std::in_place_type_t<T>{}, FWD(v), FWD(args)...);
  }
};

template <typename Fn, typename T, typename... Tx> constexpr inline bool _is_ts_applicable = false;
template <typename Fn, template <typename...> typename Tpl, typename... Ts, typename... Tx>
constexpr inline bool _is_ts_applicable<Fn, Tpl<Ts...> &, Tx...> = (... && _is_applicable<Fn, Ts &, Tx...>::value);
template <typename Fn, template <typename...> typename Tpl, typename... Ts, typename... Tx>
constexpr inline bool _is_ts_applicable<Fn, Tpl<Ts...> const &, Tx...>
    = (... && _is_applicable<Fn, Ts const &, Tx...>::value);
template <typename Fn, template <typename...> typename Tpl, typename... Ts, typename... Tx>
constexpr inline bool _is_ts_applicable<Fn, Tpl<Ts...> &&, Tx...> = (... && _is_applicable<Fn, Ts &&, Tx...>::value);
template <typename Fn, template <typename...> typename Tpl, typename... Ts, typename... Tx>
constexpr inline bool _is_ts_applicable<Fn, Tpl<Ts...> const &&, Tx...>
    = (... && _is_applicable<Fn, Ts const &&, Tx...>::value);
template <typename Fn, typename T, typename... Tx>
concept _typelist_applicable = _is_ts_applicable<Fn, T &&, Tx...>;

template <typename R, typename Fn, typename T, typename... Tx> constexpr inline bool _is_rts_applicable = false;
template <typename R, typename Fn, template <typename...> typename Tpl, typename... Ts, typename... Tx>
constexpr inline bool _is_rts_applicable<R, Fn, Tpl<Ts...> &, Tx...>
    = (... && _is_applicable_r<R, Fn, Ts &, Tx...>::value);
template <typename R, typename Fn, template <typename...> typename Tpl, typename... Ts, typename... Tx>
constexpr inline bool _is_rts_applicable<R, Fn, Tpl<Ts...> const &, Tx...>
    = (... && _is_applicable_r<R, Fn, Ts const &, Tx...>::value);
template <typename R, typename Fn, template <typename...> typename Tpl, typename... Ts, typename... Tx>
constexpr inline bool _is_rts_applicable<R, Fn, Tpl<Ts...> &&, Tx...>
    = (... && _is_applicable_r<R, Fn, Ts &&, Tx...>::value);
template <typename R, typename Fn, template <typename...> typename Tpl, typename... Ts, typename... Tx>
constexpr inline bool _is_rts_applicable<R, Fn, Tpl<Ts...> const &&, Tx...>
    = (... && _is_applicable_r<R, Fn, Ts const &&, Tx...>::value);
template <typename R, typename Fn, typename T, typename... Tx>
concept _typelist_applicable_r = _is_rts_applicable<R, Fn, T &&, Tx...>;

// Nothrow twins of the two folds above: a dispatch over a typelist can throw unless every
// alternative's call is nothrow, since which one runs is not known until run time.
template <typename Fn, typename T, typename... Tx> constexpr inline bool _is_nothrow_ts_applicable = false;
template <typename Fn, template <typename...> typename Tpl, typename... Ts, typename... Tx>
constexpr inline bool _is_nothrow_ts_applicable<Fn, Tpl<Ts...> &, Tx...>
    = (... && _is_nothrow_applicable<Fn, Ts &, Tx...>::value);
template <typename Fn, template <typename...> typename Tpl, typename... Ts, typename... Tx>
constexpr inline bool _is_nothrow_ts_applicable<Fn, Tpl<Ts...> const &, Tx...>
    = (... && _is_nothrow_applicable<Fn, Ts const &, Tx...>::value);
template <typename Fn, template <typename...> typename Tpl, typename... Ts, typename... Tx>
constexpr inline bool _is_nothrow_ts_applicable<Fn, Tpl<Ts...> &&, Tx...>
    = (... && _is_nothrow_applicable<Fn, Ts &&, Tx...>::value);
template <typename Fn, template <typename...> typename Tpl, typename... Ts, typename... Tx>
constexpr inline bool _is_nothrow_ts_applicable<Fn, Tpl<Ts...> const &&, Tx...>
    = (... && _is_nothrow_applicable<Fn, Ts const &&, Tx...>::value);
template <typename Fn, typename T, typename... Tx>
concept _typelist_nothrow_applicable = _is_nothrow_ts_applicable<Fn, T &&, Tx...>;

template <typename R, typename Fn, typename T, typename... Tx> constexpr inline bool _is_nothrow_rts_applicable = false;
template <typename R, typename Fn, template <typename...> typename Tpl, typename... Ts, typename... Tx>
constexpr inline bool _is_nothrow_rts_applicable<R, Fn, Tpl<Ts...> &, Tx...>
    = (... && _is_nothrow_applicable_r<R, Fn, Ts &, Tx...>::value);
template <typename R, typename Fn, template <typename...> typename Tpl, typename... Ts, typename... Tx>
constexpr inline bool _is_nothrow_rts_applicable<R, Fn, Tpl<Ts...> const &, Tx...>
    = (... && _is_nothrow_applicable_r<R, Fn, Ts const &, Tx...>::value);
template <typename R, typename Fn, template <typename...> typename Tpl, typename... Ts, typename... Tx>
constexpr inline bool _is_nothrow_rts_applicable<R, Fn, Tpl<Ts...> &&, Tx...>
    = (... && _is_nothrow_applicable_r<R, Fn, Ts &&, Tx...>::value);
template <typename R, typename Fn, template <typename...> typename Tpl, typename... Ts, typename... Tx>
constexpr inline bool _is_nothrow_rts_applicable<R, Fn, Tpl<Ts...> const &&, Tx...>
    = (... && _is_nothrow_applicable_r<R, Fn, Ts const &&, Tx...>::value);
template <typename R, typename Fn, typename T, typename... Tx>
concept _typelist_nothrow_applicable_r = _is_nothrow_rts_applicable<R, Fn, T &&, Tx...>;

} // namespace fn::inline LIBFN_VERSION::detail

// ---------- BEGIN fn/detail/macro_end.hpp ----------
// Deliberately no include guard: see fn/detail/macro_begin.hpp.

#undef FWD // NOSONAR cpp:S959 paired with the define in macro_begin.hpp
#pragma pop_macro("FWD")

#undef DEDUCED_RETURN // NOSONAR cpp:S959 paired with the define in macro_begin.hpp
#pragma pop_macro("DEDUCED_RETURN")
// ---------- END fn/detail/macro_end.hpp ----------

// ---------- RESUME fn/detail/functional.hpp ----------

#endif // INCLUDE_FN_DETAIL_FUNCTIONAL
// ---------- END fn/detail/functional.hpp ----------

// ---------- RESUME fn/copack.hpp ----------

// ---------- RESUME fn/copack.hpp ----------

// ---------- BEGIN fn/detail/traits.hpp ----------
#ifndef INCLUDE_FN_DETAIL_TRAITS
#define INCLUDE_FN_DETAIL_TRAITS

// ---------- RESUME fn/detail/traits.hpp ----------

namespace fn::inline LIBFN_VERSION::detail {

// The storage initializes an element as `T{args...}`, so a constraint on it must ask the same
// question: `is_constructible_v` spells parenthesized initialization, which for an aggregate
// performs no brace elision (`std::array<int, 3>` is not "constructible" from 3 ints) and permits
// narrowing where brace initialization rejects it. A reference element is not brace-initialized but
// bound, and `T{...}` for a reference `T` is not even a portable question to ask (gcc rejects it,
// clang accepts) - so that leg asks about the binding instead.
template <typename T, typename... Args>
concept _initializable                                                    //
    = (::std::is_reference_v<T> && ::std::is_constructible_v<T, Args...>) //
      || ((not ::std::is_reference_v<T>) && requires { T{::std::declval<Args>()...}; });

// Whether that same initialization can throw. Only instantiated for an `_initializable` T, and for
// the same reason it cannot be `is_nothrow_constructible_v`: the question is about `T{args...}`.
template <typename T, typename... Args>
struct _nothrow_init : ::std::bool_constant<noexcept(T{::std::declval<Args>()...})> {};
template <typename T, typename... Args>
  requires ::std::is_reference_v<T>
struct _nothrow_init<T, Args...> : ::std::bool_constant<::std::is_nothrow_constructible_v<T, Args...>> {};

template <typename T, typename... Args>
concept _nothrow_initializable = _initializable<T, Args...> && _nothrow_init<T, Args...>::value;

// Change any rvalue or empty value to prvalue, but leave lvalues unchanged.
// This is meant to find the type of data members which won't bind to rvalues.
template <typename T> extern T _as_value;

template <typename T> extern T _as_value<T &&>;
template <typename T>
  requires(::std::is_empty_v<T>)
extern T _as_value<T &>;
template <typename T>
  requires(!::std::is_empty_v<T>)
extern T &_as_value<T &>;

template <typename T> extern T const _as_value<T const &&>;
template <typename T>
  requires(::std::is_empty_v<T>)
extern T const _as_value<T const &>;
template <typename T>
  requires(!::std::is_empty_v<T>)
extern T const &_as_value<T const &>;

// Add const to second type, if first type is const
template <typename T, typename V> extern V _apply_const;
template <typename T, typename V> extern V const _apply_const<T const &, V>;
template <typename T, typename V> extern V const &_apply_const<T const &, V &>;
template <typename T, typename V> extern V const &&_apply_const<T const &, V &&>;

// Add lvalue reference to second type, if first type is lvalue reference
template <typename T, typename V> extern V _apply_lvalue;
template <typename T, typename V> extern V &_apply_lvalue<T &, V>;
template <typename T, typename V> extern V &_apply_lvalue<T &, V &&>;

} // namespace fn::inline LIBFN_VERSION::detail

namespace fn {
inline namespace LIBFN_VERSION {
template <typename T, typename V>
using apply_const_lvalue_t = decltype(detail::_apply_const<T &, decltype(detail::_apply_lvalue<T, V>)>);
} // namespace LIBFN_VERSION
} // namespace fn

#endif // INCLUDE_FN_DETAIL_TRAITS
// ---------- END fn/detail/traits.hpp ----------

// ---------- RESUME fn/copack.hpp ----------

// ---------- BEGIN fn/detail/variadic_union.hpp ----------
#ifndef INCLUDE_FN_DETAIL_VARIADIC_UNION
#define INCLUDE_FN_DETAIL_VARIADIC_UNION

// ---------- RESUME fn/detail/variadic_union.hpp ----------

// ---------- RESUME fn/detail/variadic_union.hpp ----------

// ---------- BEGIN pfn/utility.hpp ----------
#ifndef INCLUDE_PFN_UTILITY
#define INCLUDE_PFN_UTILITY

// ---------- RESUME pfn/utility.hpp ----------

namespace pfn {
inline namespace LIBFN_VERSION_BASE {

/**
 * @brief Marks a point of provably unreachable control flow: `std::unreachable` as specified
 *        for C++23 ([utility.undefined]), for C++20 compilers
 *
 * Reaching a call is undefined behaviour; the implementation is the compiler's own
 * unreachability intrinsic, so the optimizer may assume every path to the call site is dead.
 */
// LCOV_EXCL_START unreachable by design
[[noreturn]] inline void unreachable()
{
#if defined(__GNUC__) || defined(__clang__)
  __builtin_unreachable();
#elif defined(_MSC_VER)
  __assume(false);
#else
#error "No 'unreachable' intrinsic for this compiler"
#endif
}
// LCOV_EXCL_STOP

} // namespace LIBFN_VERSION_BASE
} // namespace pfn

#endif // INCLUDE_PFN_UTILITY
// ---------- END pfn/utility.hpp ----------

// ---------- RESUME fn/detail/variadic_union.hpp ----------

// ---------- BEGIN fn/detail/macro_begin.hpp ----------
// Deliberately no include guard: this header and fn/detail/macro_end.hpp bracket the section of a
// header that uses the macros below; push_macro/pop_macro make the bracketing safe under nesting
// and preserve any prior user definition.

#pragma push_macro("FWD")
#undef FWD // NOSONAR cpp:S959 saved by push_macro above

// This FWD macro is a functional equivalent to std::forward<decltype(v)>(v),
// but it saves compilation time (and typing) when used frequently.
#define FWD(...) static_cast<decltype(__VA_ARGS__) &&>(__VA_ARGS__)

#pragma push_macro("DEDUCED_RETURN")
#undef DEDUCED_RETURN // NOSONAR cpp:S959 saved by push_macro above

// Spell a function's deduced return type explicitly on MSVC only. MSVC mis-resolves a deduced
// (`auto`/`decltype(auto)`) return whose type derives from a body-local alias, leaking it as an
// opaque dependent type; an explicit trailing return type is the fix. Every other compiler keeps
// `decltype(auto)` — the natural spelling — which by construction deduces `decltype(EXPR)` on
// `return EXPR;`, so the two are the same type and this is a no-op off MSVC.
//
// Confining `decltype(EXPR)` to MSVC also keeps it off clang <= 20, which in C++23 substitutes a
// non-viable constrained overload's trailing return type BEFORE its requires-clause rejects it
// (fixed clang 21), so the explicit form would fail to compile instead of removing the non-viable
// function from the overload set.
#ifndef _MSC_VER
#define DEDUCED_RETURN(...) decltype(auto)
#else
#define DEDUCED_RETURN(...) decltype(__VA_ARGS__)
#endif
// ---------- END fn/detail/macro_begin.hpp ----------

// ---------- RESUME fn/detail/variadic_union.hpp ----------

namespace fn::inline LIBFN_VERSION::detail {

template <typename T> constexpr bool _is_in_place_type = false;
template <typename T> constexpr bool _is_in_place_type<::std::in_place_type_t<T> &> = true;
template <typename T> constexpr bool _is_in_place_type<::std::in_place_type_t<T> const &> = true;
template <typename T>
concept _some_in_place_type = _is_in_place_type<T &>;

// Constrained so a non-viable visitor fails overload resolution here: a deduced return would
// otherwise instantiate the body and turn the answer into a hard error.
template <typename T, typename Fn, typename... Args>
  requires ::std::is_invocable_v<Fn, ::std::in_place_type_t<T> const &, Args...>
[[nodiscard]] constexpr auto _invoke_type(Fn &&fn, Args &&...args) -> decltype(auto)
{
  return ::std::invoke(FWD(fn), ::std::in_place_type<T>, FWD(args)...);
}

template <typename T, typename Fn, typename... Args>
constexpr auto _is_type_invocable_result(
    Fn &&, Args &&...,
    ::std::type_identity<decltype(_invoke_type<T>(::std::declval<Fn>(), ::std::declval<Args>()...))> = {})
    -> ::std::true_type;
template <typename T, typename Fn, typename... Args>
constexpr auto _is_type_invocable_result(auto &&...) -> ::std::false_type;

template <typename T, typename Fn, typename... Args> struct _is_type_invocable {
  static constexpr bool value
      = decltype(_is_type_invocable_result<T, Fn, Args...>(::std::declval<Fn>(), ::std::declval<Args>()...))::value;
};

// invoke_type_result
template <typename T, typename Fn, typename... Args>
constexpr auto _invoke_type_result_result(Fn &&, Args &&...)
    -> ::std::type_identity<decltype(_invoke_type<T>(::std::declval<Fn>(), ::std::declval<Args>()...))>;
template <typename T, typename Fn, typename... Args>
constexpr auto _invoke_type_result_result(auto &&...) -> ::std::type_identity<void>;

template <typename T, typename Fn, typename... Args> struct _invoke_type_result {
  using type
      = decltype(_invoke_type_result_result<T, Fn, Args...>(::std::declval<Fn>(), ::std::declval<Args>()...))::type;
};

template <typename Fn, typename T, typename... Tx> constexpr inline bool _is_tst_invocable = false;
template <typename Fn, template <typename...> typename Tpl, typename... Ts, typename... Tx>
constexpr inline bool _is_tst_invocable<Fn, Tpl<Ts...> &, Tx...>
    = (... && _is_type_invocable<Ts, Fn, Ts &, Tx...>::value);
template <typename Fn, template <typename...> typename Tpl, typename... Ts, typename... Tx>
constexpr inline bool _is_tst_invocable<Fn, Tpl<Ts...> const &, Tx...>
    = (... && _is_type_invocable<Ts, Fn, Ts const &, Tx...>::value);
template <typename Fn, template <typename...> typename Tpl, typename... Ts, typename... Tx>
constexpr inline bool _is_tst_invocable<Fn, Tpl<Ts...> &&, Tx...>
    = (... && _is_type_invocable<Ts, Fn, Ts &&, Tx...>::value);
template <typename Fn, template <typename...> typename Tpl, typename... Ts, typename... Tx>
constexpr inline bool _is_tst_invocable<Fn, Tpl<Ts...> const &&, Tx...>
    = (... && _is_type_invocable<Ts, Fn, Ts const &&, Tx...>::value);
template <typename Fn, typename T, typename... Tx>
concept _typelist_type_invocable = _is_tst_invocable<Fn, T &&, Tx...>;

// The dispatch returns std::invoke(...)'s result as Ret: a same-type result is the returned
// prvalue itself, and any other converts as a return statement does. This asks those questions as
// type computations, and the same-type answer is a partial specialization so that no conversion
// machinery is even named - the deed consults no copy and no move, and MSVC mis-answers conversion
// questions about a union whose copy and move are constrained when they are asked inside a nested
// unevaluated context.
template <bool Same, typename Ret, typename R0>
struct _type_conversion_to : ::std::bool_constant<::std::is_convertible_v<R0, Ret>> {};
template <typename Ret, typename R0> struct _type_conversion_to<true, Ret, R0> : ::std::true_type {};

template <bool Invocable, typename T, typename Ret, typename Fn, typename... Args>
struct _type_invocable_r_gate : ::std::false_type {};
template <typename T, typename Ret, typename Fn, typename... Args>
struct _type_invocable_r_gate<true, T, Ret, Fn, Args...>
    : _type_conversion_to<::std::is_same_v<::std::invoke_result_t<Fn, ::std::in_place_type_t<T>, Args...>, Ret>, Ret,
                          ::std::invoke_result_t<Fn, ::std::in_place_type_t<T>, Args...>> {};

template <typename T, typename Ret, typename Fn, typename... Args>
struct _is_type_invocable_r : _type_invocable_r_gate<_is_type_invocable<T, Fn, Args...>::value, T, Ret, Fn, Args...> {};

template <typename R, typename Fn, typename T, typename... Tx> constexpr inline bool _is_rtst_invocable = false;
template <typename R, typename Fn, template <typename...> typename Tpl, typename... Ts, typename... Tx>
constexpr inline bool _is_rtst_invocable<R, Fn, Tpl<Ts...> &, Tx...>
    = (... && _is_type_invocable_r<Ts, R, Fn, Ts &, Tx...>::value);
template <typename R, typename Fn, template <typename...> typename Tpl, typename... Ts, typename... Tx>
constexpr inline bool _is_rtst_invocable<R, Fn, Tpl<Ts...> const &, Tx...>
    = (... && _is_type_invocable_r<Ts, R, Fn, Ts const &, Tx...>::value);
template <typename R, typename Fn, template <typename...> typename Tpl, typename... Ts, typename... Tx>
constexpr inline bool _is_rtst_invocable<R, Fn, Tpl<Ts...> &&, Tx...>
    = (... && _is_type_invocable_r<Ts, R, Fn, Ts &&, Tx...>::value);
template <typename R, typename Fn, template <typename...> typename Tpl, typename... Ts, typename... Tx>
constexpr inline bool _is_rtst_invocable<R, Fn, Tpl<Ts...> const &&, Tx...>
    = (... && _is_type_invocable_r<Ts, R, Fn, Ts const &&, Tx...>::value);
template <typename R, typename Fn, typename T, typename... Tx>
concept _typelist_type_invocable_r = _is_rtst_invocable<R, Fn, T &&, Tx...>;

// Nothrow twins: the alternative that runs is a run-time choice, so the dispatch is nothrow only if
// the call on every alternative is. These ask the std traits with the type tag in the argument
// list, and INVOKE and INVOKE<R> are exactly what the dispatch performs.
template <typename Fn, typename T, typename... Tx> constexpr inline bool _is_nothrow_tst_invocable = false;
template <typename Fn, template <typename...> typename Tpl, typename... Ts, typename... Tx>
constexpr inline bool _is_nothrow_tst_invocable<Fn, Tpl<Ts...> &, Tx...>
    = (... && ::std::is_nothrow_invocable_v<Fn, ::std::in_place_type_t<Ts>, Ts &, Tx...>);
template <typename Fn, template <typename...> typename Tpl, typename... Ts, typename... Tx>
constexpr inline bool _is_nothrow_tst_invocable<Fn, Tpl<Ts...> const &, Tx...>
    = (... && ::std::is_nothrow_invocable_v<Fn, ::std::in_place_type_t<Ts>, Ts const &, Tx...>);
template <typename Fn, template <typename...> typename Tpl, typename... Ts, typename... Tx>
constexpr inline bool _is_nothrow_tst_invocable<Fn, Tpl<Ts...> &&, Tx...>
    = (... && ::std::is_nothrow_invocable_v<Fn, ::std::in_place_type_t<Ts>, Ts &&, Tx...>);
template <typename Fn, template <typename...> typename Tpl, typename... Ts, typename... Tx>
constexpr inline bool _is_nothrow_tst_invocable<Fn, Tpl<Ts...> const &&, Tx...>
    = (... && ::std::is_nothrow_invocable_v<Fn, ::std::in_place_type_t<Ts>, Ts const &&, Tx...>);
template <typename Fn, typename T, typename... Tx>
concept _typelist_type_nothrow_invocable = _is_nothrow_tst_invocable<Fn, T &&, Tx...>;

template <typename R, typename Fn, typename T, typename... Tx> constexpr inline bool _is_nothrow_rtst_invocable = false;
template <typename R, typename Fn, template <typename...> typename Tpl, typename... Ts, typename... Tx>
constexpr inline bool _is_nothrow_rtst_invocable<R, Fn, Tpl<Ts...> &, Tx...>
    = (... && ::std::is_nothrow_invocable_r_v<R, Fn, ::std::in_place_type_t<Ts>, Ts &, Tx...>);
template <typename R, typename Fn, template <typename...> typename Tpl, typename... Ts, typename... Tx>
constexpr inline bool _is_nothrow_rtst_invocable<R, Fn, Tpl<Ts...> const &, Tx...>
    = (... && ::std::is_nothrow_invocable_r_v<R, Fn, ::std::in_place_type_t<Ts>, Ts const &, Tx...>);
template <typename R, typename Fn, template <typename...> typename Tpl, typename... Ts, typename... Tx>
constexpr inline bool _is_nothrow_rtst_invocable<R, Fn, Tpl<Ts...> &&, Tx...>
    = (... && ::std::is_nothrow_invocable_r_v<R, Fn, ::std::in_place_type_t<Ts>, Ts &&, Tx...>);
template <typename R, typename Fn, template <typename...> typename Tpl, typename... Ts, typename... Tx>
constexpr inline bool _is_nothrow_rtst_invocable<R, Fn, Tpl<Ts...> const &&, Tx...>
    = (... && ::std::is_nothrow_invocable_r_v<R, Fn, ::std::in_place_type_t<Ts>, Ts const &&, Tx...>);
template <typename R, typename Fn, typename T, typename... Tx>
concept _typelist_type_nothrow_invocable_r = _is_nothrow_rtst_invocable<R, Fn, T &&, Tx...>;

template <typename... Ts> union variadic_union;
template <> union variadic_union<>; // Intentionally incomplete

template <typename... Ts> constexpr bool _is_variadic_union = false;
template <typename... Ts> constexpr bool _is_variadic_union<variadic_union<Ts...> &> = true;
template <typename... Ts> constexpr bool _is_variadic_union<variadic_union<Ts...> const &> = true;

template <typename T>
concept some_variadic_union = _is_variadic_union<T &>;

template <typename T0> union variadic_union<T0> {
  static_assert(not _some_in_place_type<T0>);
  using t0 = T0;
  T0 v0;

  template <typename T>
  static constexpr bool has_type //
      = ::std::is_same_v<T, T0>;
  static constexpr ::std::size_t size = 1;

  template <typename T, typename... Args>
  constexpr variadic_union(::std::in_place_type_t<T>, Args &&...args) noexcept(noexcept(T{FWD(args)...}))
    requires ::std::is_same_v<T, T0> && requires { T{FWD(args)...}; }
      : v0{FWD(args)...}
  {
  }

  // The copy, move and assignment exist only in their trivial form: everything above goes through
  // the tagged constructor, `ptr_variadic_union` and per-member destruction, so the non-trivial
  // cases need none of them - and the trivial ones make the union exactly as trivial as its
  // members, for the copack to propagate.
  constexpr variadic_union(variadic_union const &)
    requires(::std::is_trivially_copy_constructible_v<T0>)
  = default;
  constexpr variadic_union(variadic_union &&)
    requires(::std::is_trivially_move_constructible_v<T0>)
  = default;
  constexpr variadic_union &operator=(variadic_union const &)
    requires(::std::is_trivially_copy_assignable_v<T0>)
  = default;
  constexpr variadic_union &operator=(variadic_union &&)
    requires(::std::is_trivially_move_assignable_v<T0>)
  = default;
  constexpr ~variadic_union()
    requires(::std::is_trivially_destructible_v<T0>)
  = default;
  // A union destroys nothing; this exists only to not be deleted when a member's destructor is
  // non-trivial, and its constrained pair above keeps the trivial case trivial.
  constexpr ~variadic_union() {} // NOSONAR cpp:S3490
};

template <typename T0, typename T1> union variadic_union<T0, T1> {
  static_assert(not _some_in_place_type<T0>);
  static_assert(not _some_in_place_type<T1>);
  static_assert(not ::std::is_same_v<T0, T1>);

  using t0 = T0;
  using t1 = T1;
  T0 v0;
  T1 v1;

  template <typename T>
  static constexpr bool has_type //
      = ::std::is_same_v<T, T0> || ::std::is_same_v<T, T1>;
  static constexpr ::std::size_t size = 2;

  template <typename T, typename... Args>
  constexpr variadic_union(::std::in_place_type_t<T>, Args &&...args) noexcept(noexcept(T{FWD(args)...}))
    requires ::std::is_same_v<T, T0> && requires { T{FWD(args)...}; }
      : v0{FWD(args)...}
  {
  }
  template <typename T, typename... Args>
  constexpr variadic_union(::std::in_place_type_t<T>, Args &&...args) noexcept(noexcept(T{FWD(args)...}))
    requires ::std::is_same_v<T, T1> && requires { T{FWD(args)...}; }
      : v1{FWD(args)...}
  {
  }

  constexpr variadic_union(variadic_union const &)
    requires(::std::is_trivially_copy_constructible_v<T0> && ::std::is_trivially_copy_constructible_v<T1>)
  = default;
  constexpr variadic_union(variadic_union &&)
    requires(::std::is_trivially_move_constructible_v<T0> && ::std::is_trivially_move_constructible_v<T1>)
  = default;
  constexpr variadic_union &operator=(variadic_union const &)
    requires(::std::is_trivially_copy_assignable_v<T0> && ::std::is_trivially_copy_assignable_v<T1>)
  = default;
  constexpr variadic_union &operator=(variadic_union &&)
    requires(::std::is_trivially_move_assignable_v<T0> && ::std::is_trivially_move_assignable_v<T1>)
  = default;
  constexpr ~variadic_union()
    requires(::std::is_trivially_destructible_v<T0> && ::std::is_trivially_destructible_v<T1>)
  = default;
  constexpr ~variadic_union() {} // NOSONAR cpp:S3490 the non-trivial pair of the constrained default
};

template <typename T0, typename T1, typename T2> union variadic_union<T0, T1, T2> {
  static_assert(not _some_in_place_type<T0>);
  static_assert(not _some_in_place_type<T1>);
  static_assert(not _some_in_place_type<T2>);
  static_assert(not ::std::is_same_v<T0, T1>);
  static_assert(not ::std::is_same_v<T0, T2>);
  static_assert(not ::std::is_same_v<T1, T2>);

  using t0 = T0;
  using t1 = T1;
  using t2 = T2;
  T0 v0;
  T1 v1;
  T2 v2;

  template <typename T>
  static constexpr bool has_type //
      = ::std::is_same_v<T, T0> || ::std::is_same_v<T, T1> || ::std::is_same_v<T, T2>;
  static constexpr ::std::size_t size = 3;

  template <typename T, typename... Args>
  constexpr variadic_union(::std::in_place_type_t<T>, Args &&...args) noexcept(noexcept(T{FWD(args)...}))
    requires ::std::is_same_v<T, T0> && requires { T{FWD(args)...}; }
      : v0{FWD(args)...}
  {
  }
  template <typename T, typename... Args>
  constexpr variadic_union(::std::in_place_type_t<T>, Args &&...args) noexcept(noexcept(T{FWD(args)...}))
    requires ::std::is_same_v<T, T1> && requires { T{FWD(args)...}; }
      : v1{FWD(args)...}
  {
  }
  template <typename T, typename... Args>
  constexpr variadic_union(::std::in_place_type_t<T>, Args &&...args) noexcept(noexcept(T{FWD(args)...}))
    requires ::std::is_same_v<T, T2> && requires { T{FWD(args)...}; }
      : v2{FWD(args)...}
  {
  }

  constexpr variadic_union(variadic_union const &)
    requires(::std::is_trivially_copy_constructible_v<T0> && ::std::is_trivially_copy_constructible_v<T1>
             && ::std::is_trivially_copy_constructible_v<T2>)
  = default;
  constexpr variadic_union(variadic_union &&)
    requires(::std::is_trivially_move_constructible_v<T0> && ::std::is_trivially_move_constructible_v<T1>
             && ::std::is_trivially_move_constructible_v<T2>)
  = default;
  constexpr variadic_union &operator=(variadic_union const &)
    requires(::std::is_trivially_copy_assignable_v<T0> && ::std::is_trivially_copy_assignable_v<T1>
             && ::std::is_trivially_copy_assignable_v<T2>)
  = default;
  constexpr variadic_union &operator=(variadic_union &&)
    requires(::std::is_trivially_move_assignable_v<T0> && ::std::is_trivially_move_assignable_v<T1>
             && ::std::is_trivially_move_assignable_v<T2>)
  = default;
  constexpr ~variadic_union()
    requires(::std::is_trivially_destructible_v<T0> && ::std::is_trivially_destructible_v<T1>
             && ::std::is_trivially_destructible_v<T2>)
  = default;
  constexpr ~variadic_union() {} // NOSONAR cpp:S3490 the non-trivial pair of the constrained default
};

template <typename T0, typename T1, typename T2, typename T3> union variadic_union<T0, T1, T2, T3> {
  static_assert(not _some_in_place_type<T0>);
  static_assert(not _some_in_place_type<T1>);
  static_assert(not _some_in_place_type<T2>);
  static_assert(not _some_in_place_type<T3>);
  static_assert(not ::std::is_same_v<T0, T1>);
  static_assert(not ::std::is_same_v<T0, T2>);
  static_assert(not ::std::is_same_v<T1, T2>);
  static_assert(not ::std::is_same_v<T0, T3>);
  static_assert(not ::std::is_same_v<T1, T3>);
  static_assert(not ::std::is_same_v<T2, T3>);

  using t0 = T0;
  using t1 = T1;
  using t2 = T2;
  using t3 = T3;
  T0 v0;
  T1 v1;
  T2 v2;
  T3 v3;

  template <typename T>
  static constexpr bool has_type //
      = ::std::is_same_v<T, T0> || ::std::is_same_v<T, T1> || ::std::is_same_v<T, T2> || ::std::is_same_v<T, T3>;
  static constexpr ::std::size_t size = 4;

  template <typename T, typename... Args>
  constexpr variadic_union(::std::in_place_type_t<T>, Args &&...args) noexcept(noexcept(T{FWD(args)...}))
    requires ::std::is_same_v<T, T0> && requires { T{FWD(args)...}; }
      : v0{FWD(args)...}
  {
  }
  template <typename T, typename... Args>
  constexpr variadic_union(::std::in_place_type_t<T>, Args &&...args) noexcept(noexcept(T{FWD(args)...}))
    requires ::std::is_same_v<T, T1> && requires { T{FWD(args)...}; }
      : v1{FWD(args)...}
  {
  }
  template <typename T, typename... Args>
  constexpr variadic_union(::std::in_place_type_t<T>, Args &&...args) noexcept(noexcept(T{FWD(args)...}))
    requires ::std::is_same_v<T, T2> && requires { T{FWD(args)...}; }
      : v2{FWD(args)...}
  {
  }
  template <typename T, typename... Args>
  constexpr variadic_union(::std::in_place_type_t<T>, Args &&...args) noexcept(noexcept(T{FWD(args)...}))
    requires ::std::is_same_v<T, T3> && requires { T{FWD(args)...}; }
      : v3{FWD(args)...}
  {
  }

  constexpr variadic_union(variadic_union const &)
    requires(::std::is_trivially_copy_constructible_v<T0> && ::std::is_trivially_copy_constructible_v<T1>
             && ::std::is_trivially_copy_constructible_v<T2> && ::std::is_trivially_copy_constructible_v<T3>)
  = default;
  constexpr variadic_union(variadic_union &&)
    requires(::std::is_trivially_move_constructible_v<T0> && ::std::is_trivially_move_constructible_v<T1>
             && ::std::is_trivially_move_constructible_v<T2> && ::std::is_trivially_move_constructible_v<T3>)
  = default;
  constexpr variadic_union &operator=(variadic_union const &)
    requires(::std::is_trivially_copy_assignable_v<T0> && ::std::is_trivially_copy_assignable_v<T1>
             && ::std::is_trivially_copy_assignable_v<T2> && ::std::is_trivially_copy_assignable_v<T3>)
  = default;
  constexpr variadic_union &operator=(variadic_union &&)
    requires(::std::is_trivially_move_assignable_v<T0> && ::std::is_trivially_move_assignable_v<T1>
             && ::std::is_trivially_move_assignable_v<T2> && ::std::is_trivially_move_assignable_v<T3>)
  = default;
  constexpr ~variadic_union()
    requires(::std::is_trivially_destructible_v<T0> && ::std::is_trivially_destructible_v<T1>
             && ::std::is_trivially_destructible_v<T2> && ::std::is_trivially_destructible_v<T3>)
  = default;
  constexpr ~variadic_union() {} // NOSONAR cpp:S3490 the non-trivial pair of the constrained default
};

template <typename T0, typename T1, typename T2, typename T3, typename... Ts>
  requires(sizeof...(Ts) > 0)
union variadic_union<T0, T1, T2, T3, Ts...> {
  static_assert(not _some_in_place_type<T0>);
  static_assert(not _some_in_place_type<T1>);
  static_assert(not _some_in_place_type<T2>);
  static_assert(not _some_in_place_type<T3>);
  static_assert((... && (not _some_in_place_type<Ts>)));
  static_assert(not ::std::is_same_v<T0, T1>);
  static_assert(not ::std::is_same_v<T0, T2>);
  static_assert(not ::std::is_same_v<T1, T2>);
  static_assert(not ::std::is_same_v<T0, T3>);
  static_assert(not ::std::is_same_v<T1, T3>);
  static_assert(not ::std::is_same_v<T2, T3>);
  static_assert(not(... || ::std::is_same_v<T0, Ts>));
  static_assert(not(... || ::std::is_same_v<T1, Ts>));
  static_assert(not(... || ::std::is_same_v<T2, Ts>));
  static_assert(not(... || ::std::is_same_v<T3, Ts>));

  using t0 = T0;
  using t1 = T1;
  using t2 = T2;
  using t3 = T3;
  using more_t = variadic_union<Ts...>;
  T0 v0;
  T1 v1;
  T2 v2;
  T3 v3;
  more_t more;

  template <typename T>
  static constexpr bool has_type //
      = ::std::is_same_v<T, T0> || ::std::is_same_v<T, T1> || ::std::is_same_v<T, T2> || ::std::is_same_v<T, T3>
        || variadic_union<Ts...>::template has_type<T>;
  static constexpr ::std::size_t size = 4 + more_t::size;

  template <typename T, typename... Args>
  constexpr variadic_union(::std::in_place_type_t<T>, Args &&...args) noexcept(noexcept(T{FWD(args)...}))
    requires ::std::is_same_v<T, T0> && requires { T{FWD(args)...}; }
      : v0{FWD(args)...}
  {
  }
  template <typename T, typename... Args>
  constexpr variadic_union(::std::in_place_type_t<T>, Args &&...args) noexcept(noexcept(T{FWD(args)...}))
    requires ::std::is_same_v<T, T1> && requires { T{FWD(args)...}; }
      : v1{FWD(args)...}
  {
  }
  template <typename T, typename... Args>
  constexpr variadic_union(::std::in_place_type_t<T>, Args &&...args) noexcept(noexcept(T{FWD(args)...}))
    requires ::std::is_same_v<T, T2> && requires { T{FWD(args)...}; }
      : v2{FWD(args)...}
  {
  }
  template <typename T, typename... Args>
  constexpr variadic_union(::std::in_place_type_t<T>, Args &&...args) noexcept(noexcept(T{FWD(args)...}))
    requires ::std::is_same_v<T, T3> && requires { T{FWD(args)...}; }
      : v3{FWD(args)...}
  {
  }
  template <typename T, typename... Args>
  constexpr variadic_union(::std::in_place_type_t<T> t, Args &&...args) //
      noexcept(noexcept(more_t(t, FWD(args)...)))
    requires(more_t::template has_type<T>) && requires { more_t(t, FWD(args)...); }
      : more(t, FWD(args)...)
  {
  }

  constexpr variadic_union(variadic_union const &)
    requires(::std::is_trivially_copy_constructible_v<T0> && ::std::is_trivially_copy_constructible_v<T1>
             && ::std::is_trivially_copy_constructible_v<T2> && ::std::is_trivially_copy_constructible_v<T3>
             && ::std::is_trivially_copy_constructible_v<more_t>)
  = default;
  constexpr variadic_union(variadic_union &&)
    requires(::std::is_trivially_move_constructible_v<T0> && ::std::is_trivially_move_constructible_v<T1>
             && ::std::is_trivially_move_constructible_v<T2> && ::std::is_trivially_move_constructible_v<T3>
             && ::std::is_trivially_move_constructible_v<more_t>)
  = default;
  constexpr variadic_union &operator=(variadic_union const &)
    requires(::std::is_trivially_copy_assignable_v<T0> && ::std::is_trivially_copy_assignable_v<T1>
             && ::std::is_trivially_copy_assignable_v<T2> && ::std::is_trivially_copy_assignable_v<T3>
             && ::std::is_trivially_copy_assignable_v<more_t>)
  = default;
  constexpr variadic_union &operator=(variadic_union &&)
    requires(::std::is_trivially_move_assignable_v<T0> && ::std::is_trivially_move_assignable_v<T1>
             && ::std::is_trivially_move_assignable_v<T2> && ::std::is_trivially_move_assignable_v<T3>
             && ::std::is_trivially_move_assignable_v<more_t>)
  = default;
  constexpr ~variadic_union()
    requires(::std::is_trivially_destructible_v<T0> && ::std::is_trivially_destructible_v<T1>
             && ::std::is_trivially_destructible_v<T2> && ::std::is_trivially_destructible_v<T3>
             && ::std::is_trivially_destructible_v<more_t>)
  = default;
  constexpr ~variadic_union() {} // NOSONAR cpp:S3490 the non-trivial pair of the constrained default
};

template <typename T, typename U>
[[nodiscard]] constexpr auto *ptr_variadic_union(some_variadic_union auto &&v) noexcept
  requires ::std::is_same_v<::std::remove_cvref_t<decltype(v)>, U> && (U::template has_type<T>)
           && ::std::is_same_v<T, typename U::t0>
{
  return &v.v0;
}

template <typename T, typename U>
[[nodiscard]] constexpr auto *ptr_variadic_union(some_variadic_union auto &&v) noexcept
  requires ::std::is_same_v<::std::remove_cvref_t<decltype(v)>, U> && (U::template has_type<T>)
           && ::std::is_same_v<T, typename U::t1>
{
  return &v.v1;
}

template <typename T, typename U>
[[nodiscard]] constexpr auto *ptr_variadic_union(some_variadic_union auto &&v) noexcept
  requires ::std::is_same_v<::std::remove_cvref_t<decltype(v)>, U> && (U::template has_type<T>)
           && ::std::is_same_v<T, typename U::t2>
{
  return &v.v2;
}

template <typename T, typename U>
[[nodiscard]] constexpr auto *ptr_variadic_union(some_variadic_union auto &&v) noexcept
  requires ::std::is_same_v<::std::remove_cvref_t<decltype(v)>, U> && (U::template has_type<T>)
           && ::std::is_same_v<T, typename U::t3>
{
  return &v.v3;
}

template <typename T, typename U>
[[nodiscard]] constexpr auto *ptr_variadic_union(some_variadic_union auto &&v) noexcept
  requires ::std::is_same_v<::std::remove_cvref_t<decltype(v)>, U> && (U::template has_type<T>)
           && (U::more_t::template has_type<T>)
{
  return ptr_variadic_union<T, typename U::more_t>(v.more);
}

#if defined(__GNUC__) && not defined(__clang__)
// gcc 12-14 at -O2 and above report the returned union as maybe-uninitialized wherever a trivially
// copyable copack is later copied whole: the inactive members' bytes are copied, never read. gcc 15
// does not.
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
#endif
template <typename T, typename U>
[[nodiscard]] constexpr U make_variadic_union(auto &&...args) noexcept(noexcept(T{FWD(args)...}))
  requires(U::template has_type<T>) && requires { T{FWD(args)...}; }
{
  return U(::std::in_place_type<T>, FWD(args)...);
}
#if defined(__GNUC__) && not defined(__clang__)
#pragma GCC diagnostic pop
#endif

// The two questions anyone above may ask about storing an alternative, asked OF the function that
// stores it rather than restated in terms of a trait. Restating is how the answer drifts from the
// deed: `make_variadic_union` brace-initializes, and `std::is_[nothrow_]constructible` is a question
// about parentheses - the two can disagree, and where they do the trait is wrong. Nothing here needs
// to know that, and nothing above needs to remember it.
template <typename U, typename T, typename... Args>
concept _makeable = requires { make_variadic_union<T, U>(::std::declval<Args>()...); };

template <typename U, typename T, typename... Args>
concept _nothrow_makeable = requires { requires noexcept(make_variadic_union<T, U>(::std::declval<Args>()...)); };

template <typename R, typename U, typename Fn, typename... Args>
[[nodiscard]] constexpr auto apply_variadic_union(some_variadic_union auto &&v, ::std::size_t index, Fn &&fn,
                                                  Args &&...args)
  requires ::std::is_same_v<::std::remove_cvref_t<decltype(v)>, U>   //
           && (U::size == 1) && (not ::std::is_same_v<void, R>)      //
           && _typelist_applicable_r<R, Fn, decltype(v), Args &&...> //
{
  if (index == 0)
    return static_cast<R>(_apply(FWD(fn), FWD(v).v0, FWD(args)...));
  ::pfn::unreachable(); // LCOV_EXCL_LINE
}

// The explicit return type makes each branch convert as a return statement: the constructors'
// lambdas return R itself, and MSVC refuses static_cast's spelling of that same-type prvalue when
// R is a union with constrained copy and move, where the return statement's guaranteed elision it
// accepts.
template <typename R, typename U, typename Fn, typename... Args>
[[nodiscard]] constexpr auto invoke_type_variadic_union(some_variadic_union auto &&v, ::std::size_t index, Fn &&fn,
                                                        Args &&...args) -> R
  requires ::std::is_same_v<::std::remove_cvref_t<decltype(v)>, U>       //
           && (U::size == 1) && (not ::std::is_same_v<void, R>)          //
           && _typelist_type_invocable_r<R, Fn, decltype(v), Args &&...> //
{
  if (index == 0)
    return _invoke_type<typename U::t0>(FWD(fn), FWD(v).v0, FWD(args)...);
  ::pfn::unreachable(); // LCOV_EXCL_LINE
}

template <typename R, typename U, typename Fn, typename... Args>
constexpr void apply_variadic_union(some_variadic_union auto &&v, ::std::size_t index, Fn &&fn, Args &&...args)
  requires ::std::is_same_v<::std::remove_cvref_t<decltype(v)>, U> //
           && (U::size == 1) && (::std::is_same_v<void, R>)        //
           && _typelist_applicable<Fn, decltype(v), Args &&...>    //
{
  if (index == 0)
    return (void)_apply(FWD(fn), FWD(v).v0, FWD(args)...);
  ::pfn::unreachable(); // LCOV_EXCL_LINE
}

template <typename R, typename U, typename Fn, typename... Args>
constexpr void invoke_type_variadic_union(some_variadic_union auto &&v, ::std::size_t index, Fn &&fn, Args &&...args)
  requires ::std::is_same_v<::std::remove_cvref_t<decltype(v)>, U>  //
           && (U::size == 1) && (::std::is_same_v<void, R>)         //
           && _typelist_type_invocable<Fn, decltype(v), Args &&...> //
{
  if (index == 0)
    return (void)_invoke_type<typename U::t0>(FWD(fn), FWD(v).v0, FWD(args)...);
  ::pfn::unreachable(); // LCOV_EXCL_LINE
}

template <typename R, typename U, typename Fn, typename... Args>
[[nodiscard]] constexpr auto apply_variadic_union(some_variadic_union auto &&v, ::std::size_t index, Fn &&fn,
                                                  Args &&...args)
  requires ::std::is_same_v<::std::remove_cvref_t<decltype(v)>, U>   //
           && (U::size == 2) && (not ::std::is_same_v<void, R>)      //
           && _typelist_applicable_r<R, Fn, decltype(v), Args &&...> //
{
  if (index == 0)
    return static_cast<R>(_apply(FWD(fn), FWD(v).v0, FWD(args)...));
  else if (index == 1)
    return static_cast<R>(_apply(FWD(fn), FWD(v).v1, FWD(args)...));
  ::pfn::unreachable(); // LCOV_EXCL_LINE
}

template <typename R, typename U, typename Fn, typename... Args>
[[nodiscard]] constexpr auto invoke_type_variadic_union(some_variadic_union auto &&v, ::std::size_t index, Fn &&fn,
                                                        Args &&...args) -> R
  requires ::std::is_same_v<::std::remove_cvref_t<decltype(v)>, U>       //
           && (U::size == 2) && (not ::std::is_same_v<void, R>)          //
           && _typelist_type_invocable_r<R, Fn, decltype(v), Args &&...> //
{
  if (index == 0)
    return _invoke_type<typename U::t0>(FWD(fn), FWD(v).v0, FWD(args)...);
  else if (index == 1)
    return _invoke_type<typename U::t1>(FWD(fn), FWD(v).v1, FWD(args)...);
  ::pfn::unreachable(); // LCOV_EXCL_LINE
}

template <typename R, typename U, typename Fn, typename... Args>
constexpr void apply_variadic_union(some_variadic_union auto &&v, ::std::size_t index, Fn &&fn, Args &&...args)
  requires ::std::is_same_v<::std::remove_cvref_t<decltype(v)>, U> //
           && (U::size == 2) && (::std::is_same_v<void, R>)        //
           && _typelist_applicable<Fn, decltype(v), Args &&...>    //
{
  if (index == 0)
    return (void)_apply(FWD(fn), FWD(v).v0, FWD(args)...);
  else if (index == 1)
    return (void)_apply(FWD(fn), FWD(v).v1, FWD(args)...);
  ::pfn::unreachable(); // LCOV_EXCL_LINE
}

template <typename R, typename U, typename Fn, typename... Args>
constexpr void invoke_type_variadic_union(some_variadic_union auto &&v, ::std::size_t index, Fn &&fn, Args &&...args)
  requires ::std::is_same_v<::std::remove_cvref_t<decltype(v)>, U>  //
           && (U::size == 2) && (::std::is_same_v<void, R>)         //
           && _typelist_type_invocable<Fn, decltype(v), Args &&...> //
{
  if (index == 0)
    return (void)_invoke_type<typename U::t0>(FWD(fn), FWD(v).v0, FWD(args)...);
  else if (index == 1)
    return (void)_invoke_type<typename U::t1>(FWD(fn), FWD(v).v1, FWD(args)...);
  ::pfn::unreachable(); // LCOV_EXCL_LINE
}

template <typename R, typename U, typename Fn, typename... Args>
[[nodiscard]] constexpr auto apply_variadic_union(some_variadic_union auto &&v, ::std::size_t index, Fn &&fn,
                                                  Args &&...args)
  requires ::std::is_same_v<::std::remove_cvref_t<decltype(v)>, U>   //
           && (U::size == 3) && (not ::std::is_same_v<void, R>)      //
           && _typelist_applicable_r<R, Fn, decltype(v), Args &&...> //
{
  if (index == 0)
    return static_cast<R>(_apply(FWD(fn), FWD(v).v0, FWD(args)...));
  else if (index == 1)
    return static_cast<R>(_apply(FWD(fn), FWD(v).v1, FWD(args)...));
  else if (index == 2)
    return static_cast<R>(_apply(FWD(fn), FWD(v).v2, FWD(args)...));
  ::pfn::unreachable(); // LCOV_EXCL_LINE
}

template <typename R, typename U, typename Fn, typename... Args>
[[nodiscard]] constexpr auto invoke_type_variadic_union(some_variadic_union auto &&v, ::std::size_t index, Fn &&fn,
                                                        Args &&...args) -> R
  requires ::std::is_same_v<::std::remove_cvref_t<decltype(v)>, U>       //
           && (U::size == 3) && (not ::std::is_same_v<void, R>)          //
           && _typelist_type_invocable_r<R, Fn, decltype(v), Args &&...> //
{
  if (index == 0)
    return _invoke_type<typename U::t0>(FWD(fn), FWD(v).v0, FWD(args)...);
  else if (index == 1)
    return _invoke_type<typename U::t1>(FWD(fn), FWD(v).v1, FWD(args)...);
  else if (index == 2)
    return _invoke_type<typename U::t2>(FWD(fn), FWD(v).v2, FWD(args)...);
  ::pfn::unreachable(); // LCOV_EXCL_LINE
}

template <typename R, typename U, typename Fn, typename... Args>
constexpr void apply_variadic_union(some_variadic_union auto &&v, ::std::size_t index, Fn &&fn, Args &&...args)
  requires ::std::is_same_v<::std::remove_cvref_t<decltype(v)>, U> //
           && (U::size == 3) && (::std::is_same_v<void, R>)        //
           && _typelist_applicable<Fn, decltype(v), Args &&...>    //
{
  if (index == 0)
    return (void)_apply(FWD(fn), FWD(v).v0, FWD(args)...);
  else if (index == 1)
    return (void)_apply(FWD(fn), FWD(v).v1, FWD(args)...);
  else if (index == 2)
    return (void)_apply(FWD(fn), FWD(v).v2, FWD(args)...);
  ::pfn::unreachable(); // LCOV_EXCL_LINE
}

template <typename R, typename U, typename Fn, typename... Args>
constexpr void invoke_type_variadic_union(some_variadic_union auto &&v, ::std::size_t index, Fn &&fn, Args &&...args)
  requires ::std::is_same_v<::std::remove_cvref_t<decltype(v)>, U>  //
           && (U::size == 3) && (::std::is_same_v<void, R>)         //
           && _typelist_type_invocable<Fn, decltype(v), Args &&...> //
{
  if (index == 0)
    return (void)_invoke_type<typename U::t0>(FWD(fn), FWD(v).v0, FWD(args)...);
  else if (index == 1)
    return (void)_invoke_type<typename U::t1>(FWD(fn), FWD(v).v1, FWD(args)...);
  else if (index == 2)
    return (void)_invoke_type<typename U::t2>(FWD(fn), FWD(v).v2, FWD(args)...);
  ::pfn::unreachable(); // LCOV_EXCL_LINE
}

template <typename R, typename U, typename Fn, typename... Args>
[[nodiscard]] constexpr auto apply_variadic_union(some_variadic_union auto &&v, ::std::size_t index, Fn &&fn,
                                                  Args &&...args)
  requires ::std::is_same_v<::std::remove_cvref_t<decltype(v)>, U>   //
           && (U::size == 4) && (not ::std::is_same_v<void, R>)      //
           && _typelist_applicable_r<R, Fn, decltype(v), Args &&...> //
{
  if (index == 0)
    return static_cast<R>(_apply(FWD(fn), FWD(v).v0, FWD(args)...));
  else if (index == 1)
    return static_cast<R>(_apply(FWD(fn), FWD(v).v1, FWD(args)...));
  else if (index == 2)
    return static_cast<R>(_apply(FWD(fn), FWD(v).v2, FWD(args)...));
  else if (index == 3)
    return static_cast<R>(_apply(FWD(fn), FWD(v).v3, FWD(args)...));
  ::pfn::unreachable(); // LCOV_EXCL_LINE
}

template <typename R, typename U, typename Fn, typename... Args>
[[nodiscard]] constexpr auto invoke_type_variadic_union(some_variadic_union auto &&v, ::std::size_t index, Fn &&fn,
                                                        Args &&...args) -> R
  requires ::std::is_same_v<::std::remove_cvref_t<decltype(v)>, U>       //
           && (U::size == 4) && (not ::std::is_same_v<void, R>)          //
           && _typelist_type_invocable_r<R, Fn, decltype(v), Args &&...> //
{
  if (index == 0)
    return _invoke_type<typename U::t0>(FWD(fn), FWD(v).v0, FWD(args)...);
  else if (index == 1)
    return _invoke_type<typename U::t1>(FWD(fn), FWD(v).v1, FWD(args)...);
  else if (index == 2)
    return _invoke_type<typename U::t2>(FWD(fn), FWD(v).v2, FWD(args)...);
  else if (index == 3)
    return _invoke_type<typename U::t3>(FWD(fn), FWD(v).v3, FWD(args)...);
  ::pfn::unreachable(); // LCOV_EXCL_LINE
}

template <typename R, typename U, typename Fn, typename... Args>
constexpr void apply_variadic_union(some_variadic_union auto &&v, ::std::size_t index, Fn &&fn, Args &&...args)
  requires ::std::is_same_v<::std::remove_cvref_t<decltype(v)>, U> //
           && (U::size == 4) && (::std::is_same_v<void, R>)        //
           && _typelist_applicable<Fn, decltype(v), Args &&...>    //
{
  if (index == 0)
    return (void)_apply(FWD(fn), FWD(v).v0, FWD(args)...);
  else if (index == 1)
    return (void)_apply(FWD(fn), FWD(v).v1, FWD(args)...);
  else if (index == 2)
    return (void)_apply(FWD(fn), FWD(v).v2, FWD(args)...);
  else if (index == 3)
    return (void)_apply(FWD(fn), FWD(v).v3, FWD(args)...);
  ::pfn::unreachable(); // LCOV_EXCL_LINE
}

template <typename R, typename U, typename Fn, typename... Args>
constexpr void invoke_type_variadic_union(some_variadic_union auto &&v, ::std::size_t index, Fn &&fn, Args &&...args)
  requires ::std::is_same_v<::std::remove_cvref_t<decltype(v)>, U>  //
           && (U::size == 4) && (::std::is_same_v<void, R>)         //
           && _typelist_type_invocable<Fn, decltype(v), Args &&...> //
{
  if (index == 0)
    return (void)_invoke_type<typename U::t0>(FWD(fn), FWD(v).v0, FWD(args)...);
  else if (index == 1)
    return (void)_invoke_type<typename U::t1>(FWD(fn), FWD(v).v1, FWD(args)...);
  else if (index == 2)
    return (void)_invoke_type<typename U::t2>(FWD(fn), FWD(v).v2, FWD(args)...);
  else if (index == 3)
    return (void)_invoke_type<typename U::t3>(FWD(fn), FWD(v).v3, FWD(args)...);
  ::pfn::unreachable(); // LCOV_EXCL_LINE
}

template <typename R, typename U, typename Fn, typename... Args>
[[nodiscard]] constexpr auto apply_variadic_union(some_variadic_union auto &&v, ::std::size_t index, Fn &&fn,
                                                  Args &&...args)
  requires ::std::is_same_v<::std::remove_cvref_t<decltype(v)>, U>   //
           && (U::size > 4) && (not ::std::is_same_v<void, R>)       //
           && _typelist_applicable_r<R, Fn, decltype(v), Args &&...> //
{
  if (index == 0)
    return static_cast<R>(_apply(FWD(fn), FWD(v).v0, FWD(args)...));
  else if (index == 1)
    return static_cast<R>(_apply(FWD(fn), FWD(v).v1, FWD(args)...));
  else if (index == 2)
    return static_cast<R>(_apply(FWD(fn), FWD(v).v2, FWD(args)...));
  else if (index == 3)
    return static_cast<R>(_apply(FWD(fn), FWD(v).v3, FWD(args)...));
  else
    return apply_variadic_union<R, typename U::more_t>(FWD(v).more, index - 4, FWD(fn), FWD(args)...);
}

template <typename R, typename U, typename Fn, typename... Args>
[[nodiscard]] constexpr auto invoke_type_variadic_union(some_variadic_union auto &&v, ::std::size_t index, Fn &&fn,
                                                        Args &&...args) -> R
  requires ::std::is_same_v<::std::remove_cvref_t<decltype(v)>, U>       //
           && (U::size > 4) && (not ::std::is_same_v<void, R>)           //
           && _typelist_type_invocable_r<R, Fn, decltype(v), Args &&...> //
{
  if (index == 0)
    return _invoke_type<typename U::t0>(FWD(fn), FWD(v).v0, FWD(args)...);
  else if (index == 1)
    return _invoke_type<typename U::t1>(FWD(fn), FWD(v).v1, FWD(args)...);
  else if (index == 2)
    return _invoke_type<typename U::t2>(FWD(fn), FWD(v).v2, FWD(args)...);
  else if (index == 3)
    return _invoke_type<typename U::t3>(FWD(fn), FWD(v).v3, FWD(args)...);
  else
    return invoke_type_variadic_union<R, typename U::more_t>(FWD(v).more, index - 4, FWD(fn), FWD(args)...);
}

template <typename R, typename U, typename Fn, typename... Args>
constexpr void apply_variadic_union(some_variadic_union auto &&v, ::std::size_t index, Fn &&fn, Args &&...args)
  requires ::std::is_same_v<::std::remove_cvref_t<decltype(v)>, U> //
           && (U::size > 4) && (::std::is_same_v<void, R>)         //
           && _typelist_applicable<Fn, decltype(v), Args &&...>    //
{
  if (index == 0)
    return (void)_apply(FWD(fn), FWD(v).v0, FWD(args)...);
  else if (index == 1)
    return (void)_apply(FWD(fn), FWD(v).v1, FWD(args)...);
  else if (index == 2)
    return (void)_apply(FWD(fn), FWD(v).v2, FWD(args)...);
  else if (index == 3)
    return (void)_apply(FWD(fn), FWD(v).v3, FWD(args)...);
  else
    return apply_variadic_union<R, typename U::more_t>(FWD(v).more, index - 4, FWD(fn), FWD(args)...);
}

template <typename R, typename U, typename Fn, typename... Args>
constexpr void invoke_type_variadic_union(some_variadic_union auto &&v, ::std::size_t index, Fn &&fn, Args &&...args)
  requires ::std::is_same_v<::std::remove_cvref_t<decltype(v)>, U>  //
           && (U::size > 4) && (::std::is_same_v<void, R>)          //
           && _typelist_type_invocable<Fn, decltype(v), Args &&...> //
{
  if (index == 0)
    return (void)_invoke_type<typename U::t0>(FWD(fn), FWD(v).v0, FWD(args)...);
  else if (index == 1)
    return (void)_invoke_type<typename U::t1>(FWD(fn), FWD(v).v1, FWD(args)...);
  else if (index == 2)
    return (void)_invoke_type<typename U::t2>(FWD(fn), FWD(v).v2, FWD(args)...);
  else if (index == 3)
    return (void)_invoke_type<typename U::t3>(FWD(fn), FWD(v).v3, FWD(args)...);
  else
    return invoke_type_variadic_union<R, typename U::more_t>(FWD(v).more, index - 4, FWD(fn), FWD(args)...);
}

} // namespace fn::inline LIBFN_VERSION::detail

// ---------- BEGIN fn/detail/macro_end.hpp ----------
// Deliberately no include guard: see fn/detail/macro_begin.hpp.

#undef FWD // NOSONAR cpp:S959 paired with the define in macro_begin.hpp
#pragma pop_macro("FWD")

#undef DEDUCED_RETURN // NOSONAR cpp:S959 paired with the define in macro_begin.hpp
#pragma pop_macro("DEDUCED_RETURN")
// ---------- END fn/detail/macro_end.hpp ----------

// ---------- RESUME fn/detail/variadic_union.hpp ----------

#endif // INCLUDE_FN_DETAIL_VARIADIC_UNION
// ---------- END fn/detail/variadic_union.hpp ----------

// ---------- RESUME fn/copack.hpp ----------

// ---------- BEGIN fn/functional.hpp ----------
#ifndef INCLUDE_FN_FUNCTIONAL
#define INCLUDE_FN_FUNCTIONAL

// ---------- RESUME fn/functional.hpp ----------

// ---------- RESUME fn/functional.hpp ----------

// ---------- BEGIN fn/detail/macro_begin.hpp ----------
// Deliberately no include guard: this header and fn/detail/macro_end.hpp bracket the section of a
// header that uses the macros below; push_macro/pop_macro make the bracketing safe under nesting
// and preserve any prior user definition.

#pragma push_macro("FWD")
#undef FWD // NOSONAR cpp:S959 saved by push_macro above

// This FWD macro is a functional equivalent to std::forward<decltype(v)>(v),
// but it saves compilation time (and typing) when used frequently.
#define FWD(...) static_cast<decltype(__VA_ARGS__) &&>(__VA_ARGS__)

#pragma push_macro("DEDUCED_RETURN")
#undef DEDUCED_RETURN // NOSONAR cpp:S959 saved by push_macro above

// Spell a function's deduced return type explicitly on MSVC only. MSVC mis-resolves a deduced
// (`auto`/`decltype(auto)`) return whose type derives from a body-local alias, leaking it as an
// opaque dependent type; an explicit trailing return type is the fix. Every other compiler keeps
// `decltype(auto)` — the natural spelling — which by construction deduces `decltype(EXPR)` on
// `return EXPR;`, so the two are the same type and this is a no-op off MSVC.
//
// Confining `decltype(EXPR)` to MSVC also keeps it off clang <= 20, which in C++23 substitutes a
// non-viable constrained overload's trailing return type BEFORE its requires-clause rejects it
// (fixed clang 21), so the explicit form would fail to compile instead of removing the non-viable
// function from the overload set.
#ifndef _MSC_VER
#define DEDUCED_RETURN(...) decltype(auto)
#else
#define DEDUCED_RETURN(...) decltype(__VA_ARGS__)
#endif
// ---------- END fn/detail/macro_begin.hpp ----------

// ---------- RESUME fn/functional.hpp ----------

namespace fn {
inline namespace LIBFN_VERSION {

/**
 * @brief The result type of `fn::apply` over the arguments
 *
 * Yields `void` where the application is not viable, as well as for a viable application returning
 * `void` - pair with `is_applicable` to tell the two apart.
 *
 * @tparam Fn Callable to apply
 * @tparam Args Arguments as `fn::apply` would take them, including `pack` and `copack` operands
 */
template <typename Fn, typename... Args> struct apply_result : detail::_apply_result<Fn, Args...> {};

/**
 * @brief Alias for `apply_result<Fn, Args...>::type`
 */
template <typename Fn, typename... Args> using apply_result_t = typename apply_result<Fn, Args...>::type;

/**
 * @brief Checks if `fn::apply` of `Fn` over the arguments is viable
 *
 * The multidispatch twin of `std::is_invocable`: a `pack` operand counts by its elements, and a
 * `copack` operand counts when every alternative can be dispatched. A set of alternatives which
 * disagree on the result type is rejected by a `static_assert` inside the dispatch, not by this
 * trait answering false.
 *
 * @tparam Fn Callable to apply
 * @tparam Args Arguments as `fn::apply` would take them
 */
template <typename Fn, typename... Args> struct is_applicable : detail::_is_applicable<Fn, Args...> {};

/**
 * @brief Alias for `is_applicable<Fn, Args...>::value`
 */
template <typename Fn, typename... Args> constexpr inline bool is_applicable_v = is_applicable<Fn, Args...>::value;

/**
 * @brief Checks if `fn::apply_r<Ret>` of `Fn` over the arguments is viable
 *
 * As `is_applicable`, except every branch result needs only to be acceptable as `Ret` rather than
 * converge on one deduced type.
 *
 * @tparam Ret Type the results convert to
 * @tparam Fn Callable to apply
 * @tparam Args Arguments as `fn::apply_r` would take them
 */
template <typename Ret, typename Fn, typename... Args>
struct is_applicable_r : detail::_is_applicable_r<Ret, Fn, Args...> {};

/**
 * @brief Alias for `is_applicable_r<Ret, Fn, Args...>::value`
 */
template <typename Ret, typename Fn, typename... Args>
constexpr inline bool is_applicable_r_v = is_applicable_r<Ret, Fn, Args...>::value;

/**
 * @brief Checks if `fn::apply` of `Fn` over the arguments is viable and cannot throw
 *
 * Composes through the dispatch: for a `copack` operand every alternative's call must be nothrow,
 * since which one runs is a run-time fact. Answers false where the call is not viable at all.
 *
 * @tparam Fn Callable to apply
 * @tparam Args Arguments as `fn::apply` would take them
 */
template <typename Fn, typename... Args> struct is_nothrow_applicable : detail::_is_nothrow_applicable<Fn, Args...> {};

/**
 * @brief Alias for `is_nothrow_applicable<Fn, Args...>::value`
 */
template <typename Fn, typename... Args>
constexpr inline bool is_nothrow_applicable_v = is_nothrow_applicable<Fn, Args...>::value;

/**
 * @brief Checks if `fn::apply_r<Ret>` of `Fn` over the arguments is viable and cannot throw
 *
 * @tparam Ret Type the results convert to
 * @tparam Fn Callable to apply
 * @tparam Args Arguments as `fn::apply_r` would take them
 */
template <typename Ret, typename Fn, typename... Args>
struct is_nothrow_applicable_r : detail::_is_nothrow_applicable_r<Ret, Fn, Args...> {};

/**
 * @brief Alias for `is_nothrow_applicable_r<Ret, Fn, Args...>::value`
 */
template <typename Ret, typename Fn, typename... Args>
constexpr inline bool is_nothrow_applicable_r_v = is_nothrow_applicable_r<Ret, Fn, Args...>::value;

/**
 * @brief The multidispatch entry point: unpacks products, dispatches over alternatives, invokes `fn`
 *
 * A `pack` operand spreads into the call by elements; a lone tuple-like argument has `std::apply`'s
 * meaning; a `copack` operand dispatches on its active alternative, itself unpacked one level when
 * tuple-like; several pack/copack operands first fold into one, distributing alternatives over
 * products. The arm is selected by ordinary C++ overload resolution, and the dispatch is
 * exhaustive: an alternative without a viable arm makes the whole call not applicable.
 *
 * @param fn Callable; `fn::overload` fuses per-alternative arms into one
 * @param args Any mix of scalars, `pack`s and `copack`s, in call order
 * @return Result of invoking `fn` on the selected call shape
 */
template <typename Fn, typename... Args>
  requires is_applicable_v<Fn, Args...>
constexpr auto apply(Fn &&fn, Args &&...args) noexcept(is_nothrow_applicable_v<Fn, Args...>)
    -> apply_result_t<Fn, Args...>
{
  return detail::_apply(FWD(fn), FWD(args)...);
}

/**
 * @brief `fn::apply` with the result converted to `Ret`
 *
 * Branch results need only be acceptable as `Ret`, which is how alternatives eliminating into
 * different types converge: name a type they all convert into - every alternative converts
 * implicitly into its parent `copack`, so a `copack_for` of the branch results always serves.
 *
 * @tparam Ret Type the result converts to
 * @param fn Callable; `fn::overload` fuses per-alternative arms into one
 * @param args Any mix of scalars, `pack`s and `copack`s, in call order
 * @return Result of the dispatch, converted to `Ret`
 */
template <typename Ret, typename Fn, typename... Args>
  requires is_applicable_r_v<Ret, Fn, Args...>
constexpr auto apply_r(Fn &&fn, Args &&...args) noexcept(is_nothrow_applicable_r_v<Ret, Fn, Args...>) -> Ret
{
  return detail::_apply_r<Ret>(FWD(fn), FWD(args)...);
}

/**
 * @brief Checks if `fn::apply` of `Fn` over `Args` is viable - the concept form of `is_applicable`
 *
 * @tparam Fn Callable to apply
 * @tparam Args Arguments as `fn::apply` would take them
 */
template <typename Fn, typename... Args>
concept applicable = is_applicable_v<Fn, Args...>;

/**
 * @brief As `applicable`, adding the semantic promise of equality preservation - mirroring
 *        `std::regular_invocable` against `std::invocable`
 *
 * @tparam Fn Callable to apply
 * @tparam Args Arguments as `fn::apply` would take them
 */
template <typename Fn, typename... Args>
concept regular_applicable = applicable<Fn, Args...>;

/**
 * @brief Checks if `Fn` can be applied to every alternative of the typelist `T`
 *
 * The exhaustiveness question `copack` and `choice` dispatch asks before selecting an arm: each
 * alternative is tried in `T`'s own cv-ref qualification, with the trailing `Args` following the
 * alternative's content.
 *
 * @tparam Fn Callable to apply
 * @tparam T The typelist - a `copack` or `choice`, cv-ref qualified
 * @tparam Args Trailing arguments, appended after the alternative's content
 */
template <typename Fn, typename T, typename... Args>
concept typelist_applicable = detail::_typelist_applicable<Fn, T, Args...>;

/**
 * @brief As `typelist_applicable`, with every branch result converting to `Ret`
 *
 * @tparam Ret Type the results convert to
 * @tparam Fn Callable to apply
 * @tparam T The typelist - a `copack` or `choice`, cv-ref qualified
 * @tparam Args Trailing arguments, appended after the alternative's content
 */
template <typename Ret, typename Fn, typename T, typename... Args>
concept typelist_applicable_r = detail::_typelist_applicable_r<Ret, Fn, T, Args...>;

} // namespace LIBFN_VERSION
} // namespace fn

// ---------- BEGIN fn/detail/macro_end.hpp ----------
// Deliberately no include guard: see fn/detail/macro_begin.hpp.

#undef FWD // NOSONAR cpp:S959 paired with the define in macro_begin.hpp
#pragma pop_macro("FWD")

#undef DEDUCED_RETURN // NOSONAR cpp:S959 paired with the define in macro_begin.hpp
#pragma pop_macro("DEDUCED_RETURN")
// ---------- END fn/detail/macro_end.hpp ----------

// ---------- RESUME fn/functional.hpp ----------

#endif // INCLUDE_FN_FUNCTIONAL
// ---------- END fn/functional.hpp ----------

// ---------- RESUME fn/copack.hpp ----------

// ---------- RESUME fn/copack.hpp ----------

// ---------- BEGIN fn/detail/macro_begin.hpp ----------
// Deliberately no include guard: this header and fn/detail/macro_end.hpp bracket the section of a
// header that uses the macros below; push_macro/pop_macro make the bracketing safe under nesting
// and preserve any prior user definition.

#pragma push_macro("FWD")
#undef FWD // NOSONAR cpp:S959 saved by push_macro above

// This FWD macro is a functional equivalent to std::forward<decltype(v)>(v),
// but it saves compilation time (and typing) when used frequently.
#define FWD(...) static_cast<decltype(__VA_ARGS__) &&>(__VA_ARGS__)

#pragma push_macro("DEDUCED_RETURN")
#undef DEDUCED_RETURN // NOSONAR cpp:S959 saved by push_macro above

// Spell a function's deduced return type explicitly on MSVC only. MSVC mis-resolves a deduced
// (`auto`/`decltype(auto)`) return whose type derives from a body-local alias, leaking it as an
// opaque dependent type; an explicit trailing return type is the fix. Every other compiler keeps
// `decltype(auto)` — the natural spelling — which by construction deduces `decltype(EXPR)` on
// `return EXPR;`, so the two are the same type and this is a no-op off MSVC.
//
// Confining `decltype(EXPR)` to MSVC also keeps it off clang <= 20, which in C++23 substitutes a
// non-viable constrained overload's trailing return type BEFORE its requires-clause rejects it
// (fixed clang 21), so the explicit form would fail to compile instead of removing the non-viable
// function from the overload set.
#ifndef _MSC_VER
#define DEDUCED_RETURN(...) decltype(auto)
#else
#define DEDUCED_RETURN(...) decltype(__VA_ARGS__)
#endif
// ---------- END fn/detail/macro_begin.hpp ----------

// ---------- RESUME fn/copack.hpp ----------

namespace fn {
inline namespace LIBFN_VERSION {

/**
 * @brief Checks if a type is a `copack` (with any alternatives, including none)
 *
 * @tparam T Type to check, possibly cv-ref qualified
 */
template <typename T>
concept some_copack = detail::_some_copack<T>;

/**
 * @brief Checks if a type is the empty `copack<>` - the uninhabited zero
 *
 * A carrier side of this type is statically known never to hold a value, which is what renders
 * the operations over that side vacuous.
 *
 * @tparam T Type to check, possibly cv-ref qualified
 */
template <typename T>
concept empty_copack = some_copack<T> && (::std::remove_cvref_t<T>::size == 0);

/**
 * @brief Checks if a type is a `std::in_place_type_t` tag
 *
 * @tparam T Type to check, possibly cv-ref qualified
 */
template <typename T>
concept some_in_place_type = detail::_some_in_place_type<T>;

namespace detail {
template <typename T>
static constexpr bool _is_valid_copack_subtype //
    = (not ::std::is_same_v<void, T>)          //
    &&(not ::std::is_reference_v<T>)           //
    &&(not some_copack<T>)                     //
    &&(not some_in_place_type<T>)              //
    &&::std::is_same_v<T, ::std::remove_cv_t<T>>;

struct _apply_autodetect_tag final {};

// Whether comparing an alternative can throw. An alternative the other side does not have is never
// compared, so it cannot throw - and need not even be comparable, which is why this is a guarded
// specialization rather than a disjunction: unlike a requires-clause, a noexcept-specifier is an
// ordinary constant expression, and every operand of its `||` has to be well-formed.
template <typename T, typename... Tx> constexpr inline bool _nothrow_eq_with = true;
template <typename T, typename... Tx>
  requires type_one_of<T, Tx...>
constexpr inline bool _nothrow_eq_with<T, Tx...> = noexcept(::std::declval<T const &>() == ::std::declval<T const &>());

template <typename Fn, typename Self, typename T, typename... Args> struct _typelist_select_apply_result;
template <typename Fn, typename Self, template <typename...> typename Tpl, typename... Ts, typename... Args>
struct _typelist_select_apply_result<Fn, Self, Tpl<Ts...>, Args...> {
  using T0 = select_nth_t<0, Ts...>;
  using R0 = ::fn::detail::_apply_result<Fn, apply_const_lvalue_t<Self, T0>, Args...>::type;
  static constexpr bool type_found
      = (...
         && ::std::is_same_v<R0,
                             typename ::fn::detail::_apply_result<Fn, apply_const_lvalue_t<Self, Ts>, Args...>::type>);
  // If every alternative is applicable here, they must all yield the same result type.
  static_assert(not(... && ::fn::detail::_is_applicable<Fn, apply_const_lvalue_t<Self, Ts>, Args...>::value)
                || type_found);
  using type = ::std::conditional_t<type_found, R0, void>;
};

struct _collapsing_copack_tag final {};

namespace _collapsing_copack {
template <typename... Ts> struct typelist;
template <typename... Ts> extern typelist<Ts...> const &typelist_v;

template <typename... Ts, typename T>
auto operator^(typelist<Ts...> const &, typelist<T> const &) -> typelist<Ts..., T> const &;
template <typename... Ts, typename... Us>
auto operator^(typelist<Ts...> const &, typelist<::fn::copack<Us...>> const &) -> typelist<Ts..., Us...> const &;

template <typename... Ts> using flattened = ::std::remove_cvref_t<decltype((typelist_v<> ^ ... ^ typelist_v<Ts>))>;

template <template <typename...> typename Tpl, typename T> struct normalized;
template <template <typename...> typename Tpl, typename... Ts> struct normalized<Tpl, typelist<Ts...>> {
  using type = typename ::fn::detail::normalized<Ts...>::template apply<Tpl>;
};
} // namespace _collapsing_copack

// A result no copack can hold - void above all - must drop the caller's candidate, not explode:
// everything behind the gate (flattening, normalization, the copack they name) hard-errors OUTSIDE
// any immediate context. The false gate has no `type`, and the collapsing traits pass that absence
// through by inheritance, so it surfaces where a return type names `::type` - in the immediate
// context, as a clean substitution failure.
template <bool, template <typename...> typename Tpl, typename... Rs> struct _collapsing_copack_gate {};
template <template <typename...> typename Tpl, typename... Rs> struct _collapsing_copack_gate<true, Tpl, Rs...> {
  using type = _collapsing_copack::normalized<Tpl, _collapsing_copack::flattened<Rs...>>::type;
};

template <typename R> constexpr inline bool _collapsible_result = some_copack<R> || _is_valid_copack_subtype<R>;

template <typename Fn, typename Self, typename T, typename... Args> struct _typelist_collapsing_copack;
template <typename Fn, typename Self, template <typename...> typename Tpl, typename... Ts, typename... Args>
struct _typelist_collapsing_copack<Fn, Self, Tpl<Ts...>, Args...>
    : _collapsing_copack_gate<
          (...
           && _collapsible_result<::std::remove_cvref_t<
               typename ::fn::detail::_apply_result<Fn, apply_const_lvalue_t<Self, Ts>, Args...>::type>>),
          Tpl,
          ::std::remove_cvref_t<
              typename ::fn::detail::_apply_result<Fn, apply_const_lvalue_t<Self, Ts>, Args...>::type>...> {};

template <typename T, typename Fn, typename Self, typename... Args> struct _copack_apply_result final {
  using type = T;
};
template <typename Fn, typename Self, typename... Args>
struct _copack_apply_result<_apply_autodetect_tag, Fn, Self, Args...> final {
  using type = _typelist_select_apply_result<Fn, Self, ::std::remove_cvref_t<Self>, Args...>::type;
};
template <typename Fn, typename Self, typename... Args>
struct _copack_apply_result<_collapsing_copack_tag, Fn, Self, Args...> final
    : _typelist_collapsing_copack<Fn, Self, ::std::remove_cvref_t<Self>, Args...> {};

template <template <typename...> typename Tpl> struct _joining_superset_tag final {};

// and_then's join - a sibling of the collapse above with the OPPOSITE convention for a result of
// the target kind: the collapse keeps it whole (fmap nests the nominal atom), the join splices its
// alternatives into the accumulated list (bind flattens). Only results of the tag's template kind
// splice - choice::and_then passes its own kind, and the and_then functor's cluster arm passes
// choice over a bare copack payload.
namespace _joining_superset {
template <typename... Ts> struct typelist;
template <typename... Ts> extern typelist<Ts...> const &typelist_v;

template <typename... Ts, template <typename...> typename Tpl, typename... Us>
auto operator^(typelist<Ts...> const &, typelist<Tpl<Us...>> const &) -> typelist<Ts..., Us...> const &;

template <typename... Ts> using flattened = ::std::remove_cvref_t<decltype((typelist_v<> ^ ... ^ typelist_v<Ts>))>;

template <template <typename...> typename Tpl, typename T> constexpr inline bool is_kind = false;
template <template <typename...> typename Tpl, typename... Us> constexpr inline bool is_kind<Tpl, Tpl<Us...>> = true;

template <template <typename...> typename Tpl, typename T> struct superset;
template <template <typename...> typename Tpl, typename... Ts> struct superset<Tpl, typelist<Ts...>> {
  using type = ::fn::detail::normalized<Ts...>::template apply<Tpl>;
};
} // namespace _joining_superset

template <template <typename...> typename Tpl, typename... Rs> struct _joining_superset_type {
  using type = _joining_superset::superset<Tpl, _joining_superset::flattened<Rs...>>::type;
};

// Results all of the target kind join into the normalized superset; anything else falls back to
// the select trait, so today's diagnostics are preserved verbatim - a convergent result of another
// kind instantiates the member, whose static_assert names the requirement, and a divergent one
// trips select's own assert.
template <template <typename...> typename Tpl, typename Fn, typename Self, typename T, typename... Args>
struct _typelist_joining_superset;
template <template <typename...> typename Tpl, typename Fn, typename Self, template <typename...> typename Tpl2,
          typename... Ts, typename... Args>
struct _typelist_joining_superset<Tpl, Fn, Self, Tpl2<Ts...>, Args...>
    : ::std::conditional_t<
          (...
           && _joining_superset::is_kind<Tpl, ::std::remove_cvref_t<typename ::fn::detail::_apply_result<
                                                  Fn, apply_const_lvalue_t<Self, Ts>, Args...>::type>>),
          _joining_superset_type<Tpl, ::std::remove_cvref_t<typename ::fn::detail::_apply_result<
                                          Fn, apply_const_lvalue_t<Self, Ts>, Args...>::type>...>,
          _typelist_select_apply_result<Fn, Self, Tpl2<Ts...>, Args...>> {};

template <template <typename...> typename Tpl, typename Fn, typename Self, typename... Args>
struct _copack_apply_result<_joining_superset_tag<Tpl>, Fn, Self, Args...> final
    : _typelist_joining_superset<Tpl, Fn, Self, ::std::remove_cvref_t<Self>, Args...> {};

template <typename Fn, typename Self, typename T, typename... Args> struct _typelist_type_select_invoke_result;
template <typename Fn, typename Self, template <typename...> typename Tpl, typename... Ts, typename... Args>
struct _typelist_type_select_invoke_result<Fn, Self, Tpl<Ts...>, Args...> {
  using T0 = select_nth_t<0, Ts...>;
  using R0 = ::fn::detail::_invoke_type_result<T0, Fn, apply_const_lvalue_t<Self, T0>, Args...>::type;
  static constexpr bool type_found
      = (...
         && ::std::is_same_v<
             R0, typename ::fn::detail::_invoke_type_result<Ts, Fn, apply_const_lvalue_t<Self, Ts>, Args...>::type>);
  // If every alternative is invocable here, they must all yield the same result type.
  static_assert(not(... && ::fn::detail::_is_type_invocable<Ts, Fn, apply_const_lvalue_t<Self, Ts>, Args...>::value)
                || type_found);
  using type = ::std::conditional_t<type_found, R0, void>;
};

template <typename Fn, typename Self, typename T, typename... Args> struct _typelist_type_collapsing_copack;
template <typename Fn, typename Self, template <typename...> typename Tpl, typename... Ts, typename... Args>
struct _typelist_type_collapsing_copack<Fn, Self, Tpl<Ts...>, Args...>
    : _collapsing_copack_gate<
          (...
           && _collapsible_result<::std::remove_cvref_t<
               typename ::fn::detail::_invoke_type_result<Ts, Fn, apply_const_lvalue_t<Self, Ts>, Args...>::type>>),
          Tpl,
          ::std::remove_cvref_t<
              typename ::fn::detail::_invoke_type_result<Ts, Fn, apply_const_lvalue_t<Self, Ts>, Args...>::type>...> {};

template <typename T, typename Fn, typename Self, typename... Args> struct _copack_invoke_type_result final {
  using type = T;
};
template <typename Fn, typename Self, typename... Args>
struct _copack_invoke_type_result<_apply_autodetect_tag, Fn, Self, Args...> final {
  using type = _typelist_type_select_invoke_result<Fn, Self, ::std::remove_cvref_t<Self>, Args...>::type;
};
template <typename Fn, typename Self, typename... Args>
struct _copack_invoke_type_result<_collapsing_copack_tag, Fn, Self, Args...> final
    : _typelist_type_collapsing_copack<Fn, Self, ::std::remove_cvref_t<Self>, Args...> {};

} // namespace detail

/**
 * @brief The canonical coproduct payload: exactly one alternative is present
 *
 * A discriminated union indexed by type, not by position. The alternatives are required to be
 * flat, unique and sorted in the library's total order over types, and an instantiation that
 * diverges - out of order, duplicated, or nested - is ill-formed; spell `copack_for`, which
 * normalizes any list into the canonical form, rather than name that order by hand. Every
 * evaluation of a copack is an exhaustive dispatch: a callback set missing any alternative is
 * rejected at compile time. A structural type when its alternatives are.
 *
 * @tparam Ts The alternatives - flat, unique and sorted in the canonical order
 */
template <typename... Ts> struct copack;

/**
 * @brief The empty copack: the algebra's zero, uninhabited by construction
 *
 * The deleted default constructor is the whole point: no value of this type can ever exist, so a
 * carrier side declared `copack<>` is statically known never to be engaged. As the identity of
 * the union it vanishes inside `copack_for`; the remaining special members are kept so that the
 * type can sit inside a union storage.
 */
template <> struct copack<> final {
  /**
   * @brief Default constructor; not available on this carrier
   */
  constexpr copack() noexcept = delete; // NOTE, `= delete` here is the whole point
  /**
   * @brief Destructor
   */
  constexpr ~copack() noexcept = default;
  /**
   * @brief Copy constructor
   */
  constexpr copack(copack const &) noexcept = default;
  /**
   * @brief Move constructor
   */
  constexpr copack(copack &&) noexcept = default;
  /**
   * @brief Copy assignment
   */
  constexpr copack &operator=(copack const &) noexcept = default;
  /**
   * @brief Move assignment
   */
  constexpr copack &operator=(copack &&) noexcept = default;

  /**
   * @brief The number of alternatives
   */
  static constexpr ::std::size_t size = 0;
  /**
   * @brief Whether `T` is one of the alternatives
   */
  template <typename T> static constexpr bool has_type = false;
};

/**
 * @brief The storage and operations of a non-empty copack
 *
 * Holds one alternative in a variadic union together with its index. The special members are
 * exactly as trivial, available and nothrow as the alternatives permit; mutation follows the
 * standard's reinit discipline, with the strong exception guarantee and no valueless state.
 *
 * @tparam Ts The alternatives - flat, unique and sorted in the canonical order
 */
template <typename... Ts>
  requires(sizeof...(Ts) > 0)
struct copack<Ts...> {
  static_assert((... && detail::_is_valid_copack_subtype<Ts>));
  static_assert(::std::same_as<typename detail::normalized<Ts...>::template apply<::fn::copack>, copack>);

  /**
   * @brief The union holding the alternatives
   */
  using data_t = detail::variadic_union<Ts...>;
  /**
   * @brief The union holding the active alternative
   */
  data_t data;
  /**
   * @brief The index of the active alternative
   */
  ::std::size_t index;

  /**
   * @brief The number of alternatives
   */
  static constexpr ::std::size_t size = sizeof...(Ts);

  // What copying and moving a copack cost, asked of the storage that performs them - see the concepts
  // in detail/variadic_union.hpp. Everything below is specified and constrained in these terms, so
  // that no declaration has to restate what the storage does, and none can drift from it.
  static constexpr bool _copyable = (... && detail::_makeable<data_t, Ts, Ts const &>);
  static constexpr bool _movable = (... && detail::_makeable<data_t, Ts, Ts>);
  static constexpr bool _nothrow_copyable = (... && detail::_nothrow_makeable<data_t, Ts, Ts const &>);
  static constexpr bool _nothrow_movable = (... && detail::_nothrow_makeable<data_t, Ts, Ts>);

  // Assignment requires of every alternative its own `operator=`, and `_reassign` uses it whenever
  // the incoming alternative is the one already held; a different alternative is replaced by
  // construction, through `_reinit`. Each helper chooses its arm per alternative - so the choice
  // belongs INSIDE the fold: hoisting it out would demand that one arm serve them all, and would
  // reject a copack whose alternatives simply need different ones. The nothrow disjunct is what keeps
  // the strong guarantee without a valueless state - some arm must be unable to lose the value in
  // hand.
  static constexpr bool _copy_assignable
      = (...
         && (::std::is_copy_assignable_v<Ts> && detail::_makeable<data_t, Ts, Ts const &>
             && (detail::_nothrow_makeable<data_t, Ts, Ts const &> || detail::_nothrow_makeable<data_t, Ts, Ts>)));
  static constexpr bool _nothrow_copy_assignable
      = (... && (::std::is_nothrow_copy_assignable_v<Ts> && detail::_nothrow_makeable<data_t, Ts, Ts const &>));
  static constexpr bool _move_assignable
      = (... && (::std::is_move_assignable_v<Ts> && detail::_nothrow_makeable<data_t, Ts, Ts>));
  static constexpr bool _nothrow_move_assignable = (... && ::std::is_nothrow_move_assignable_v<Ts>);

  // Each special member is trivial exactly when every alternative permits it, with the gates
  // `std::variant` uses. The trivial arm IS the compiler's defaulted member - for the assignments,
  // member-wise copying of the union's object representation - which for types passing these gates
  // is observationally identical to the general arms: a pure optimization, not different semantics.
  static constexpr bool _trivially_destructible = (... && ::std::is_trivially_destructible_v<Ts>);
  static constexpr bool _trivially_copy_constructible = (... && ::std::is_trivially_copy_constructible_v<Ts>);
  static constexpr bool _trivially_move_constructible = (... && ::std::is_trivially_move_constructible_v<Ts>);
  static constexpr bool _trivially_copy_assignable
      = (...
         && (::std::is_trivially_copy_constructible_v<Ts> && ::std::is_trivially_copy_assignable_v<Ts>
             && ::std::is_trivially_destructible_v<Ts>));
  static constexpr bool _trivially_move_assignable
      = (...
         && (::std::is_trivially_move_constructible_v<Ts> && ::std::is_trivially_move_assignable_v<Ts>
             && ::std::is_trivially_destructible_v<Ts>));

  /**
   * @brief The `I`-th alternative in the canonical order
   *
   * @tparam I Index of the alternative
   */
  template <::std::size_t I> using select_nth = detail::select_nth_t<I, Ts...>;

  /**
   * @brief Checks if `T` is one of the alternatives
   *
   * @tparam T Type to look for
   */
  template <typename T> static constexpr bool has_type = data_t::template has_type<T>;

  // Every dispatch below is nothrow exactly when the call on each alternative is: which one runs is
  // a run-time choice, so one throwing alternative is enough to make the whole dispatch throwing.
  template <typename Ret>
  [[nodiscard]] constexpr auto
  _invoke(auto &&fn) const & noexcept(detail::_is_nothrow_rtst_invocable<Ret, decltype(fn), copack const &>)
  {
    return detail::invoke_type_variadic_union<Ret, data_t>(this->data, this->index, FWD(fn));
  }

  template <typename Ret>
  [[nodiscard]] constexpr auto
  _invoke(auto &&fn) && noexcept(detail::_is_nothrow_rtst_invocable<Ret, decltype(fn), copack &&>)
  {
    return detail::invoke_type_variadic_union<Ret, data_t>(::std::move(*this).data, ::std::move(*this).index, FWD(fn));
  }

  template <typename Fn>
  [[nodiscard]] constexpr auto _transform(Fn &&fn) const & noexcept(
      detail::_is_nothrow_rtst_invocable<
          typename detail::_copack_invoke_type_result<detail::_collapsing_copack_tag, Fn &&, copack const &>::type,
          Fn &&, copack const &>) ->
      typename detail::_copack_invoke_type_result<detail::_collapsing_copack_tag, Fn &&, copack const &>::type
  {
    using type = detail::_copack_invoke_type_result<detail::_collapsing_copack_tag, Fn &&, copack const &>::type;
    return detail::invoke_type_variadic_union<type, data_t>(this->data, index, FWD(fn));
  }

  template <typename Fn>
  [[nodiscard]] constexpr auto _transform(Fn &&fn) && noexcept(
      detail::_is_nothrow_rtst_invocable<
          typename detail::_copack_invoke_type_result<detail::_collapsing_copack_tag, Fn &&, copack &&>::type, Fn &&,
          copack &&>) ->
      typename detail::_copack_invoke_type_result<detail::_collapsing_copack_tag, Fn &&, copack &&>::type
  {
    using type = detail::_copack_invoke_type_result<detail::_collapsing_copack_tag, Fn &&, copack &&>::type;
    return detail::invoke_type_variadic_union<type, data_t>(::std::move(*this).data, index, FWD(fn));
  }

  /**
   * @brief Constructs the alternative matching the value's decayed type
   *
   * Takes a value of exactly one alternative: a merely convertible non-alternative is rejected,
   * so interconvertible alternatives never make a resolution puzzle. Explicit exactly where the
   * conversion to that alternative is.
   *
   * @param v Value of one alternative
   */
  template <typename T>
  constexpr copack(T &&v) // NOSONAR cpp:S1709,S6458 implicit arm of the explicit pair; has_type excludes self
      noexcept(detail::_nothrow_makeable<data_t, ::std::remove_cvref_t<T>, decltype(v)>)
    requires has_type<::std::remove_cvref_t<T>> && (detail::_makeable<data_t, ::std::remove_cvref_t<T>, decltype(v)>)
                 && (::std::is_convertible_v<decltype(v), ::std::remove_cvref_t<T>>)
      : data(detail::make_variadic_union<::std::remove_cvref_t<T>, data_t>(FWD(v))),
        index(detail::type_index<::std::remove_cvref_t<T>, Ts...>)
  {
  }

  template <typename T>
  constexpr explicit copack(T &&v) // NOSONAR cpp:S6458 has_type excludes self
      noexcept(detail::_nothrow_makeable<data_t, ::std::remove_cvref_t<T>, decltype(v)>)
    requires has_type<::std::remove_cvref_t<T>> && (detail::_makeable<data_t, ::std::remove_cvref_t<T>, decltype(v)>)
                 && (not ::std::is_convertible_v<decltype(v), ::std::remove_cvref_t<T>>)
      : data(detail::make_variadic_union<::std::remove_cvref_t<T>, data_t>(FWD(v))),
        index(detail::type_index<::std::remove_cvref_t<T>, Ts...>)
  {
  }

  /**
   * @brief Constructs the alternative `T` in place from the arguments
   *
   * @tparam T The alternative to construct
   * @param args Arguments to construct the alternative from
   */
  template <typename T>
  constexpr explicit copack(::std::in_place_type_t<T>,
                            auto &&...args) noexcept(detail::_nothrow_makeable<data_t, T, decltype(args)...>)
    requires has_type<T> && detail::_makeable<data_t, T, decltype(args)...>
      : data(detail::make_variadic_union<T, data_t>(FWD(args)...)), index(detail::type_index<T, Ts...>)
  {
  }

  /**
   * @brief Widening constructor from a copack over a subset of the alternatives
   *
   * The active alternative relocates into this copack; implicit, as the subset-to-superset
   * direction can never lose information.
   *
   * @param arg The narrower copack
   */
  template <typename... Tx>
  constexpr copack(copack<Tx...> const &arg) // NOSONAR cpp:S1709 implicit widening by design
      noexcept((... && detail::_nothrow_makeable<data_t, Tx, Tx const &>))
    requires detail::is_superset_of<copack, copack<Tx...>> && (not ::std::is_same_v<copack, copack<Tx...>>)
                 && (... && detail::_makeable<data_t, Tx, Tx const &>) && (sizeof...(Tx) > 0)
      : data(FWD(arg).template _invoke<data_t>([]<typename T>(::std::in_place_type_t<T>, auto &&v) -> data_t {
          return detail::make_variadic_union<T, data_t>(FWD(v));
        })),
        index(FWD(arg).template _invoke<::std::size_t>([]<typename T>(::std::in_place_type_t<T>, auto &&) { //
          return detail::type_index<T, Ts...>;
        }))
  {
  }

  /**
   * @brief Widening constructor from a copack over a subset of the alternatives
   */
  template <typename... Tx>
  constexpr copack(copack<Tx...> &&arg) // NOSONAR cpp:S1709 implicit widening by design
      noexcept((... && detail::_nothrow_makeable<data_t, Tx, Tx>))
    requires detail::is_superset_of<copack, copack<Tx...>> && (not ::std::is_same_v<copack, copack<Tx...>>)
                 && (... && detail::_makeable<data_t, Tx, Tx>) && (sizeof...(Tx) > 0)
      : data(FWD(arg).template _invoke<data_t>([]<typename T>(::std::in_place_type_t<T>, auto &&v) -> data_t {
          return detail::make_variadic_union<T, data_t>(FWD(v));
        })),
        index(FWD(arg).template _invoke<::std::size_t>([]<typename T>(::std::in_place_type_t<T>, auto &&) { //
          return detail::type_index<T, Ts...>;
        }))
  {
  }

  /**
   * @brief Widening constructor from a copack whose type is spelled as a tag
   *
   * @param arg The narrower copack
   */
  template <typename... Tx>
  constexpr copack(::std::in_place_type_t<copack<Tx...>>, some_copack auto &&arg) //
      noexcept((... && detail::_nothrow_makeable<data_t, Tx, apply_const_lvalue_t<decltype(arg), Tx &&>>))
    requires ::std::is_same_v<::std::remove_cvref_t<decltype(arg)>, copack<Tx...>>
                 && detail::is_superset_of<copack, copack<Tx...>> && (sizeof...(Tx) > 0)
      : data(FWD(arg).template _invoke<data_t>([]<typename T>(::std::in_place_type_t<T>, auto &&v) -> data_t {
          return detail::make_variadic_union<T, data_t>(FWD(v));
        })),
        index(FWD(arg).template _invoke<::std::size_t>([]<typename T>(::std::in_place_type_t<T>, auto &&) { //
          return detail::type_index<T, Ts...>;
        }))
  {
  }

  /**
   * @brief Copy constructor; trivial where every alternative's is
   *
   * @param other The copack to copy from
   */
  constexpr copack(copack const &other)
    requires _trivially_copy_constructible
  = default;
  constexpr copack(copack const &other) noexcept(_nothrow_copyable)
    requires(not _trivially_copy_constructible) && _copyable
      : data(detail::invoke_type_variadic_union<data_t, data_t>(                 //
            other.data, other.index,                                             //
            []<typename T>(::std::in_place_type_t<T>, auto const &v) -> data_t { //
              return detail::make_variadic_union<T, data_t>(v);
            })),
        index(other.index)
  {
  }

  /**
   * @brief Move constructor; trivial where every alternative's is
   *
   * @param other The copack to move from
   */
  constexpr copack(copack &&other)
    requires _trivially_move_constructible
  = default;
  constexpr copack(copack &&other) noexcept(_nothrow_movable)
    requires(not _trivially_move_constructible) && _movable
      : data(detail::invoke_type_variadic_union<data_t, data_t>(            //
            ::std::move(other).data, other.index,                           //
            []<typename T>(::std::in_place_type_t<T>, auto &&v) -> data_t { //
              return detail::make_variadic_union<T, data_t>(FWD(v));
            })),
        index(other.index)
  {
  }

  /**
   * @brief Destructor
   */
  constexpr ~copack()
    requires _trivially_destructible
  = default;
  constexpr ~copack() noexcept
    requires(not _trivially_destructible)
  {
    detail::invoke_type_variadic_union<void, data_t>( //
        this->data, index, [this]<typename T>(::std::in_place_type_t<T>, auto &&) {
          ::std::destroy_at(detail::ptr_variadic_union<T, data_t>(this->data));
        });
  }

  // Replaces the alternative in hand with a `T` built from `args`, mirroring reinit-expected
  // ([expected.object.assign]): a copack always holds one of its alternatives - there is no valueless
  // state to fall back on - so the one it holds is destroyed only once its replacement is certain.
  // Which arm applies is decided per alternative, not for the copack as a whole: a nothrow-copyable one
  // is built straight over the old, and one whose copy can throw is copied into a temporary first,
  // where only its (nothrow) move goes near the storage.
  //
  // The standard's third arm - snapshot the old, roll back on throw - belongs to assignment of the
  // SAME alternative, which is `_reassign`'s job; here the old alternative is a different type, and
  // admitting a snapshot arm would gate the incoming alternative on the outgoing one's movability.
  // An alternative that can be neither built nor moved without throwing is constrained away instead.
  //
  // The arm is chosen by asking the storage what it can do, never by a trait that restates it:
  // `std::is_nothrow_move_constructible_v` asks about `T(T&&)`, the storage performs `T{...}`, and
  // the two can disagree - braced initialization considers initializer-list constructors first, so a
  // type can promise a nothrow move and still throw from `T{std::move(t)}`. Believing that promise
  // here would destroy the old alternative and then fail to replace it.
  template <typename T, typename... Args>
  constexpr void _reinit(Args &&...args) noexcept(detail::_nothrow_makeable<data_t, T, Args...>)
    requires has_type<T> && detail::_makeable<data_t, T, Args...>
             && (detail::_nothrow_makeable<data_t, T, Args...> || detail::_nothrow_makeable<data_t, T, T>)
  {
    if constexpr (detail::_nothrow_makeable<data_t, T, Args...>) {
      ::std::destroy_at(this);
      ::std::construct_at(this, ::std::in_place_type<T>, FWD(args)...);
    } else {
      T tmp{FWD(args)...}; // may throw, and the storage is untouched until it cannot
      ::std::destroy_at(this);
      ::std::construct_at(this, ::std::in_place_type<T>, ::std::move(tmp)); // cannot throw: see above
    }
  }

  // Assigns the incoming alternative with its own `operator=` when it is the one already held: the
  // arms mirror `_reinit`'s shape, and the third is the standard's snapshot-and-restore - live here,
  // where old and new are the same type, so the constraint that admits the alternative also
  // guarantees its snapshot.
  template <typename T, typename V> constexpr void _reassign(V &&v) noexcept(::std::is_nothrow_assignable_v<T &, V>)
  {
    T *held = detail::ptr_variadic_union<T, data_t>(this->data);
    if constexpr (::std::is_nothrow_assignable_v<T &, V>) {
      *held = FWD(v);
    } else if constexpr (::std::is_nothrow_assignable_v<T &, T>) {
      T tmp{FWD(v)}; // may throw, and the value in hand is untouched until it cannot
      *held = ::std::move(tmp);
    } else if constexpr (detail::_nothrow_makeable<data_t, T, T>) {
      T snap{::std::move(*held)};
      try {
        *held = FWD(v);
      } catch (...) {
        ::std::destroy_at(this);
        ::std::construct_at(this, ::std::in_place_type<T>, ::std::move(snap)); // cannot throw: see above
        throw;
      }
    } else {
      T snap{*held}; // the copy that cannot throw, where the move is the one that can
      try {
        *held = FWD(v);
      } catch (...) {
        ::std::destroy_at(this);
        ::std::construct_at(this, ::std::in_place_type<T>, snap); // restored by that same nothrow copy
        throw;
      }
    }
  }

  /**
   * @brief Copy assignment, with the strong exception guarantee
   *
   * @param other The copack to copy from
   * @return Reference to `*this`
   */
  // Assignment requires of every alternative its own `operator=`, and uses it when the incoming
  // alternative is the one already held; a different alternative is replaced by construction, as
  // [variant.assign] does. A copack therefore no longer offers an operation its alternative refuses -
  // a pack holding a reference deletes assignment precisely because C++ cannot rebind a reference,
  // and destroy-and-reconstruct would synthesize exactly that.
  constexpr copack &operator=(copack const &other)
    requires _trivially_copy_assignable
  = default;
  constexpr copack &operator=(copack const &other) noexcept(_nothrow_copy_assignable)
    requires(not _trivially_copy_assignable) && _copy_assignable
  {
    if (this != &other) {
      if (index == other.index) {
        detail::invoke_type_variadic_union<void, data_t>( //
            other.data, other.index,
            [this]<typename T>(::std::in_place_type_t<T>, auto const &v) { this->template _reassign<T>(v); });
      } else {
        detail::invoke_type_variadic_union<void, data_t>( //
            other.data, other.index,
            [this]<typename T>(::std::in_place_type_t<T>, auto const &v) { this->template _reinit<T>(v); });
      }
    }
    return *this;
  }

  /**
   * @brief Move assignment, with the strong exception guarantee
   *
   * @param other The copack to move from
   * @return Reference to `*this`
   */
  // The nothrow move construction is still demanded - `_reinit`'s replacement arm and `_reassign`'s
  // snapshot both rest on it - but the operator itself is only as nothrow as the alternatives' own
  // move assignment. Where moving can throw, a nothrow-copy-assignable copack is still assignable from
  // an rvalue, by copy.
  constexpr copack &operator=(copack &&other)
    requires _trivially_move_assignable
  = default;
  constexpr copack &operator=(copack &&other) noexcept(_nothrow_move_assignable)
    requires(not _trivially_move_assignable) && _move_assignable
  {
    if (this != &other) {
      if (index == other.index) {
        detail::invoke_type_variadic_union<void, data_t>( //
            ::std::move(other).data, other.index,
            [this]<typename T>(::std::in_place_type_t<T>, auto &&v) { this->template _reassign<T>(FWD(v)); });
      } else {
        detail::invoke_type_variadic_union<void, data_t>( //
            ::std::move(other).data, other.index,
            [this]<typename T>(::std::in_place_type_t<T>, auto &&v) { this->template _reinit<T>(FWD(v)); });
      }
    }
    return *this;
  }

  /**
   * @brief Widening copy assignment from a copack over a subset of the alternatives
   *
   * @param arg The narrower copack
   * @return Reference to `*this`
   */
  // Constrained on the alternatives the source can actually deliver, like the widening
  // constructors: routing through construction and same-type assignment would let an uninvolved
  // alternative of the destination forbid the assignment, and would build a whole temporary copack.
  // The incoming alternative is assigned in place when it is the one held, and replaces it by
  // construction otherwise, exactly as the same-type operator= does.
  template <typename... Tx>
  constexpr copack &operator=(copack<Tx...> const &arg) //
      noexcept((... && (::std::is_nothrow_copy_assignable_v<Tx> && detail::_nothrow_makeable<data_t, Tx, Tx const &>)))
    requires detail::is_superset_of<copack, copack<Tx...>> && (not ::std::is_same_v<copack, copack<Tx...>>)
             && (...
                 && (::std::is_copy_assignable_v<Tx> && detail::_makeable<data_t, Tx, Tx const &>
                     && (detail::_nothrow_makeable<data_t, Tx, Tx const &>
                         || detail::_nothrow_makeable<data_t, Tx, Tx>)))
             && (sizeof...(Tx) > 0)
  {
    arg.template _invoke<void>([this]<typename T>(::std::in_place_type_t<T>, auto const &v) {
      if (this->index == detail::type_index<T, Ts...>)
        this->template _reassign<T>(v);
      else
        this->template _reinit<T>(v);
    });
    return *this;
  }

  /**
   * @brief Widening move assignment from a copack over a subset of the alternatives
   *
   * @param arg The narrower copack
   * @return Reference to `*this`
   */
  template <typename... Tx>
  constexpr copack &operator=(copack<Tx...> &&arg) //
      noexcept((... && ::std::is_nothrow_move_assignable_v<Tx>))
    requires detail::is_superset_of<copack, copack<Tx...>> && (not ::std::is_same_v<copack, copack<Tx...>>)
             && (... && (::std::is_move_assignable_v<Tx> && detail::_nothrow_makeable<data_t, Tx, Tx>))
             && (sizeof...(Tx) > 0)
  {
    ::std::move(arg).template _invoke<void>([this]<typename T>(::std::in_place_type_t<T>, auto &&v) {
      if (this->index == detail::type_index<T, Ts...>)
        this->template _reassign<T>(FWD(v));
      else
        this->template _reinit<T>(FWD(v));
    });
    return *this;
  }

  /**
   * @brief Assignment from a value of one alternative, with the strong exception guarantee
   *
   * @param v Value of one alternative
   * @return Reference to `*this`
   */
  // Takes a value of exactly one alternative, as the converting constructors do - never
  // std::variant's converting-assignment resolution, so a convertible non-alternative stays
  // rejected and interconvertible alternatives never make a resolution puzzle. The one route
  // otherwise - converting constructor, then whole-copack assignment - builds a temporary copack and
  // lets an uninvolved alternative forbid the assignment; this overload consults only the
  // alternative involved, assigning in place when it is the one held and replacing by
  // construction otherwise.
  template <typename U, typename T = ::std::remove_cvref_t<U>>
  constexpr copack &operator=(U &&v) //
      noexcept(::std::is_nothrow_assignable_v<T &, decltype(v)> && detail::_nothrow_makeable<data_t, T, decltype(v)>)
    requires has_type<T> && ::std::is_assignable_v<T &, decltype(v)> && detail::_makeable<data_t, T, decltype(v)>
             && (detail::_nothrow_makeable<data_t, T, decltype(v)> || detail::_nothrow_makeable<data_t, T, T>)
  {
    if (index == detail::type_index<T, Ts...>)
      this->template _reassign<T>(FWD(v));
    else
      this->template _reinit<T>(FWD(v));
    return *this;
  }

  /**
   * @brief Destroys the alternative held and constructs a `T` from the arguments, with the strong
   *        exception guarantee
   *
   * @tparam T The alternative to construct
   * @param args Arguments to construct the new alternative from
   * @return Reference to the new alternative
   */
  // The mutation path for alternatives that do not support assignment: destroy-and-reconstruct,
  // requested at the call site by name, constructing a new `T` rather than claiming an assignment
  // the type refused. Always reconstructs, also when `T` is the alternative already held -
  // assign-when-same is `operator=`'s meaning and stays there - so the constraint asks about `T`
  // alone: the outgoing alternative is only destroyed, whatever its own traits. Arguments that
  // refer into the alternative held will dangle, as with std::optional's and std::variant's
  // emplace.
  template <typename T>
  constexpr T &emplace(auto &&...args) //
      noexcept(detail::_nothrow_makeable<data_t, T, decltype(args)...>)
    requires has_type<T> && detail::_makeable<data_t, T, decltype(args)...>
             && (detail::_nothrow_makeable<data_t, T, decltype(args)...> || detail::_nothrow_makeable<data_t, T, T>)
  {
    this->template _reinit<T>(FWD(args)...);
    return *detail::ptr_variadic_union<T, data_t>(this->data);
  }

  /**
   * @brief Checks if `T` is the active alternative
   *
   * @tparam T The alternative to ask about
   * @return Whether `T` is the alternative held
   */
  template <typename T>
    requires has_type<T>
  [[nodiscard]] constexpr bool has_value(::std::in_place_type_t<T> = ::std::in_place_type<T>) const noexcept
  {
    return detail::invoke_type_variadic_union<bool, data_t>( //
        this->data, index,
        []<typename U>(::std::in_place_type_t<U>, auto &&) constexpr -> bool { return ::std::is_same_v<T, U>; });
  }

  /**
   * @brief Pointer to the alternative `T`, or `nullptr` where it is not the one held
   *
   * The escape hatch for direct access: unlike `apply`, no dispatch and no exhaustiveness - the
   * caller names one alternative and tests the result.
   *
   * @tparam T The alternative to access
   * @return Pointer to the alternative, or `nullptr`
   */
  template <typename T>
    requires has_type<T>
  [[nodiscard]] constexpr T *get_ptr(::std::in_place_type_t<T> = ::std::in_place_type<T>) noexcept
  {
    return has_value(::std::in_place_type<T>) ? detail::ptr_variadic_union<T, data_t>(data) : nullptr;
  }

  template <typename T>
    requires has_type<T>
  [[nodiscard]] constexpr T const *get_ptr(::std::in_place_type_t<T> = ::std::in_place_type<T>) const noexcept
  {
    return has_value(::std::in_place_type<T>) ? detail::ptr_variadic_union<T, data_t>(data) : nullptr;
  }

  /**
   * @brief Eliminates the copack: the active alternative routes into the callable
   *
   * The dispatch is exhaustive - every alternative must have a viable arm, selected by ordinary
   * overload resolution - and the result type is deduced, so all alternatives must yield the same
   * one; `apply_r` serves where they differ. A tuple-like alternative is unpacked one level into
   * its elements, and trailing arguments follow the content.
   *
   * @param fn Callable applied on the active alternative; `fn::overload` fuses arms into one
   * @param args Additional arguments, appended after the alternative's content
   * @return The callable's result
   */
  template <typename Fn, typename... Args>
  [[nodiscard]] constexpr auto apply(Fn &&fn, Args &&...args) & noexcept(
      detail::_is_nothrow_rts_applicable<
          typename detail::_copack_apply_result<detail::_apply_autodetect_tag, Fn &&, copack &, Args &&...>::type,
          Fn &&, copack &, Args &&...>) ->
      typename detail::_copack_apply_result<detail::_apply_autodetect_tag, Fn &&, copack &, Args &&...>::type
    requires typelist_applicable<Fn, copack &, Args &&...>
  {
    using type = detail::_copack_apply_result<detail::_apply_autodetect_tag, Fn &&, copack &, Args &&...>::type;
    return detail::apply_variadic_union<type, data_t>(this->data, index, FWD(fn), FWD(args)...);
  }

  template <typename Fn, typename... Args>
  [[nodiscard]] constexpr auto apply(Fn &&fn, Args &&...args) const & noexcept(
      detail::_is_nothrow_rts_applicable<
          typename detail::_copack_apply_result<detail::_apply_autodetect_tag, Fn &&, copack const &, Args &&...>::type,
          Fn &&, copack const &, Args &&...>) ->
      typename detail::_copack_apply_result<detail::_apply_autodetect_tag, Fn &&, copack const &, Args &&...>::type
    requires typelist_applicable<Fn, copack const &, Args &&...>
  {
    using type = detail::_copack_apply_result<detail::_apply_autodetect_tag, Fn &&, copack const &, Args &&...>::type;
    return detail::apply_variadic_union<type, data_t>(this->data, index, FWD(fn), FWD(args)...);
  }

  template <typename Fn, typename... Args>
  [[nodiscard]] constexpr auto apply(Fn &&fn, Args &&...args) && noexcept(
      detail::_is_nothrow_rts_applicable<
          typename detail::_copack_apply_result<detail::_apply_autodetect_tag, Fn &&, copack &&, Args &&...>::type,
          Fn &&, copack &&, Args &&...>) ->
      typename detail::_copack_apply_result<detail::_apply_autodetect_tag, Fn &&, copack &&, Args &&...>::type
    requires typelist_applicable<Fn, copack &&, Args &&...>
  {
    using type = detail::_copack_apply_result<detail::_apply_autodetect_tag, Fn &&, copack &&, Args &&...>::type;
    return detail::apply_variadic_union<type, data_t>(::std::move(*this).data, index, FWD(fn), FWD(args)...);
  }

  template <typename Fn, typename... Args>
  [[nodiscard]] constexpr auto apply(Fn &&fn, Args &&...args) const && noexcept(
      detail::_is_nothrow_rts_applicable<typename detail::_copack_apply_result<detail::_apply_autodetect_tag, Fn &&,
                                                                               copack const &&, Args &&...>::type,
                                         Fn &&, copack const &&, Args &&...>) ->
      typename detail::_copack_apply_result<detail::_apply_autodetect_tag, Fn &&, copack const &&, Args &&...>::type
    requires typelist_applicable<Fn, copack const &&, Args &&...>
  {
    using type = detail::_copack_apply_result<detail::_apply_autodetect_tag, Fn &&, copack const &&, Args &&...>::type;
    return detail::apply_variadic_union<type, data_t>(::std::move(*this).data, index, FWD(fn), FWD(args)...);
  }

  /**
   * @brief Eliminates the copack, converting each branch's result to `Ret`
   *
   * The escape from result-type convergence: every alternative converts implicitly into its
   * parent copack, so `apply_r` targeting a `copack_for` of the branch results accepts branches
   * that disagree.
   *
   * @tparam Ret Type the results convert to
   * @param fn Callable applied on the active alternative; `fn::overload` fuses arms into one
   * @param args Additional arguments, appended after the alternative's content
   * @return The callable's result, converted to `Ret`
   */
  template <typename Ret, typename Fn, typename... Args>
  [[nodiscard]] constexpr auto
  apply_r(Fn &&fn, Args &&...args) & noexcept(detail::_is_nothrow_rts_applicable<Ret, Fn &&, copack &, Args &&...>)
      -> Ret
    requires typelist_applicable_r<Ret, Fn, copack &, Args &&...>
  {
    using type = detail::_copack_apply_result<Ret, Fn &&, copack &, Args &&...>::type;
    return detail::apply_variadic_union<type, data_t>(this->data, index, FWD(fn), FWD(args)...);
  }

  template <typename Ret, typename Fn, typename... Args>
  [[nodiscard]] constexpr auto apply_r(Fn &&fn, Args &&...args) const & noexcept(
      detail::_is_nothrow_rts_applicable<Ret, Fn &&, copack const &, Args &&...>) -> Ret
    requires typelist_applicable_r<Ret, Fn, copack const &, Args &&...>
  {
    using type = detail::_copack_apply_result<Ret, Fn &&, copack const &, Args &&...>::type;
    return detail::apply_variadic_union<type, data_t>(this->data, index, FWD(fn), FWD(args)...);
  }

  template <typename Ret, typename Fn, typename... Args>
  [[nodiscard]] constexpr auto
  apply_r(Fn &&fn, Args &&...args) && noexcept(detail::_is_nothrow_rts_applicable<Ret, Fn &&, copack &&, Args &&...>)
      -> Ret
    requires typelist_applicable_r<Ret, Fn, copack &&, Args &&...>
  {
    using type = detail::_copack_apply_result<Ret, Fn &&, copack &&, Args &&...>::type;
    return detail::apply_variadic_union<type, data_t>(::std::move(*this).data, index, FWD(fn), FWD(args)...);
  }

  template <typename Ret, typename Fn, typename... Args>
  [[nodiscard]] constexpr auto apply_r(Fn &&fn, Args &&...args) const && noexcept(
      detail::_is_nothrow_rts_applicable<Ret, Fn &&, copack const &&, Args &&...>) -> Ret
    requires typelist_applicable_r<Ret, Fn, copack const &&, Args &&...>
  {
    using type = detail::_copack_apply_result<Ret, Fn &&, copack const &&, Args &&...>::type;
    return detail::apply_variadic_union<type, data_t>(::std::move(*this).data, index, FWD(fn), FWD(args)...);
  }

  /**
   * @brief Eliminates the copack, keyed by the alternative's type
   *
   * The active arm receives `std::in_place_type<T>` for the alternative held, followed by its
   * content - a tuple-like alternative's elements form is the row's one signature - so the handler
   * knows which injection placed the value, even where C++'s implicit conversions would conflate
   * the payloads.
   *
   * @param fn Callable applied on the tag and the alternative's content
   * @param args Additional arguments, appended after the content
   * @return The callable's result
   */
  template <typename Fn, typename... Args>
  [[nodiscard]] constexpr auto apply_type(Fn &&fn, Args &&...args) & noexcept(
      detail::_is_nothrow_rtst_invocable<
          typename detail::_copack_invoke_type_result<detail::_apply_autodetect_tag, detail::_apply_type_fn<Fn>,
                                                      copack &, Args &&...>::type,
          detail::_apply_type_fn<Fn>, copack &, Args &&...>) ->
      typename detail::_copack_invoke_type_result<detail::_apply_autodetect_tag, detail::_apply_type_fn<Fn>, copack &,
                                                  Args &&...>::type
    requires detail::_typelist_type_invocable<detail::_apply_type_fn<Fn>, copack &, Args &&...>
  {
    using type = detail::_copack_invoke_type_result<detail::_apply_autodetect_tag, detail::_apply_type_fn<Fn>, copack &,
                                                    Args &&...>::type;
    return detail::invoke_type_variadic_union<type, data_t>(this->data, index, detail::_apply_type_fn<Fn>{FWD(fn)},
                                                            FWD(args)...);
  }

  template <typename Fn, typename... Args>
  [[nodiscard]] constexpr auto apply_type(Fn &&fn, Args &&...args) const & noexcept(
      detail::_is_nothrow_rtst_invocable<
          typename detail::_copack_invoke_type_result<detail::_apply_autodetect_tag, detail::_apply_type_fn<Fn>,
                                                      copack const &, Args &&...>::type,
          detail::_apply_type_fn<Fn>, copack const &, Args &&...>) ->
      typename detail::_copack_invoke_type_result<detail::_apply_autodetect_tag, detail::_apply_type_fn<Fn>,
                                                  copack const &, Args &&...>::type
    requires detail::_typelist_type_invocable<detail::_apply_type_fn<Fn>, copack const &, Args &&...>
  {
    using type = detail::_copack_invoke_type_result<detail::_apply_autodetect_tag, detail::_apply_type_fn<Fn>,
                                                    copack const &, Args &&...>::type;
    return detail::invoke_type_variadic_union<type, data_t>(this->data, index, detail::_apply_type_fn<Fn>{FWD(fn)},
                                                            FWD(args)...);
  }

  template <typename Fn, typename... Args>
  [[nodiscard]] constexpr auto apply_type(Fn &&fn, Args &&...args) && noexcept(
      detail::_is_nothrow_rtst_invocable<
          typename detail::_copack_invoke_type_result<detail::_apply_autodetect_tag, detail::_apply_type_fn<Fn>,
                                                      copack &&, Args &&...>::type,
          detail::_apply_type_fn<Fn>, copack &&, Args &&...>) ->
      typename detail::_copack_invoke_type_result<detail::_apply_autodetect_tag, detail::_apply_type_fn<Fn>, copack &&,
                                                  Args &&...>::type
    requires detail::_typelist_type_invocable<detail::_apply_type_fn<Fn>, copack &&, Args &&...>
  {
    using type = detail::_copack_invoke_type_result<detail::_apply_autodetect_tag, detail::_apply_type_fn<Fn>,
                                                    copack &&, Args &&...>::type;
    return detail::invoke_type_variadic_union<type, data_t>(::std::move(*this).data, index,
                                                            detail::_apply_type_fn<Fn>{FWD(fn)}, FWD(args)...);
  }

  template <typename Fn, typename... Args>
  [[nodiscard]] constexpr auto apply_type(Fn &&fn, Args &&...args) const && noexcept(
      detail::_is_nothrow_rtst_invocable<
          typename detail::_copack_invoke_type_result<detail::_apply_autodetect_tag, detail::_apply_type_fn<Fn>,
                                                      copack const &&, Args &&...>::type,
          detail::_apply_type_fn<Fn>, copack const &&, Args &&...>) ->
      typename detail::_copack_invoke_type_result<detail::_apply_autodetect_tag, detail::_apply_type_fn<Fn>,
                                                  copack const &&, Args &&...>::type
    requires detail::_typelist_type_invocable<detail::_apply_type_fn<Fn>, copack const &&, Args &&...>
  {
    using type = detail::_copack_invoke_type_result<detail::_apply_autodetect_tag, detail::_apply_type_fn<Fn>,
                                                    copack const &&, Args &&...>::type;
    return detail::invoke_type_variadic_union<type, data_t>(::std::move(*this).data, index,
                                                            detail::_apply_type_fn<Fn>{FWD(fn)}, FWD(args)...);
  }

  /**
   * @brief Eliminates the copack, keyed by the alternative's type, converting the result to `Ret`
   *
   * @tparam Ret Type the results convert to
   * @param fn Callable applied on the tag and the alternative's content
   * @param args Additional arguments, appended after the content
   * @return The callable's result, converted to `Ret`
   */
  template <typename Ret, typename Fn, typename... Args>
  [[nodiscard]] constexpr auto apply_type_r(Fn &&fn, Args &&...args) & noexcept(
      detail::_is_nothrow_rtst_invocable<Ret, detail::_apply_type_fn<Fn>, copack &, Args &&...>) -> Ret
    requires detail::_typelist_type_invocable_r<Ret, detail::_apply_type_fn<Fn>, copack &, Args &&...>
  {
    using type = detail::_copack_invoke_type_result<Ret, detail::_apply_type_fn<Fn>, copack &, Args &&...>::type;
    return detail::invoke_type_variadic_union<type, data_t>(this->data, index, detail::_apply_type_fn<Fn>{FWD(fn)},
                                                            FWD(args)...);
  }

  template <typename Ret, typename Fn, typename... Args>
  [[nodiscard]] constexpr auto apply_type_r(Fn &&fn, Args &&...args) const & noexcept(
      detail::_is_nothrow_rtst_invocable<Ret, detail::_apply_type_fn<Fn>, copack const &, Args &&...>) -> Ret
    requires detail::_typelist_type_invocable_r<Ret, detail::_apply_type_fn<Fn>, copack const &, Args &&...>
  {
    using type = detail::_copack_invoke_type_result<Ret, detail::_apply_type_fn<Fn>, copack const &, Args &&...>::type;
    return detail::invoke_type_variadic_union<type, data_t>(this->data, index, detail::_apply_type_fn<Fn>{FWD(fn)},
                                                            FWD(args)...);
  }

  template <typename Ret, typename Fn, typename... Args>
  [[nodiscard]] constexpr auto apply_type_r(Fn &&fn, Args &&...args) && noexcept(
      detail::_is_nothrow_rtst_invocable<Ret, detail::_apply_type_fn<Fn>, copack &&, Args &&...>) -> Ret
    requires detail::_typelist_type_invocable_r<Ret, detail::_apply_type_fn<Fn>, copack &&, Args &&...>
  {
    using type = detail::_copack_invoke_type_result<Ret, detail::_apply_type_fn<Fn>, copack &&, Args &&...>::type;
    return detail::invoke_type_variadic_union<type, data_t>(::std::move(*this).data, index,
                                                            detail::_apply_type_fn<Fn>{FWD(fn)}, FWD(args)...);
  }

  template <typename Ret, typename Fn, typename... Args>
  [[nodiscard]] constexpr auto apply_type_r(Fn &&fn, Args &&...args) const && noexcept(
      detail::_is_nothrow_rtst_invocable<Ret, detail::_apply_type_fn<Fn>, copack const &&, Args &&...>) -> Ret
    requires detail::_typelist_type_invocable_r<Ret, detail::_apply_type_fn<Fn>, copack const &&, Args &&...>
  {
    using type = detail::_copack_invoke_type_result<Ret, detail::_apply_type_fn<Fn>, copack const &&, Args &&...>::type;
    return detail::invoke_type_variadic_union<type, data_t>(::std::move(*this).data, index,
                                                            detail::_apply_type_fn<Fn>{FWD(fn)}, FWD(args)...);
  }

  /**
   * @brief Maps the alternatives, the branch results forming a new normalized copack
   *
   * The self-flattening map: the callable is dispatched exhaustively, and the branch results -
   * heterogeneous types allowed, a copack result dissolving into the set - flatten, deduplicate
   * and sort into the `copack_for` of them all.
   *
   * @param fn Callable applied on the active alternative; `fn::overload` fuses arms into one
   * @param args Additional arguments, appended after the alternative's content
   * @return A copack of the normalized branch-result set, holding the active branch's result
   */
  template <typename Fn, typename... Args>
  [[nodiscard]] constexpr auto transform(Fn &&fn, Args &&...args) & noexcept(
      detail::_is_nothrow_rts_applicable<
          typename detail::_copack_apply_result<detail::_collapsing_copack_tag, Fn &&, copack &, Args &&...>::type,
          Fn &&, copack &, Args &&...>) ->
      typename detail::_copack_apply_result<detail::_collapsing_copack_tag, Fn &&, copack &, Args &&...>::type
    requires typelist_applicable<Fn, copack &, Args &&...>
  {
    using type = detail::_copack_apply_result<detail::_collapsing_copack_tag, Fn &&, copack &, Args &&...>::type;
    return detail::apply_variadic_union<type, data_t>(this->data, index, FWD(fn), FWD(args)...);
  }

  template <typename Fn, typename... Args>
  [[nodiscard]] constexpr auto transform(Fn &&fn, Args &&...args) const & noexcept(
      detail::_is_nothrow_rts_applicable<typename detail::_copack_apply_result<detail::_collapsing_copack_tag, Fn &&,
                                                                               copack const &, Args &&...>::type,
                                         Fn &&, copack const &, Args &&...>) ->
      typename detail::_copack_apply_result<detail::_collapsing_copack_tag, Fn &&, copack const &, Args &&...>::type
    requires typelist_applicable<Fn, copack const &, Args &&...>
  {
    using type = detail::_copack_apply_result<detail::_collapsing_copack_tag, Fn &&, copack const &, Args &&...>::type;
    return detail::apply_variadic_union<type, data_t>(this->data, index, FWD(fn), FWD(args)...);
  }

  template <typename Fn, typename... Args>
  [[nodiscard]] constexpr auto transform(Fn &&fn, Args &&...args) && noexcept(
      detail::_is_nothrow_rts_applicable<
          typename detail::_copack_apply_result<detail::_collapsing_copack_tag, Fn &&, copack &&, Args &&...>::type,
          Fn &&, copack &&, Args &&...>) ->
      typename detail::_copack_apply_result<detail::_collapsing_copack_tag, Fn &&, copack &&, Args &&...>::type
    requires typelist_applicable<Fn, copack &&, Args &&...>
  {
    using type = detail::_copack_apply_result<detail::_collapsing_copack_tag, Fn &&, copack &&, Args &&...>::type;
    return detail::apply_variadic_union<type, data_t>(::std::move(*this).data, index, FWD(fn), FWD(args)...);
  }

  template <typename Fn, typename... Args>
  [[nodiscard]] constexpr auto transform(Fn &&fn, Args &&...args) const && noexcept(
      detail::_is_nothrow_rts_applicable<typename detail::_copack_apply_result<detail::_collapsing_copack_tag, Fn &&,
                                                                               copack const &&, Args &&...>::type,
                                         Fn &&, copack const &&, Args &&...>) ->
      typename detail::_copack_apply_result<detail::_collapsing_copack_tag, Fn &&, copack const &&, Args &&...>::type
    requires typelist_applicable<Fn, copack const &&, Args &&...>
  {
    using type = detail::_copack_apply_result<detail::_collapsing_copack_tag, Fn &&, copack const &&, Args &&...>::type;
    return detail::apply_variadic_union<type, data_t>(::std::move(*this).data, index, FWD(fn), FWD(args)...);
  }
};

// CTAD for single-element copack
template <typename T> explicit copack(::std::in_place_type_t<T>, auto &&...) -> copack<T>;
template <typename T> explicit copack(T) -> copack<::std::remove_cvref_t<T>>;

namespace detail {
// The value lift builds `copack<remove_cvref_t<Src>>` - a class whose body refuses an in_place tag as
// an alternative. MSVC (C++20 mode) compiles a candidate's noexcept-specifier once deduction
// succeeds, BEFORE the constraint rejects the tag, so the specifier must not name that copack unless
// the guard holds: a guarded specialization, as `_nothrow_eq_with` is, and for the same reason.
template <typename Src> constexpr inline bool _nothrow_copack_lift = false;
template <typename Src>
  requires(not some_in_place_type<Src>)
constexpr inline bool _nothrow_copack_lift<Src>
    = ::std::is_nothrow_constructible_v<copack<::std::remove_cvref_t<Src>>, Src>;
} // namespace detail

// Lifts
/**
 * @brief Lifts a value into a singular copack, decaying
 *
 * Unlike `as_pack`, always by value: a copack alternative can never be a reference.
 *
 * @param src Value to lift
 * @return A `copack` over the decayed type of `src`, holding it
 */
[[nodiscard]] constexpr auto as_copack(auto &&src) //
    noexcept(detail::_nothrow_copack_lift<decltype(src)>) -> decltype(auto)
  requires(not some_in_place_type<decltype(src)>)
{
  return copack<::std::remove_cvref_t<decltype(src)>>(FWD(src));
}

/**
 * @brief Lifts arguments into a singular copack of `T`, constructed in place
 *
 * @tparam T The sole alternative
 * @param args Arguments to construct the alternative from
 * @return `copack<T>` holding the alternative
 */
template <typename T>
[[nodiscard]] constexpr auto as_copack(::std::in_place_type_t<T>, auto &&...args) //
    noexcept(::std::is_nothrow_constructible_v<copack<T>, ::std::in_place_type_t<T>, decltype(args)...>)
        -> decltype(auto)
  requires ::std::is_constructible_v<copack<T>, ::std::in_place_type_t<T>, decltype(args)...>
{
  return copack<T>(::std::in_place_type<T>, FWD(args)...);
}

/**
 * @brief Compares two copacks: equal when they hold the same alternative type with equal values
 *
 * The copacks need not have the same alternative sets: an alternative the other side cannot hold
 * compares unequal without being compared - and need not even be equality-comparable.
 *
 * @param lh Left copack
 * @param rh Right copack
 * @return Whether the active alternatives are the same type with equal values
 */
template <typename... Ts, typename... Tx>
[[nodiscard]] constexpr bool operator==(copack<Ts...> const &lh, copack<Tx...> const &rh) //
    noexcept((... && detail::_nothrow_eq_with<Ts, Tx...>))
  requires(... && (::std::equality_comparable<Ts> || not detail::type_one_of<Ts, Tx...>)) //
          && ((sizeof...(Ts)) > 0) && ((sizeof...(Tx)) > 0)
{
  return lh.template _invoke<bool>([&rh]<typename T>(::std::in_place_type_t<T> d, auto const &lh) {
    if constexpr (::std::remove_cvref_t<decltype(rh)>::template has_type<T>) {
      return rh.has_value(d) && lh == *rh.get_ptr(d);
    } else {
      return false;
    }
  });
}

// No operator!=: C++20 rewrites `a != b` as `!(a == b)`, so the synthesized candidate inherits
// operator=='s constraints and the two cannot drift apart.

/**
 * @brief Builds the canonical `copack` for any list of types
 *
 * The user-facing construction alias: flattens nested copacks, deduplicates, and sorts into the
 * library's canonical order, resolving to the one valid `copack` - in an API signature the two
 * are the same type. Spell `copack_for` rather than `copack`, so that no spelling in your project
 * is tied to one compiler's alternative order.
 *
 * @tparam Ts Types to combine - alternatives and copacks of them, in any order, duplicates allowed
 */
template <typename... Ts>
using copack_for
    = detail::_collapsing_copack::normalized<::fn::copack, detail::_collapsing_copack::flattened<Ts...>>::type;

namespace detail {
template <typename T> struct _sole_alternative {};
template <typename T> struct _sole_alternative<::fn::copack<T>> {
  using type = T;
};
} // namespace detail

/**
 * @brief Accesses the sole alternative of a singular copack
 *
 * Only a `copack` with exactly one alternative qualifies - the access needs no dispatch and cannot
 * miss. Returns the alternative carrying the copack's cv-qualification and value category, exactly
 * as `apply` would pass it.
 *
 * @param c The singular copack, in any value category
 * @return Reference to the sole alternative
 */
template <typename Cp>
  requires requires { typename detail::_sole_alternative<::std::remove_cvref_t<Cp>>::type; }
[[nodiscard]] constexpr decltype(auto) get(Cp &&c) noexcept
{
  using type = detail::_sole_alternative<::std::remove_cvref_t<Cp>>::type;
  if constexpr (::std::is_lvalue_reference_v<Cp>)
    return (*c.get_ptr(::std::in_place_type<type>));
  else
    return ::std::move(*c.get_ptr(::std::in_place_type<type>));
}

namespace detail {
// The graded joins for expected's binds over a copack side, when the exhaustive branches return
// DIFFERENT expected types. Sets convergent in the exact result type fall back to the select
// trait, preserving today's behaviour and diagnostics verbatim - exact, not stripped, because
// select compares exact types and a set convergent only after removing cv/ref would reach its
// assert; such a set engages the join like any heterogeneous all-expected one. An invalid set -
// a non-expected result, mixed void and non-void values, or a plain fixed side some branch does
// not retain - leaves no `type`, so asking answers instead of erroring. Tpl is the caller's own
// two-parameter carrier, keeping this header free of the expected dependency.
template <template <typename...> typename Tpl, typename E> struct _joining_expected_tag final {};
template <template <typename...> typename Tpl, typename T> struct _joining_recovery_tag final {};
template <template <typename...> typename Tpl> struct _joining_optional_tag final {};
template <template <typename...> typename Tpl, typename T> struct _joining_optional_recovery_tag final {};

namespace _joining_expected {
template <typename T> struct parts;
template <template <typename...> typename Tpl, typename V, typename E> struct parts<Tpl<V, E>> {
  using value_type = V;
  using error_type = E;
};

template <typename T> struct parts_one;
template <template <typename...> typename T1, typename V> struct parts_one<T1<V>> {
  using type = V;
};

template <typename... Ts> constexpr inline bool all_same = true; // zero or one element
template <typename T0, typename... Ts>
  requires(sizeof...(Ts) > 0)
constexpr inline bool all_same<T0, Ts...> = (... && ::std::is_same_v<T0, Ts>);

// the dispatched side's join: exact convergence preserved; heterogeneous types splice through
// copack_for (a copack-typed result flattens into it); mixed void and non-void has no answer
template <typename... Ts> struct list_join {};
template <typename T0, typename... Ts>
  requires all_same<T0, Ts...>
struct list_join<T0, Ts...> {
  using type = T0;
};
template <typename T0, typename... Ts>
  requires(not all_same<T0, Ts...>) && _collapsible_result<T0> && (... && _collapsible_result<Ts>)
struct list_join<T0, Ts...> {
  using type = ::fn::copack_for<T0, Ts...>;
};

// the carried side's join, unioned with self's own grade: a copack side joins everything (an
// empty one vanishes into the union); a plain side must be retained by every branch exactly
template <typename E, typename... Es> struct graded_join {};
template <typename E, typename... Es>
  requires _some_copack<E>
struct graded_join<E, Es...> {
  using type = ::fn::copack_for<E, Es...>;
};
template <typename E, typename... Es>
  requires(not _some_copack<E>) && (... && ::std::is_same_v<E, Es>)
struct graded_join<E, Es...> {
  using type = E;
};
// ... or by its singular lift copack<E>, which then spells the result: grading never silently
// drops, so one graded branch lifts the plain side and the plain branches with it
template <typename E, typename... Es>
  requires(not _some_copack<E>) && (not(... && ::std::is_same_v<E, Es>))
          && (... && (::std::is_same_v<E, Es> || ::std::is_same_v<::fn::copack<E>, Es>))
struct graded_join<E, Es...> {
  using type = ::fn::copack<E>;
};
} // namespace _joining_expected

template <template <typename...> typename Tpl, typename E, typename... Rs> struct _joined_expected {};
template <template <typename...> typename Tpl, typename E, typename... Rs>
  requires requires {
    typename _joining_expected::list_join<typename _joining_expected::parts<Rs>::value_type...>::type;
    typename _joining_expected::graded_join<E, typename _joining_expected::parts<Rs>::error_type...>::type;
  }
struct _joined_expected<Tpl, E, Rs...> {
  static constexpr bool _hetero_join = true;
  using type
      = Tpl<typename _joining_expected::list_join<typename _joining_expected::parts<Rs>::value_type...>::type,
            typename _joining_expected::graded_join<E, typename _joining_expected::parts<Rs>::error_type...>::type>;
};

template <template <typename...> typename Tpl, typename T, typename... Rs> struct _joined_recovery {};
template <template <typename...> typename Tpl, typename T, typename... Rs>
  requires requires {
    typename _joining_expected::graded_join<T, typename _joining_expected::parts<Rs>::value_type...>::type;
    typename _joining_expected::list_join<typename _joining_expected::parts<Rs>::error_type...>::type;
  }
struct _joined_recovery<Tpl, T, Rs...> {
  static constexpr bool _hetero_join = true;
  using type
      = Tpl<typename _joining_expected::graded_join<T, typename _joining_expected::parts<Rs>::value_type...>::type,
            typename _joining_expected::list_join<typename _joining_expected::parts<Rs>::error_type...>::type>;
};

template <template <typename...> typename Tpl, typename... Rs> struct _joined_optional {};
template <template <typename...> typename Tpl, typename... Rs>
  requires requires { typename _joining_expected::list_join<typename _joining_expected::parts_one<Rs>::type...>::type; }
struct _joined_optional<Tpl, Rs...> {
  static constexpr bool _hetero_join = true;
  using type = Tpl<typename _joining_expected::list_join<typename _joining_expected::parts_one<Rs>::type...>::type>;
};

// the recovery join into a one-parameter carrier: self's pass-through value joins every branch's
// value under the grade-sticky rules; unlike the same-kind traits there is no select tier - self's
// value must always enter the join, which handles exact convergence itself
template <template <typename...> typename Tpl, typename T, typename... Rs> struct _joined_optional_recovery {};
template <template <typename...> typename Tpl, typename T, typename... Rs>
  requires requires {
    typename _joining_expected::graded_join<T, typename _joining_expected::parts_one<Rs>::type...>::type;
  }
struct _joined_optional_recovery<Tpl, T, Rs...> {
  static constexpr bool _hetero_join = true;
  using type
      = Tpl<typename _joining_expected::graded_join<T, typename _joining_expected::parts_one<Rs>::type...>::type>;
};

// a heterogeneous set that is not all-expected answers (no `type`), it does not assert: the join
// owns every heterogeneous shape, and only convergent sets keep the select trait's diagnostics
struct _no_join {};

template <typename T>
concept _is_hetero_join = requires { T::_hetero_join; };

// Applicability of the bind's dispatch: per-branch for a copack side - the autodetect
// _is_applicable would substitute the select trait's type and trip its convergence assert for the
// very sets the join owns - plain _is_applicable otherwise.
template <typename Fn, typename V> constexpr inline bool _bind_applicable = _is_applicable<Fn, V>::value;
template <typename Fn, typename V>
  requires _some_copack<::std::remove_cvref_t<V>>
constexpr inline bool _bind_applicable<Fn, V> = _is_ts_applicable<Fn, V>;

template <template <typename...> typename Tpl, typename E, typename Fn, typename Self, typename T, typename... Args>
struct _typelist_joining_expected;
template <template <typename...> typename Tpl, typename E, typename Fn, typename Self,
          template <typename...> typename Tpl2, typename... Ts, typename... Args>
struct _typelist_joining_expected<Tpl, E, Fn, Self, Tpl2<Ts...>, Args...>
    : ::std::conditional_t<
          (sizeof...(Ts) == 0), _no_join,
          ::std::conditional_t<
              _joining_expected::all_same<
                  typename ::fn::detail::_apply_result<Fn, apply_const_lvalue_t<Self, Ts>, Args...>::type...>,
              _typelist_select_apply_result<Fn, Self, Tpl2<Ts...>, Args...>,
              ::std::conditional_t<
                  (...
                   && _joining_superset::is_kind<Tpl, ::std::remove_cvref_t<typename ::fn::detail::_apply_result<
                                                          Fn, apply_const_lvalue_t<Self, Ts>, Args...>::type>>),
                  _joined_expected<Tpl, E,
                                   ::std::remove_cvref_t<typename ::fn::detail::_apply_result<
                                       Fn, apply_const_lvalue_t<Self, Ts>, Args...>::type>...>,
                  _no_join>>> {};

template <template <typename...> typename Tpl, typename T, typename Fn, typename Self, typename U, typename... Args>
struct _typelist_joining_recovery;
template <template <typename...> typename Tpl, typename T, typename Fn, typename Self,
          template <typename...> typename Tpl2, typename... Ts, typename... Args>
struct _typelist_joining_recovery<Tpl, T, Fn, Self, Tpl2<Ts...>, Args...>
    : ::std::conditional_t<
          (sizeof...(Ts) == 0), _no_join,
          ::std::conditional_t<
              _joining_expected::all_same<
                  typename ::fn::detail::_apply_result<Fn, apply_const_lvalue_t<Self, Ts>, Args...>::type...>,
              _typelist_select_apply_result<Fn, Self, Tpl2<Ts...>, Args...>,
              ::std::conditional_t<
                  (...
                   && _joining_superset::is_kind<Tpl, ::std::remove_cvref_t<typename ::fn::detail::_apply_result<
                                                          Fn, apply_const_lvalue_t<Self, Ts>, Args...>::type>>),
                  _joined_recovery<Tpl, T,
                                   ::std::remove_cvref_t<typename ::fn::detail::_apply_result<
                                       Fn, apply_const_lvalue_t<Self, Ts>, Args...>::type>...>,
                  _no_join>>> {};

template <template <typename...> typename Tpl, typename E, typename Fn, typename Self, typename... Args>
struct _copack_apply_result<_joining_expected_tag<Tpl, E>, Fn, Self, Args...>
    : _typelist_joining_expected<Tpl, E, Fn, Self, ::std::remove_cvref_t<Self>, Args...> {};

template <template <typename...> typename Tpl, typename T, typename Fn, typename Self, typename... Args>
struct _copack_apply_result<_joining_recovery_tag<Tpl, T>, Fn, Self, Args...>
    : _typelist_joining_recovery<Tpl, T, Fn, Self, ::std::remove_cvref_t<Self>, Args...> {};

template <template <typename...> typename Tpl, typename Fn, typename Self, typename U, typename... Args>
struct _typelist_joining_optional;
template <template <typename...> typename Tpl, typename Fn, typename Self, template <typename...> typename Tpl2,
          typename... Ts, typename... Args>
struct _typelist_joining_optional<Tpl, Fn, Self, Tpl2<Ts...>, Args...>
    : ::std::conditional_t<
          (sizeof...(Ts) == 0), _no_join,
          ::std::conditional_t<
              _joining_expected::all_same<
                  typename ::fn::detail::_apply_result<Fn, apply_const_lvalue_t<Self, Ts>, Args...>::type...>,
              _typelist_select_apply_result<Fn, Self, Tpl2<Ts...>, Args...>,
              ::std::conditional_t<
                  (...
                   && _joining_superset::is_kind<Tpl, ::std::remove_cvref_t<typename ::fn::detail::_apply_result<
                                                          Fn, apply_const_lvalue_t<Self, Ts>, Args...>::type>>),
                  _joined_optional<Tpl, ::std::remove_cvref_t<typename ::fn::detail::_apply_result<
                                            Fn, apply_const_lvalue_t<Self, Ts>, Args...>::type>...>,
                  _no_join>>> {};

template <template <typename...> typename Tpl, typename Fn, typename Self, typename... Args>
struct _copack_apply_result<_joining_optional_tag<Tpl>, Fn, Self, Args...>
    : _typelist_joining_optional<Tpl, Fn, Self, ::std::remove_cvref_t<Self>, Args...> {};

template <template <typename...> typename Tpl, typename T, typename Fn, typename Self, typename U, typename... Args>
struct _typelist_joining_optional_recovery;
template <template <typename...> typename Tpl, typename T, typename Fn, typename Self,
          template <typename...> typename Tpl2, typename... Ts, typename... Args>
struct _typelist_joining_optional_recovery<Tpl, T, Fn, Self, Tpl2<Ts...>, Args...>
    : ::std::conditional_t<
          (sizeof...(Ts) == 0), _no_join,
          ::std::conditional_t<
              (...
               && _joining_superset::is_kind<Tpl, ::std::remove_cvref_t<typename ::fn::detail::_apply_result<
                                                      Fn, apply_const_lvalue_t<Self, Ts>, Args...>::type>>),
              _joined_optional_recovery<Tpl, T,
                                        ::std::remove_cvref_t<typename ::fn::detail::_apply_result<
                                            Fn, apply_const_lvalue_t<Self, Ts>, Args...>::type>...>,
              _no_join>> {};

template <template <typename...> typename Tpl, typename T, typename Fn, typename Self, typename... Args>
struct _copack_apply_result<_joining_optional_recovery_tag<Tpl, T>, Fn, Self, Args...>
    : _typelist_joining_optional_recovery<Tpl, T, Fn, Self, ::std::remove_cvref_t<Self>, Args...> {};

// The cluster bind's join - the verb layer's licensed cross-carrier dispatch over a bare copack
// payload. The same superset join as the choice members', under the asking rule of the joining
// traits here: an all-Tpl set joins into the normalized superset, a set convergent in the exact
// result type keeps the select trait's answer verbatim, every other set leaves no `type` - the
// members' fall-back to select would assert where a probing concept must get an answer. The
// convergence tier must be exact, not stripped: select compares exact result types, so a set
// convergent only after removing cv/ref would reach its assert.
template <template <typename...> typename Tpl> struct _joining_cluster_tag final {};

template <template <typename...> typename Tpl, typename Fn, typename Self, typename T, typename... Args>
struct _typelist_joining_cluster;
template <template <typename...> typename Tpl, typename Fn, typename Self, template <typename...> typename Tpl2,
          typename... Ts, typename... Args>
struct _typelist_joining_cluster<Tpl, Fn, Self, Tpl2<Ts...>, Args...>
    : ::std::conditional_t<
          (sizeof...(Ts) == 0), _no_join,
          ::std::conditional_t<
              (...
               && _joining_superset::is_kind<Tpl, ::std::remove_cvref_t<typename ::fn::detail::_apply_result<
                                                      Fn, apply_const_lvalue_t<Self, Ts>, Args...>::type>>),
              _joining_superset_type<Tpl, ::std::remove_cvref_t<typename ::fn::detail::_apply_result<
                                              Fn, apply_const_lvalue_t<Self, Ts>, Args...>::type>...>,
              ::std::conditional_t<_joining_expected::all_same<typename ::fn::detail::_apply_result<
                                       Fn, apply_const_lvalue_t<Self, Ts>, Args...>::type...>,
                                   _typelist_select_apply_result<Fn, Self, Tpl2<Ts...>, Args...>, _no_join>>> {};

template <template <typename...> typename Tpl, typename Fn, typename Self, typename... Args>
struct _copack_apply_result<_joining_cluster_tag<Tpl>, Fn, Self, Args...>
    : _typelist_joining_cluster<Tpl, Fn, Self, ::std::remove_cvref_t<Self>, Args...> {};

// The tag-generic engine entry for join-mode dispatch over a copack side: each branch converts
// into the tag's announced result. Serves expected's graded binds and the verb layer's cluster arm
template <typename Tag, typename Cp, typename Fn>
  requires _some_copack<::std::remove_cvref_t<Cp>>
[[nodiscard]] constexpr auto _tagged_join_apply(Cp &&cp, Fn &&fn) //
    noexcept(_is_nothrow_rts_applicable<typename _copack_apply_result<Tag, Fn &&, Cp &&>::type, Fn &&, Cp &&>) ->
    typename _copack_apply_result<Tag, Fn &&, Cp &&>::type
{
  using type = _copack_apply_result<Tag, Fn &&, Cp &&>::type;
  using data_t = ::std::remove_cvref_t<Cp>::data_t;
  return apply_variadic_union<type, data_t>(FWD(cp).data, cp.index, FWD(fn));
}
} // namespace detail

} // namespace LIBFN_VERSION
} // namespace fn

// ---------- BEGIN fn/detail/macro_end.hpp ----------
// Deliberately no include guard: see fn/detail/macro_begin.hpp.

#undef FWD // NOSONAR cpp:S959 paired with the define in macro_begin.hpp
#pragma pop_macro("FWD")

#undef DEDUCED_RETURN // NOSONAR cpp:S959 paired with the define in macro_begin.hpp
#pragma pop_macro("DEDUCED_RETURN")
// ---------- END fn/detail/macro_end.hpp ----------

// ---------- RESUME fn/copack.hpp ----------

#endif // INCLUDE_FN_COPACK
// ---------- END fn/copack.hpp ----------

// ---------- RESUME fn/choice.hpp ----------

// ---------- RESUME fn/choice.hpp ----------

// ---------- BEGIN fn/fwd.hpp ----------
#ifndef INCLUDE_FN_FWD
#define INCLUDE_FN_FWD

// For exposition only
// ---------- RESUME fn/fwd.hpp ----------

#endif // INCLUDE_FN_FWD
// ---------- END fn/fwd.hpp ----------

// ---------- RESUME fn/choice.hpp ----------

// ---------- BEGIN fn/just.hpp ----------
#ifndef INCLUDE_FN_JUST
#define INCLUDE_FN_JUST

// ---------- RESUME fn/just.hpp ----------

// ---------- RESUME fn/just.hpp ----------

// ---------- RESUME fn/just.hpp ----------

// ---------- RESUME fn/just.hpp ----------

// ---------- RESUME fn/just.hpp ----------

// ---------- BEGIN fn/pack.hpp ----------
#ifndef INCLUDE_FN_PACK
#define INCLUDE_FN_PACK

// ---------- RESUME fn/pack.hpp ----------

// ---------- RESUME fn/pack.hpp ----------

// ---------- BEGIN fn/detail/pack_impl.hpp ----------
#ifndef INCLUDE_FN_DETAIL_PACK_IMPL
#define INCLUDE_FN_DETAIL_PACK_IMPL

// ---------- RESUME fn/detail/pack_impl.hpp ----------

// ---------- RESUME fn/detail/pack_impl.hpp ----------

// ---------- RESUME fn/detail/pack_impl.hpp ----------

// ---------- RESUME fn/detail/pack_impl.hpp ----------

// ---------- RESUME fn/detail/pack_impl.hpp ----------

// ---------- BEGIN fn/detail/macro_begin.hpp ----------
// Deliberately no include guard: this header and fn/detail/macro_end.hpp bracket the section of a
// header that uses the macros below; push_macro/pop_macro make the bracketing safe under nesting
// and preserve any prior user definition.

#pragma push_macro("FWD")
#undef FWD // NOSONAR cpp:S959 saved by push_macro above

// This FWD macro is a functional equivalent to std::forward<decltype(v)>(v),
// but it saves compilation time (and typing) when used frequently.
#define FWD(...) static_cast<decltype(__VA_ARGS__) &&>(__VA_ARGS__)

#pragma push_macro("DEDUCED_RETURN")
#undef DEDUCED_RETURN // NOSONAR cpp:S959 saved by push_macro above

// Spell a function's deduced return type explicitly on MSVC only. MSVC mis-resolves a deduced
// (`auto`/`decltype(auto)`) return whose type derives from a body-local alias, leaking it as an
// opaque dependent type; an explicit trailing return type is the fix. Every other compiler keeps
// `decltype(auto)` — the natural spelling — which by construction deduces `decltype(EXPR)` on
// `return EXPR;`, so the two are the same type and this is a no-op off MSVC.
//
// Confining `decltype(EXPR)` to MSVC also keeps it off clang <= 20, which in C++23 substitutes a
// non-viable constrained overload's trailing return type BEFORE its requires-clause rejects it
// (fixed clang 21), so the explicit form would fail to compile instead of removing the non-viable
// function from the overload set.
#ifndef _MSC_VER
#define DEDUCED_RETURN(...) decltype(auto)
#else
#define DEDUCED_RETURN(...) decltype(__VA_ARGS__)
#endif
// ---------- END fn/detail/macro_begin.hpp ----------

// ---------- RESUME fn/detail/pack_impl.hpp ----------

namespace fn::inline LIBFN_VERSION::detail {
template <::std::size_t I, typename T> struct _element {
  static_assert(not ::std::is_rvalue_reference_v<T>);
  T v; // NOSONAR cpp:S6226 MSVC ignores the attribute
};

// Initializes one element. A reference element is spelled as a cast rather than `T{arg}`: the two
// are the same thing ([expr.type.conv]/1.3 defines the latter as direct-initializing an invented
// variable of type T, and [dcl.init.list]/3.9 initializes a reference from a single element whose
// type is reference-related to it, i.e. binds), but gcc reads the braced form as materializing a
// temporary and rejects the bind - while accepting the equivalent declaration. The cast keeps both
// compilers on the binding path.
template <typename T>
[[nodiscard]] constexpr auto _make_element(auto &&...args) noexcept(_nothrow_initializable<T, decltype(args)...>) -> T
  requires _initializable<T, decltype(args)...>
{
  if constexpr (::std::is_reference_v<T>)
    return T(FWD(args)...); // a single argument, so this is a cast expression: it binds
  else
    return T{FWD(args)...};
}

// The two questions anyone above may ask about constructing an element, asked OF the function that
// constructs it rather than restated in terms of a trait - the same discipline as `_makeable` beside
// `make_variadic_union`, and for the same reason: a restatement can drift from the deed.
template <typename T, typename... Args>
concept _makeable_element = requires { _make_element<T>(::std::declval<Args>()...); };

template <typename T, typename... Args>
concept _nothrow_makeable_element = requires { requires noexcept(_make_element<T>(::std::declval<Args>()...)); };

// One element's relocation into a new pack: the copy-initialization its holder performs
// ([dcl.init.aggr]/4.3, reached through brace elision), asked of the holder one element at a time -
// `_element<I, T>{src}` elides into the same member copy-initialization. This excludes explicit
// constructors, where `is_[nothrow_]constructible_v` would admit them.
template <typename E, typename Src>
concept _relocatable_element = requires { E{::std::declval<Src>()}; };

template <typename E, typename Src>
concept _nothrow_relocatable_element = requires { requires noexcept(E{::std::declval<Src>()}); };

// The algebra's own constructors are not elements: a copack must distribute over the product, and a
// nested pack is a non-canonical spelling of the flat product with no consistent shape (apply
// flattens it, the tuple protocol preserves it). Foreign structured types stay opaque atoms.
template <typename T> static constexpr bool _is_valid_pack_element = (not _some_copack<T>) && (not _some_pack<T>);

template <typename T> constexpr inline bool _spliceable_pack = false;
template <typename... Tx>
constexpr inline bool _spliceable_pack<::fn::pack<Tx...>> = (... && _is_valid_pack_element<Tx>);

template <typename, typename... Ts> struct pack_impl;

template <typename... Ts> struct _pack_append;
// A pack never holds a copack. The specialization is defined but has no `type`, so naming
// `append_type<copack>` is a substitution failure rather than a use of an incomplete type; and the
// specializations must exclude each other, or more than one matches and the choice is ambiguous.
template <typename T, typename... Ts>
  requires _some_copack<T>
struct _pack_append<T, Ts...> {};
template <typename T, typename... Ts>
  requires(not _some_pack<T>) && (not _some_copack<T>)
struct _pack_append<T, Ts...> {
  using impl = pack_impl<::std::index_sequence_for<Ts..., T>, Ts..., T>;
  using type = ::fn::pack<Ts..., T>;
};

template <typename T, typename... Ts> struct _pack_append_pack;
template <typename... Tx, typename... Ts> struct _pack_append_pack<::fn::pack<Tx...>, Ts...> {
  using impl = pack_impl<::std::index_sequence_for<Ts..., Tx...>, Ts..., Tx...>;
  using type = ::fn::pack<Ts..., Tx...>;
};
// A tag can NAME a pack type whose own elements are invalid without instantiating it; splicing it
// would instantiate the ill-formed result. Same shape as the copack case: defined without `type`, so
// asking stays a substitution failure.
template <typename T, typename... Ts>
  requires _some_pack<T> && (not _spliceable_pack<::std::remove_cvref_t<T>>)
struct _pack_append<T, Ts...> {};
template <typename T, typename... Ts>
  requires _some_pack<T> && _spliceable_pack<::std::remove_cvref_t<T>>
struct _pack_append<T, Ts...> {
  using impl = _pack_append_pack<::std::remove_cvref_t<T>, Ts...>::impl;
  using type = _pack_append_pack<::std::remove_cvref_t<T>, Ts...>::type;
};

template <::std::size_t... Is, typename... Ts>
struct pack_impl<::std::index_sequence<Is...>, Ts...> : _element<Is, Ts>... {
  static constexpr ::std::size_t size = sizeof...(Is);

  // Comparison is element-wise rather than defaulted, because a defaulted comparison over a
  // reference member is deleted outright, where a reference element must compare its REFERENT - the
  // semantics of optional<T&> and of std::tuple. Asked of the elements as the fold reaches them, so
  // an element which cannot be compared leaves the operator non-viable rather than ill-formed; the
  // `&&` fold answers true for the empty pack, and the `||` fold stops at the first element that
  // orders. No ordering is synthesized from `<`: an element brings its own `<=>` or none.
  template <typename Self>
  static constexpr auto _equal(Self const &lh, Self const &rh) //
      noexcept((... && noexcept(static_cast<bool>(lh._element<Is, Ts>::v == rh._element<Is, Ts>::v)))) -> bool
    requires(... && requires {
      { lh._element<Is, Ts>::v == rh._element<Is, Ts>::v } -> ::std::convertible_to<bool>;
    })
  {
    return (... && static_cast<bool>(lh._element<Is, Ts>::v == rh._element<Is, Ts>::v));
  }

  // The common category is `void` - a valid return type, not a substitution failure - when an
  // element's `<=>` answers something that is not a comparison category, or when the elements'
  // categories have no common one. Left unsaid, that would make the operator viable to ask about and
  // ill-formed to use, so it is said.
  template <typename Self>
  static constexpr auto _compare(Self const &lh, Self const &rh) //
      noexcept((... && noexcept(lh._element<Is, Ts>::v <=> rh._element<Is, Ts>::v)))
          -> ::std::common_comparison_category_t<decltype(lh._element<Is, Ts>::v <=> rh._element<Is, Ts>::v)...>
    requires(not ::std::is_void_v<
             ::std::common_comparison_category_t<decltype(lh._element<Is, Ts>::v <=> rh._element<Is, Ts>::v)...>>)
  {
    using type = ::std::common_comparison_category_t<decltype(lh._element<Is, Ts>::v <=> rh._element<Is, Ts>::v)...>;
    type result = type::equivalent;
    [[maybe_unused]] bool const ordered
        = (((result = (lh._element<Is, Ts>::v <=> rh._element<Is, Ts>::v)) != 0) || ...);
    return result;
  }

  template <typename Self, typename Fn, typename... Args>
    requires(not(... || (_some_pack<Args> || _some_copack<Args>)))
  static constexpr auto _swap_invoke(Self &&self, Fn &&fn, Args &&...args) //
      noexcept(::std::is_nothrow_invocable_v<Fn &&, Args &&..., apply_const_lvalue_t<Self, Ts &&>...>)
          -> ::std::invoke_result<Fn &&, Args &&..., apply_const_lvalue_t<Self, Ts &&>...>::type
    requires(::std::is_invocable<Fn &&, Args && ..., apply_const_lvalue_t<Self, Ts &&>...>::value)
  {
    return ::std::invoke(FWD(fn), FWD(args)...,
                         static_cast<apply_const_lvalue_t<Self, Ts &&>>(FWD(self)._element<Is, Ts>::v)...);
  }

  // The pack's elements are the argument list, and every argument is terminal: handed over whole
  // via INVOKE, never re-entering elimination. Routing through the engine instead would give a
  // lone tuple-like element std::apply's meaning, making its treatment depend on its siblings.
  template <typename Self, typename Fn, typename... Args>
    requires(not(... || (_some_pack<Args> || _some_copack<Args>)))
  static constexpr auto _apply(Self &&self, Fn &&fn, Args &&...args) //
      noexcept(::std::is_nothrow_invocable_v<Fn &&, apply_const_lvalue_t<Self, Ts &&>..., Args &&...>)
          -> ::std::invoke_result<Fn &&, apply_const_lvalue_t<Self, Ts &&>..., Args &&...>::type
    requires(::std::is_invocable<Fn &&, apply_const_lvalue_t<Self, Ts &&>..., Args && ...>::value)
  {
    return ::std::invoke(FWD(fn), static_cast<apply_const_lvalue_t<Self, Ts &&>>(FWD(self)._element<Is, Ts>::v)...,
                         FWD(args)...);
  }

  template <typename Ret, typename Self, typename Fn, typename... Args>
    requires(not(... || (_some_pack<Args> || _some_copack<Args>)))
  static constexpr auto _apply_r(Self &&self, Fn &&fn, Args &&...args) //
      noexcept(::std::is_nothrow_invocable_r_v<Ret, Fn &&, apply_const_lvalue_t<Self, Ts &&>..., Args &&...>) -> Ret
    requires(::std::is_invocable_r<Ret, Fn &&, apply_const_lvalue_t<Self, Ts &&>..., Args && ...>::value)
  {
    return ::pfn::invoke_r<Ret>(
        FWD(fn), static_cast<apply_const_lvalue_t<Self, Ts &&>>(FWD(self)._element<Is, Ts>::v)..., FWD(args)...);
  }

  template <::std::size_t I, typename Self>
  static constexpr decltype(auto) _get(Self &&self) noexcept
    requires(I < size)
  {
    return static_cast<apply_const_lvalue_t<Self, select_nth_t<I, Ts...> &&>>(
        FWD(self)._element<I, select_nth_t<I, Ts...>>::v);
  }

  template <typename T> using append_type = _pack_append<T, Ts...>::type;

  // Every existing element is relocated into the new pack, so appending weighs that as well as the
  // construction of the element being appended.
  template <typename Self>
  static constexpr bool _relocatable
      = (... && _relocatable_element<_element<Is, Ts>, apply_const_lvalue_t<Self, Ts &&>>);

  template <typename Self>
  static constexpr bool _nothrow_relocatable
      = (... && _nothrow_relocatable_element<_element<Is, Ts>, apply_const_lvalue_t<Self, Ts &&>>);

  template <typename T, typename Self>
  static constexpr auto _append(Self &&self, auto &&...args) //
      noexcept(_nothrow_relocatable<Self> && _nothrow_makeable_element<T, decltype(args)...>)
          -> pack_impl<::std::index_sequence<Is..., size>, Ts..., T>
    requires(not _some_copack<T>) && (not _some_pack<T>)
            && _relocatable<Self> && _makeable_element<T, decltype(args)...>
  {
    return {static_cast<apply_const_lvalue_t<Self, Ts &&>>(FWD(self)._element<Is, Ts>::v)...,
            _make_element<T>(FWD(args)...)};
  }

  // Splicing is normalization, not elimination: the appended pack's elements relocate through
  // INVOKE, so a lone tuple-like element arrives whole instead of taking std::apply's meaning
  // through the engine's tuple arm.
  template <typename T, typename Self>
  static constexpr auto _append(Self &&self, auto &&other) //
      noexcept(_nothrow_relocatable<Self>
               && ::std::remove_cvref_t<T>::_impl::template _nothrow_relocatable<decltype(other)>) -> //
      typename _pack_append<::std::remove_cvref_t<T>, Ts...>::impl
    requires _some_pack<T> && (::std::is_same_v<::std::remove_cvref_t<decltype(other)>, ::std::remove_cvref_t<T>>)
             && _relocatable<Self> && ::std::remove_cvref_t<T>::_impl::template
  _relocatable<decltype(other)>
  {
    using type = _pack_append<::std::remove_cvref_t<T>, Ts...>::impl;
    return FWD(other)._swap_invoke(FWD(other), [&self](auto &&...args) {
      return type{static_cast<apply_const_lvalue_t<Self, Ts &&>>(FWD(self)._element<Is, Ts>::v)..., FWD(args)...};
    });
  }

  // The tag form constructs the named pack from the arguments, then splices it: appending a pack
  // means concatenation in every spelling. One relocation per element more than appending the
  // elements directly - the spelling of an append is a performance knob, never a result change.
  template <typename T, typename Self>
  static constexpr auto _append(Self &&self, auto &&...args) //
      noexcept(_nothrow_relocatable<Self> && _nothrow_initializable<::std::remove_cvref_t<T>, decltype(args)...>
               && ::std::remove_cvref_t<T>::_impl::template _nothrow_relocatable<::std::remove_cvref_t<T>>) -> //
      typename _pack_append<::std::remove_cvref_t<T>, Ts...>::impl
    requires _some_pack<T>
             && (not(sizeof...(args) == 1
                     && (... && ::std::is_same_v<::std::remove_cvref_t<decltype(args)>, ::std::remove_cvref_t<T>>)))
             && _relocatable<Self> && _initializable<::std::remove_cvref_t<T>, decltype(args)...>
             && ::std::remove_cvref_t<T>::_impl::template
  _relocatable<::std::remove_cvref_t<T>>
  {
    using pack_t = ::std::remove_cvref_t<T>;
    using type = _pack_append<pack_t, Ts...>::impl;
    return pack_t::_impl::_swap_invoke(pack_t{FWD(args)...}, [&self](auto &&...elems) {
      return type{static_cast<apply_const_lvalue_t<Self, Ts &&>>(FWD(self)._element<Is, Ts>::v)..., FWD(elems)...};
    });
  }
};

} // namespace fn::inline LIBFN_VERSION::detail

// ---------- BEGIN fn/detail/macro_end.hpp ----------
// Deliberately no include guard: see fn/detail/macro_begin.hpp.

#undef FWD // NOSONAR cpp:S959 paired with the define in macro_begin.hpp
#pragma pop_macro("FWD")

#undef DEDUCED_RETURN // NOSONAR cpp:S959 paired with the define in macro_begin.hpp
#pragma pop_macro("DEDUCED_RETURN")
// ---------- END fn/detail/macro_end.hpp ----------

// ---------- RESUME fn/detail/pack_impl.hpp ----------

#endif // INCLUDE_FN_DETAIL_PACK_IMPL
// ---------- END fn/detail/pack_impl.hpp ----------

// ---------- RESUME fn/pack.hpp ----------

// ---------- BEGIN fn/monadic.hpp ----------
#ifndef INCLUDE_FN_MONADIC
#define INCLUDE_FN_MONADIC

// ---------- BEGIN fn/detail/monadic.hpp ----------
#ifndef INCLUDE_FN_DETAIL_MONADIC
#define INCLUDE_FN_DETAIL_MONADIC

// ---------- RESUME fn/detail/monadic.hpp ----------

// ---------- RESUME fn/detail/monadic.hpp ----------

namespace fn::inline LIBFN_VERSION::detail {

template <typename T>
concept _some_monadic_type = _some_expected<T> || _some_optional<T> || _some_choice<T> || _some_just<T>;

template <typename Functor, typename V, typename... Args>
concept _monadic_invocable = _some_monadic_type<V> && ::std::invocable<typename Functor::apply, V, Args...>;

} // namespace fn::inline LIBFN_VERSION::detail

#endif // INCLUDE_FN_DETAIL_MONADIC
// ---------- END fn/detail/monadic.hpp ----------

// ---------- RESUME fn/monadic.hpp ----------

// ---------- RESUME fn/monadic.hpp ----------

namespace fn {
inline namespace LIBFN_VERSION {

/**
 * @brief Checks if a type is one of the library's carriers - what a pipeline flows through
 *
 * The four kinds a verb may be applied to: `expected`, `optional`, `choice` and `just`. A `pack` or
 * a `copack` is data a carrier holds, not a carrier, and answers false.
 *
 * @tparam T Type to check, possibly cv-ref qualified
 */
template <typename T>
concept some_monadic_type = detail::_some_monadic_type<T>;

/**
 * @brief Checks if a verb applies to a carrier - the constraint `operator|` itself carries
 *
 * The question asked of the verb's own `apply` object, so every arm it offers counts. This is what
 * a pipeline asks, and it differs from the `applicable_` concept of an individual verb, which asks
 * whether the callback is used to serve the operand: an operation over an uninhabited side consults
 * no callback at all, and so applies while no callback is applicable to it.
 *
 * @tparam Functor The verb, such as `fn::transform_t`
 * @tparam V The carrier, possibly cv-ref qualified
 * @tparam Args The verb's arguments as its functor holds them, typically the callback
 */
template <typename Functor, typename V, typename... Args>
concept monadic_invocable = detail::_monadic_invocable<Functor, V, Args...>;

} // namespace LIBFN_VERSION
} // namespace fn

#endif // INCLUDE_FN_MONADIC
// ---------- END fn/monadic.hpp ----------

// ---------- RESUME fn/pack.hpp ----------

// ---------- RESUME fn/pack.hpp ----------

// ---------- BEGIN fn/detail/macro_begin.hpp ----------
// Deliberately no include guard: this header and fn/detail/macro_end.hpp bracket the section of a
// header that uses the macros below; push_macro/pop_macro make the bracketing safe under nesting
// and preserve any prior user definition.

#pragma push_macro("FWD")
#undef FWD // NOSONAR cpp:S959 saved by push_macro above

// This FWD macro is a functional equivalent to std::forward<decltype(v)>(v),
// but it saves compilation time (and typing) when used frequently.
#define FWD(...) static_cast<decltype(__VA_ARGS__) &&>(__VA_ARGS__)

#pragma push_macro("DEDUCED_RETURN")
#undef DEDUCED_RETURN // NOSONAR cpp:S959 saved by push_macro above

// Spell a function's deduced return type explicitly on MSVC only. MSVC mis-resolves a deduced
// (`auto`/`decltype(auto)`) return whose type derives from a body-local alias, leaking it as an
// opaque dependent type; an explicit trailing return type is the fix. Every other compiler keeps
// `decltype(auto)` — the natural spelling — which by construction deduces `decltype(EXPR)` on
// `return EXPR;`, so the two are the same type and this is a no-op off MSVC.
//
// Confining `decltype(EXPR)` to MSVC also keeps it off clang <= 20, which in C++23 substitutes a
// non-viable constrained overload's trailing return type BEFORE its requires-clause rejects it
// (fixed clang 21), so the explicit form would fail to compile instead of removing the non-viable
// function from the overload set.
#ifndef _MSC_VER
#define DEDUCED_RETURN(...) decltype(auto)
#else
#define DEDUCED_RETURN(...) decltype(__VA_ARGS__)
#endif
// ---------- END fn/detail/macro_begin.hpp ----------

// ---------- RESUME fn/pack.hpp ----------

namespace fn {
inline namespace LIBFN_VERSION {

/**
 * @brief Checks if a type is a `pack` (with any elements)
 *
 * @tparam T Type to check, possibly cv-ref qualified
 */
template <typename T>
concept some_pack = detail::_some_pack<T>;

/**
 * @brief The product payload: all fields present, strictly flat
 *
 * A tuple-like structure supporting the tuple protocol - `get`, `tuple_size`, `tuple_element`,
 * structured bindings - and an `append` mechanism. Unlike `std::tuple`, a `pack` is not a valid
 * element of a `pack`: appending one splices its fields in rather than nesting it. Elements may
 * be lvalue references - `pack<T&>` is how the other carriers propagate references - and a const
 * pack propagates its const onto reference elements, handing out read-only views of the
 * referenced data. `pack<>` is the nullary product, the algebra's unit: a value that exists and
 * holds nothing, where the uninhabited `copack<>` is the zero. A structural type when its
 * elements are, so a constexpr pack can be used as a template parameter.
 *
 * @tparam Ts Element types; values or lvalue references, never rvalue references
 */
template <typename... Ts> struct pack : detail::pack_impl<::std::index_sequence_for<Ts...>, Ts...> {
  using _impl = detail::pack_impl<::std::index_sequence_for<Ts...>, Ts...>;
  static_assert((... && detail::_is_valid_pack_element<Ts>));

  /**
   * @brief The pack type that appending a `T` yields
   */
  template <typename T> using append_type = _impl::template append_type<T>;

  /**
   * @brief Compares two packs of the same type element by element, `<=>` lexicographically
   *
   * Every element decides: one that cannot be compared leaves the operator non-viable, which asking
   * answers rather than erroring on, and a reference element compares its referent, as
   * `fn::optional<T&>` and `std::tuple` do. `<=>` asks each element for its own, synthesizing no
   * ordering from `<`. `!=`, `<`, `>`, `<=` and `>=` follow from these two by rewriting.
   */
  [[nodiscard]] constexpr auto operator==(pack const &other) const //
      noexcept(noexcept(_impl::_equal(*this, other))) -> bool
    requires requires(pack const &a, pack const &b) { _impl::_equal(a, b); }
  {
    return _impl::_equal(*this, other);
  }

  /**
   * @brief Orders two packs lexicographically, element by element
   */
  [[nodiscard]] constexpr auto operator<=>(pack const &other) const //
      noexcept(noexcept(_impl::_compare(*this, other)))
    requires requires(pack const &a, pack const &b) { _impl::_compare(a, b); }
  {
    return _impl::_compare(*this, other);
  }

  /**
   * @brief Appends an element of type `T`, constructed in place from the arguments
   *
   * A `pack` for `T` splices its fields in - packs stay strictly flat - and a `copack` is not a
   * valid element at all. The result is a new pack; the existing elements are copied or moved in
   * `*this`'s value category, so a const pack with a reference element is not appendable: const
   * propagates through the reference, and the new pack's element cannot bind it.
   *
   * @tparam T Type of the new element
   * @param args Arguments to construct the new element from
   * @return A new pack, with the new element at the end
   */
  template <typename T>
  [[nodiscard]] constexpr auto append(::std::in_place_type_t<T>, auto &&...args) & //
      noexcept(noexcept(_impl::template _append<T>(::std::declval<pack &>(), FWD(args)...))) -> append_type<T>
    requires requires { append_type<T>{_impl::template _append<T>(*this, FWD(args)...)}; }
  {
    return {_impl::template _append<T>(*this, FWD(args)...)};
  }

  template <typename T>
  [[nodiscard]] constexpr auto append(::std::in_place_type_t<T>, auto &&...args) const & //
      noexcept(noexcept(_impl::template _append<T>(::std::declval<pack const &>(), FWD(args)...))) -> append_type<T>
    requires requires { append_type<T>{_impl::template _append<T>(*this, FWD(args)...)}; }
  {
    return {_impl::template _append<T>(*this, FWD(args)...)};
  }

  template <typename T>
  [[nodiscard]] constexpr auto append(::std::in_place_type_t<T>, auto &&...args) && //
      noexcept(noexcept(_impl::template _append<T>(::std::declval<pack &&>(), FWD(args)...))) -> append_type<T>
    requires requires { append_type<T>{_impl::template _append<T>(::std::move(*this), FWD(args)...)}; }
  {
    return {_impl::template _append<T>(::std::move(*this), FWD(args)...)};
  }

  template <typename T>
  [[nodiscard]] constexpr auto append(::std::in_place_type_t<T>, auto &&...args) const && //
      noexcept(noexcept(_impl::template _append<T>(::std::declval<pack const &&>(), FWD(args)...))) -> append_type<T>
    requires requires { append_type<T>{_impl::template _append<T>(::std::move(*this), FWD(args)...)}; }
  {
    return {_impl::template _append<T>(::std::move(*this), FWD(args)...)};
  }

  /**
   * @brief Appends a value; a `pack` argument splices its fields in
   *
   * Packs stay strictly flat: appending a pack appends its fields, never a nested pack. The
   * result is a new pack; the existing elements are copied or moved in `*this`'s value category.
   *
   * @param arg Value to append, or a pack whose fields to append
   * @return A new pack, with the addition at the end
   */
  template <typename Arg>
  [[nodiscard]] constexpr auto append(Arg &&arg) & //
      noexcept(noexcept(_impl::template _append<Arg>(::std::declval<pack &>(), FWD(arg)))) -> append_type<Arg>
    requires(not some_in_place_type<Arg>)
            && requires { append_type<Arg>{_impl::template _append<Arg>(*this, FWD(arg))}; }
  {
    return {_impl::template _append<Arg>(*this, FWD(arg))};
  }

  template <typename Arg>
  [[nodiscard]] constexpr auto append(Arg &&arg) const & //
      noexcept(noexcept(_impl::template _append<Arg>(::std::declval<pack const &>(), FWD(arg)))) -> append_type<Arg>
    requires(not some_in_place_type<Arg>)
            && requires { append_type<Arg>{_impl::template _append<Arg>(*this, FWD(arg))}; }
  {
    return {_impl::template _append<Arg>(*this, FWD(arg))};
  }

  template <typename Arg>
  [[nodiscard]] constexpr auto append(Arg &&arg) && //
      noexcept(noexcept(_impl::template _append<Arg>(::std::declval<pack &&>(), FWD(arg)))) -> append_type<Arg>
    requires(not some_in_place_type<Arg>)
            && requires { append_type<Arg>{_impl::template _append<Arg>(::std::move(*this), FWD(arg))}; }
  {
    return {_impl::template _append<Arg>(::std::move(*this), FWD(arg))};
  }

  template <typename Arg>
  [[nodiscard]] constexpr auto append(Arg &&arg) const && //
      noexcept(noexcept(_impl::template _append<Arg>(::std::declval<pack const &&>(), FWD(arg)))) -> append_type<Arg>
    requires(not some_in_place_type<Arg>)
            && requires { append_type<Arg>{_impl::template _append<Arg>(::std::move(*this), FWD(arg))}; }
  {
    return {_impl::template _append<Arg>(::std::move(*this), FWD(arg))};
  }

  /**
   * @brief Eliminates the pack: the elements spread into the callable as separate arguments
   *
   * The bridge between the product as stored and the product as an argument list: `pack<A, B>`
   * invokes `f(a, b)`, and `pack<>` invokes `f()`. The elements are handed over in `*this`'s
   * cv-qualification and value category, and trailing arguments follow them.
   *
   * @param fn Callable applied on the elements
   * @param args Additional arguments, appended after the elements
   * @return The callable's result
   */
  template <typename Fn>
  [[nodiscard]] constexpr auto apply(Fn &&fn, auto &&...args) & //
      noexcept(noexcept(_impl::_apply(::std::declval<pack &>(), FWD(fn), FWD(args)...)))
          -> DEDUCED_RETURN(_impl::_apply(*this, FWD(fn), FWD(args)...))
    requires requires { _impl::_apply(*this, FWD(fn), FWD(args)...); }
  {
    return _impl::_apply(*this, FWD(fn), FWD(args)...);
  }

  template <typename Fn>
  [[nodiscard]] constexpr auto apply(Fn &&fn, auto &&...args) const & //
      noexcept(noexcept(_impl::_apply(::std::declval<pack const &>(), FWD(fn), FWD(args)...)))
          -> DEDUCED_RETURN(_impl::_apply(*this, FWD(fn), FWD(args)...))
    requires requires { _impl::_apply(*this, FWD(fn), FWD(args)...); }
  {
    return _impl::_apply(*this, FWD(fn), FWD(args)...);
  }

  template <typename Fn>
  [[nodiscard]] constexpr auto apply(Fn &&fn, auto &&...args) && //
      noexcept(noexcept(_impl::_apply(::std::declval<pack &&>(), FWD(fn), FWD(args)...)))
          -> DEDUCED_RETURN(_impl::_apply(::std::move(*this), FWD(fn), FWD(args)...))
    requires requires { _impl::_apply(::std::move(*this), FWD(fn), FWD(args)...); }
  {
    return _impl::_apply(::std::move(*this), FWD(fn), FWD(args)...);
  }

  template <typename Fn>
  [[nodiscard]] constexpr auto apply(Fn &&fn, auto &&...args) const && //
      noexcept(noexcept(_impl::_apply(::std::declval<pack const &&>(), FWD(fn), FWD(args)...)))
          -> DEDUCED_RETURN(_impl::_apply(::std::move(*this), FWD(fn), FWD(args)...))
    requires requires { _impl::_apply(::std::move(*this), FWD(fn), FWD(args)...); }
  {
    return _impl::_apply(::std::move(*this), FWD(fn), FWD(args)...);
  }

  /**
   * @brief Eliminates the pack, converting the result to `Ret`
   *
   * @tparam Ret Type the result converts to
   * @param fn Callable applied on the elements
   * @param args Additional arguments, appended after the elements
   * @return The callable's result, converted to `Ret`
   */
  template <typename Ret, typename Fn>
  [[nodiscard]] constexpr auto apply_r(Fn &&fn, auto &&...args) & //
      noexcept(noexcept(_impl::template _apply_r<Ret>(::std::declval<pack &>(), FWD(fn), FWD(args)...))) -> Ret
    requires requires { _impl::template _apply_r<Ret>(*this, FWD(fn), FWD(args)...); }
  {
    return _impl::template _apply_r<Ret>(*this, FWD(fn), FWD(args)...);
  }

  template <typename Ret, typename Fn>
  [[nodiscard]] constexpr auto apply_r(Fn &&fn, auto &&...args) const & //
      noexcept(noexcept(_impl::template _apply_r<Ret>(::std::declval<pack const &>(), FWD(fn), FWD(args)...))) -> Ret
    requires requires { _impl::template _apply_r<Ret>(*this, FWD(fn), FWD(args)...); }
  {
    return _impl::template _apply_r<Ret>(*this, FWD(fn), FWD(args)...);
  }

  template <typename Ret, typename Fn>
  [[nodiscard]] constexpr auto apply_r(Fn &&fn, auto &&...args) && //
      noexcept(noexcept(_impl::template _apply_r<Ret>(::std::declval<pack &&>(), FWD(fn), FWD(args)...))) -> Ret
    requires requires { _impl::template _apply_r<Ret>(::std::move(*this), FWD(fn), FWD(args)...); }
  {
    return _impl::template _apply_r<Ret>(::std::move(*this), FWD(fn), FWD(args)...);
  }

  template <typename Ret, typename Fn>
  [[nodiscard]] constexpr auto apply_r(Fn &&fn, auto &&...args) const && //
      noexcept(noexcept(_impl::template _apply_r<Ret>(::std::declval<pack const &&>(), FWD(fn), FWD(args)...))) -> Ret
    requires requires { _impl::template _apply_r<Ret>(::std::move(*this), FWD(fn), FWD(args)...); }
  {
    return _impl::template _apply_r<Ret>(::std::move(*this), FWD(fn), FWD(args)...);
  }
};

template <typename... Args> pack(Args &&...args) -> pack<Args...>;

/**
 * @brief Tuple-protocol element access
 *
 * Returns the `I`-th element carrying the pack's cv-qualification and value
 * category, exactly as `apply` would pass it. Found by ADL, so it also serves
 * structured bindings and the generic `using ::std::get; get<I>(p)` idiom.
 *
 * @tparam I element index
 * @param p the pack
 * @return reference to the `I`-th element
 */
template <::std::size_t I, some_pack P>
[[nodiscard]] constexpr decltype(auto) get(P &&p) noexcept
  requires(I < ::std::remove_cvref_t<P>::size)
{
  return ::std::remove_cvref_t<P>::template _get<I>(FWD(p));
}

// Lifts
/**
 * @brief Lifts no values into the empty `pack` - the unit
 * @return `pack<>`
 */
[[nodiscard]] constexpr auto as_pack() noexcept -> pack<> { return {}; }

/**
 * @brief Lifts values into a `pack`, deduction preserving each argument's value category
 *
 * `as_pack(42)` yields `pack<int>`; an lvalue `x` yields `pack<int &>` - a reference rather than
 * a copy.
 *
 * @param src First value to lift
 * @param args Further values to lift
 * @return The new pack
 */
// The unused leading pack absorbs explicit template arguments and the constraint rejects them:
// this overload is deduction-only (value-category preserving), the overload below serves spelled types
template <typename... Explicit, typename T, typename... Args>
  requires(sizeof...(Explicit) == 0) && (not some_in_place_type<T>)
          && detail::_initializable<pack<T, Args...>, T, Args...>
[[nodiscard]] constexpr auto as_pack(T &&src, Args &&...args) //
    noexcept(detail::_nothrow_initializable<pack<T, Args...>, T, Args...>) -> pack<T, Args...>
{
  return pack<T, Args...>{FWD(src), FWD(args)...};
}

/**
 * @brief Lifts values into a `pack` of exactly the spelled element types
 *
 * `as_pack<bool, int>(x, d)` converts each argument at the call boundary; every element type must
 * be spelled - a partial spelling is not viable - and a reference element is what you ask for, as
 * in `as_pack<int const &>(x)`.
 *
 * @tparam T First element type, as spelled
 * @tparam Args Further element types, as spelled
 * @param src First value, converted to `T`
 * @param args Further values, converted to `Args...`
 * @return The new pack
 */
// No element type is deduced: the explicit form names ALL of pack<T, Args...> or is not viable
// (a partial spelling fails on arity); by-value parameters admit conversion at the call boundary
// (narrowing included) while still relocating rvalue arguments
template <typename T, typename... Args>
  requires(not some_in_place_type<T>) && detail::_initializable<pack<T, Args...>, T, Args...>
[[nodiscard]] constexpr auto as_pack(::std::type_identity_t<T> src, ::std::type_identity_t<Args>... args) //
    noexcept(detail::_nothrow_initializable<pack<T, Args...>, T, Args...>) -> pack<T, Args...>
{
  return pack<T, Args...>{FWD(src), FWD(args)...};
}

namespace detail {

// `value()` throws when the monad holds no value, but the join only reaches it once `has_value()`
// has answered - so the specification below asks what folding and lifting the value promise, with
// the accessor spelled as a type rather than as a call which would drag its own throw in.
template <typename Monad> using _value_of_t = decltype(::std::declval<Monad>().value());

// A product with an uninhabited factor is itself uninhabited, and copack<> has no value fold - the
// join over such a side must not name the fold, in the declared type, the noexcept specification
// or the body, and always resolves through `efn`.
template <typename Lh, typename Rh>
constexpr inline bool _uninhabited_join = empty_copack<typename ::std::remove_cvref_t<Lh>::value_type>
                                          || empty_copack<typename ::std::remove_cvref_t<Rh>::value_type>;

template <bool Uninhabited, typename Lh, typename Rh> struct _joined {
  using type = copack<>;
};
template <typename Lh, typename Rh> struct _joined<false, Lh, Rh> {
  using type = decltype(::fn::detail::_fold_detail::fold<typename ::std::remove_cvref_t<Lh>::value_type,
                                                         typename ::std::remove_cvref_t<Rh>::value_type>(
      ::std::declval<_value_of_t<Lh>>(), ::std::declval<_value_of_t<Rh>>()));
};
template <typename Lh, typename Rh> using _joined_t = typename _joined<_uninhabited_join<Lh, Rh>, Lh, Rh>::type;

// `_join` invokes `efn` as an lvalue - a named parameter - so the `Efn &` questions ask about the
// call the body performs; the reference collapses to it whatever category the callable arrived in.
template <bool Uninhabited, template <typename> typename Tpl, typename Lh, typename Rh, typename Efn>
struct _nothrow_join_arm {
  static constexpr bool value = ::std::is_nothrow_invocable_v<Efn &, Lh> && ::std::is_nothrow_invocable_v<Efn &, Rh>
                                && _nothrow_initializable<Tpl<copack<>>, ::std::invoke_result_t<Efn &, Lh>>
                                && _nothrow_initializable<Tpl<copack<>>, ::std::invoke_result_t<Efn &, Rh>>;
};
template <template <typename> typename Tpl, typename Lh, typename Rh, typename Efn>
struct _nothrow_join_arm<false, Tpl, Lh, Rh, Efn> {
  static constexpr bool value
      = noexcept(::fn::detail::_fold_detail::fold<typename ::std::remove_cvref_t<Lh>::value_type,
                                                  typename ::std::remove_cvref_t<Rh>::value_type>(
            ::std::declval<_value_of_t<Lh>>(), ::std::declval<_value_of_t<Rh>>()))
        && _nothrow_initializable<Tpl<_joined_t<Lh, Rh>>, ::std::in_place_t, _joined_t<Lh, Rh>>
        && ::std::is_nothrow_invocable_v<Efn &, Lh> && ::std::is_nothrow_invocable_v<Efn &, Rh>
        && _nothrow_initializable<Tpl<_joined_t<Lh, Rh>>, ::std::invoke_result_t<Efn &, Lh>>
        && _nothrow_initializable<Tpl<_joined_t<Lh, Rh>>, ::std::invoke_result_t<Efn &, Rh>>;
};
template <template <typename> typename Tpl, typename Lh, typename Rh, typename Efn>
constexpr inline bool _nothrow_join = _nothrow_join_arm<_uninhabited_join<Lh, Rh>, Tpl, Lh, Rh, Efn>::value;

// The disjunction's value channel: the sum of the two value types, with void spelled pack<> -
// both are the unit, and a copack cannot hold void.
template <typename V> using _sum_element_t = ::std::conditional_t<::std::is_void_v<V>, pack<>, V>;
template <typename Lh, typename Rh>
using _disjoined_t = copack_for<_sum_element_t<typename ::std::remove_cvref_t<Lh>::value_type>,
                                _sum_element_t<typename ::std::remove_cvref_t<Rh>::value_type>>;

template <typename T> constexpr inline bool _dead_value = empty_copack<typename ::std::remove_cvref_t<T>::value_type>;

// A dead side (uninhabited value) never relocates into the result - its inject arm is if
// constexpr'd out of the body, and weighs nothing here.
template <bool Dead, typename Type, typename Side> struct _nothrow_disj_inject {
  static constexpr bool value = true;
};
template <typename Type, typename Side> struct _nothrow_disj_inject<false, Type, Side> {
  static constexpr bool value
      = _nothrow_initializable<Type, ::std::in_place_t, decltype(::std::declval<Side>().value())>;
};

template <template <typename> typename Tpl>
[[nodiscard]] constexpr auto _join(auto &&lh, auto &&rh, auto &&efn) //
    noexcept(_nothrow_join<Tpl, decltype(lh), decltype(rh), decltype(efn)>)
        -> Tpl<_joined_t<decltype(lh), decltype(rh)>>
{
  using type = Tpl<_joined_t<decltype(lh), decltype(rh)>>;
  if constexpr (_uninhabited_join<decltype(lh), decltype(rh)>) {
    if (not lh.has_value())
      return type{efn(FWD(lh))};
    else
      return type{efn(FWD(rh))};
  } else {
    using Lh = ::std::remove_cvref_t<decltype(lh)>::value_type;
    using Rh = ::std::remove_cvref_t<decltype(rh)>::value_type;
    if (lh.has_value() && rh.has_value())
      return type{::std::in_place, ::fn::detail::_fold_detail::fold<Lh, Rh>(FWD(lh).value(), FWD(rh).value())};
    else if (not lh.has_value())
      return type{efn(FWD(lh))};
    else
      return type{efn(FWD(rh))};
  }
}

} // namespace detail

/**
 * @brief The data conjunction: concatenates into a `pack`, distributing over `copack` alternatives
 *
 * With plain data on both sides the fields concatenate into one flat `pack`. When either operand
 * is a `copack`, the product distributes over its alternatives - two copacks yield the full
 * cartesian product - producing a normalized `copack` of `pack`s. Dispatches on its left operand:
 * a bare `scalar & scalar` is not part of the algebra, so lift one side first, as in
 * `fn::as_pack(a) & b`.
 *
 * @param lh A `pack` or a `copack`
 * @param rh The data to conjoin: a scalar, a `pack` or a `copack`
 * @return A `pack`, or a `copack` of `pack`s where alternatives distribute
 */
[[nodiscard]] constexpr auto operator&(auto &&lh, auto &&rh) //
    noexcept(noexcept(::fn::detail::_fold_detail::fold<::std::remove_cvref_t<decltype(lh)>,
                                                       ::std::remove_cvref_t<decltype(rh)>>(FWD(lh), FWD(rh))))
  requires(some_copack<decltype(lh)> || some_pack<decltype(lh)>)
{
  using Lh = ::std::remove_cvref_t<decltype(lh)>;
  using Rh = ::std::remove_cvref_t<decltype(rh)>;
  return ::fn::detail::_fold_detail::fold<Lh, Rh>(FWD(lh), FWD(rh));
}

namespace detail {
// The data fold takes data. A monadic carrier among the arguments would become a pack element,
// silently answering a question the caller did not ask: `&` over carriers conjoins the carriers
// themselves, and their values cannot be reached without `value()`, which throws.
template <typename... Ts>
concept _no_carrier = (... && (not some_monadic_type<Ts>));

// ... and the carrier folds take carriers, all of them: a mixed argument list belongs to neither
// world and is refused, rather than resolved by the leading argument.
template <typename... Ts>
concept _all_carriers = (... && some_monadic_type<Ts>);
} // namespace detail

/**
 * @brief The n-ary fold of `operator &` above; a single argument is forwarded unchanged
 *
 * Two modes, never mixed in one call: with every argument a computation carrier the fold is the
 * monadic conjunction, exactly what cascading `operator &` produces, and with none of them a
 * carrier it is the data-level product, a leading scalar lifted into a `pack` first. A mixed
 * argument list is refused rather than resolved by the leading argument.
 */
constexpr inline struct conjoin_t {
  /**
   * @brief Forwards a single argument unchanged
   * @param arg The argument
   * @return The argument, forwarded
   */
  template <typename Arg> [[nodiscard]] constexpr auto operator()(Arg &&arg) const -> decltype(arg) { return FWD(arg); }

  /**
   * @brief Folds data into a product, or carriers into their conjunction
   *
   * With no carrier among the arguments the fold is the data-level product: a leading scalar is
   * lifted into a `pack` first, and a leading `pack` or `copack` dispatches `operator &` itself.
   * With every argument a carrier the same fold is their monadic conjunction.
   *
   * @param arg The leading argument
   * @param args Further arguments - all data, or all carriers, never the two mixed
   * @return The folded product, or the folded conjunction
   */
  template <typename Arg, typename... Args>
    requires(not some_copack<Arg>) && (not some_pack<Arg>) && detail::_no_carrier<Arg, Args...>
  [[nodiscard]] constexpr auto operator()(Arg &&arg, Args &&...args) const
  {
    return (::fn::pack{FWD(arg)} & ... & FWD(args));
  }

  template <typename Arg, typename... Args>
    requires(some_copack<Arg> || some_pack<Arg>) && detail::_no_carrier<Args...>
  [[nodiscard]] constexpr auto operator()(Arg &&arg, Args &&...args) const
  {
    return (FWD(arg) & ... & FWD(args));
  }

  template <typename Arg, typename... Args>
    requires(sizeof...(Args) > 0)
            && detail::_all_carriers<Arg, Args...> && requires(Arg &&a, Args &&...as) { (FWD(a) & ... & FWD(as)); }
  [[nodiscard]] constexpr auto operator()(Arg &&arg, Args &&...args) const //
      noexcept(noexcept((FWD(arg) & ... & FWD(args))))
  {
    return (FWD(arg) & ... & FWD(args));
  }
} conjoin; ///< The n-ary conjunction: `conjoin(a, b, c)`

/**
 * @brief The n-ary fold of the disjunction `operator |` over the monadic carriers; a single
 *        argument is forwarded unchanged
 *
 * Carriers only, in every arity - disjunction has no data-level form. An identity-cluster operand
 * makes the whole disjunction total, folding the result into `just` or `choice`.
 */
constexpr inline struct disjoin_t {
  // Carriers only, in every arity: `|` over anything else is the built-in operator, and folding
  // integers into 3 is not what this asks for

  /**
   * @brief Forwards a single carrier unchanged
   * @param arg The carrier
   * @return The carrier, forwarded
   */
  template <some_monadic_type Arg> [[nodiscard]] constexpr auto operator()(Arg &&arg) const -> decltype(arg)
  {
    return FWD(arg);
  }

  /**
   * @brief Folds the carriers into their disjunction
   *
   * The n-ary form of `operator |`: the result holds the first operand that worked, its values
   * summing into a `copack`, and the errors multiply into a `pack` reached only where every
   * operand failed. An identity-cluster operand makes the whole disjunction total.
   *
   * @param arg The leading carrier
   * @param args Further carriers to disjoin
   * @return The folded disjunction
   */
  template <typename Arg, typename... Args>
    requires(sizeof...(Args) > 0)
            && detail::_all_carriers<Arg, Args...> && requires(Arg &&a, Args &&...as) { (FWD(a) | ... | FWD(as)); }
  [[nodiscard]] constexpr auto operator()(Arg &&arg, Args &&...args) const //
      noexcept(noexcept((FWD(arg) | ... | FWD(args))))
  {
    return (FWD(arg) | ... | FWD(args));
  }
} disjoin; ///< The n-ary disjunction: `disjoin(a, b, c)`

} // namespace LIBFN_VERSION
} // namespace fn

namespace std {
template <typename... Ts>
struct tuple_size<::fn::pack<Ts...>> : ::std::integral_constant<::std::size_t, sizeof...(Ts)> {};

template <::std::size_t I, typename... Ts> struct tuple_element<I, ::fn::pack<Ts...>> {
  using type = ::fn::detail::select_nth_t<I, Ts...>;
};

// A const pack propagates const onto reference elements, so `tuple_element<I, pack const>`
// must match `get` and cannot defer to the generic `tuple_element<I, const T>`.
template <::std::size_t I, typename... Ts> struct tuple_element<I, ::fn::pack<Ts...> const> {
  using type = decltype(::fn::detail::_apply_const<::fn::pack<Ts...> const &, ::fn::detail::select_nth_t<I, Ts...>>);
};
} // namespace std

// ---------- BEGIN fn/detail/macro_end.hpp ----------
// Deliberately no include guard: see fn/detail/macro_begin.hpp.

#undef FWD // NOSONAR cpp:S959 paired with the define in macro_begin.hpp
#pragma pop_macro("FWD")

#undef DEDUCED_RETURN // NOSONAR cpp:S959 paired with the define in macro_begin.hpp
#pragma pop_macro("DEDUCED_RETURN")
// ---------- END fn/detail/macro_end.hpp ----------

// ---------- RESUME fn/pack.hpp ----------

#endif // INCLUDE_FN_PACK
// ---------- END fn/pack.hpp ----------

// ---------- RESUME fn/just.hpp ----------

// ---------- BEGIN fn/detail/macro_begin.hpp ----------
// Deliberately no include guard: this header and fn/detail/macro_end.hpp bracket the section of a
// header that uses the macros below; push_macro/pop_macro make the bracketing safe under nesting
// and preserve any prior user definition.

#pragma push_macro("FWD")
#undef FWD // NOSONAR cpp:S959 saved by push_macro above

// This FWD macro is a functional equivalent to std::forward<decltype(v)>(v),
// but it saves compilation time (and typing) when used frequently.
#define FWD(...) static_cast<decltype(__VA_ARGS__) &&>(__VA_ARGS__)

#pragma push_macro("DEDUCED_RETURN")
#undef DEDUCED_RETURN // NOSONAR cpp:S959 saved by push_macro above

// Spell a function's deduced return type explicitly on MSVC only. MSVC mis-resolves a deduced
// (`auto`/`decltype(auto)`) return whose type derives from a body-local alias, leaking it as an
// opaque dependent type; an explicit trailing return type is the fix. Every other compiler keeps
// `decltype(auto)` — the natural spelling — which by construction deduces `decltype(EXPR)` on
// `return EXPR;`, so the two are the same type and this is a no-op off MSVC.
//
// Confining `decltype(EXPR)` to MSVC also keeps it off clang <= 20, which in C++23 substitutes a
// non-viable constrained overload's trailing return type BEFORE its requires-clause rejects it
// (fixed clang 21), so the explicit form would fail to compile instead of removing the non-viable
// function from the overload set.
#ifndef _MSC_VER
#define DEDUCED_RETURN(...) decltype(auto)
#else
#define DEDUCED_RETURN(...) decltype(__VA_ARGS__)
#endif
// ---------- END fn/detail/macro_begin.hpp ----------

// ---------- RESUME fn/just.hpp ----------

namespace fn {
inline namespace LIBFN_VERSION {

/**
 * @brief Checks if a type is a `just` (with any payload)
 *
 * @tparam T Type to check, possibly cv-ref qualified
 */
template <typename T>
concept some_just = detail::_some_just<T>;

namespace detail {
// The payload just admits - the class mandates below assert the same set, and the transform verb
// asks this before naming just<result> anywhere, so an inadmissible result answers instead of
// firing a mandate inside the probe
template <typename T>
concept _just_payload = (not _some_copack<T>) && (not ::std::is_reference_v<T>) && (not ::std::is_array_v<T>)
                        && (not _some_in_place_type<T>) && ::std::is_same_v<T, ::std::remove_cv_t<T>>;

// What the callback's result may become: void and admissible payloads make a just; anything else
// keeps the member viable-but-loud below
template <typename Fn, typename... V>
concept _just_admissible_result
    = ::std::is_void_v<typename _apply_result<Fn, V...>::type> || _just_payload<typename _apply_result<Fn, V...>::type>;

// transform's declared result: `just` of an admissible payload; the RAW result type for an
// inadmissible one - a copack, a reference, an array - always formable, so the member stays
// viable and the body's static_assert names the requirement on use, the family's own pedagogy
// (naming just<result> here instead would fire the class mandate inside the verbs' probes and
// other candidates' noexcept specifications). An inapplicable callback still leaves no `type`.
template <typename Fn, typename... V> struct _just_transform_result {};
template <typename Fn, typename... V>
  requires(_is_applicable<Fn, V...>::value) && (not _just_admissible_result<Fn, V...>)
struct _just_transform_result<Fn, V...> {
  using type = typename _apply_result<Fn, V...>::type;
};
template <typename Fn, typename... V>
  requires(_is_applicable<Fn, V...>::value) && _just_admissible_result<Fn, V...>
struct _just_transform_result<Fn, V...> {
  using type = ::fn::just<typename _apply_result<Fn, V...>::type>;
};

// transform's result is direct-non-list-initialized from the thunk's invocation: no extra move,
// and immovable result types work (the pattern of pfn's _expected_from_invoke)
constexpr inline struct _just_from_invoke_t {
  explicit _just_from_invoke_t() = default;
} _just_from_invoke{};
} // namespace detail

// Declared ahead of the primary, whose transform names it - without this the primary would be
// instantiated for void first, and the specialization below would come too late.
template <> struct just<void>;

/**
 * @brief The identity carrier: holds exactly one value of `T`, always present
 *
 * The unit of the monadic family as a value: no error channel, no empty state, one payload. As
 * trivial as `T` permits in copying, moving, assignment and destruction; a structural type when
 * `T` is one. A copack payload is deliberately rejected - dispatch granularity belongs to the
 * engine, uniform per payload, so identity over a copack is spelled `choice`; a `choice` payload
 * stays legal, an atom here as everywhere.
 *
 * @tparam T Payload type
 */
template <typename T> struct just {
  static_assert(not detail::_some_copack<T>, "a just over a copack is spelled choice");
  static_assert(not ::std::is_reference_v<T>);
  static_assert(not ::std::is_array_v<T>);
  static_assert(not detail::_some_in_place_type<T>);
  static_assert(::std::is_same_v<T, ::std::remove_cv_t<T>>);

  /**
   * @brief The type of the value side
   */
  using value_type = T;

  /**
   * @brief The payload
   */
  T v_{};

  /**
   * @brief Default constructor
   */
  constexpr just() = default;
  /**
   * @brief Copy constructor
   */
  constexpr just(just const &) = default;
  /**
   * @brief Move constructor
   */
  constexpr just(just &&) = default;
  /**
   * @brief Copy assignment
   */
  constexpr just &operator=(just const &) = default;
  /**
   * @brief Move assignment
   */
  constexpr just &operator=(just &&) = default;
  /**
   * @brief Destructor
   */
  constexpr ~just() = default;

  /**
   * @brief Constructs the payload from a value
   *
   * Explicit exactly where the conversion to `T` is.
   *
   * @param v Value to initialize the payload from
   */
  template <typename U>
  constexpr just(U &&v) // NOSONAR cpp:S1709 implicit arm of the explicit pair
      noexcept(::std::is_nothrow_constructible_v<T, decltype(v)>)
    requires(not some_just<::std::remove_cvref_t<U>>) && (not detail::_some_in_place_type<::std::remove_cvref_t<U>>)
            && ::std::is_constructible_v<T, decltype(v)> && ::std::is_convertible_v<decltype(v), T>
      : v_(FWD(v))
  {
  }

  template <typename U>
  constexpr explicit just(U &&v) // NOSONAR cpp:S6458 the some_just constraint excludes same-kind sources
      noexcept(::std::is_nothrow_constructible_v<T, decltype(v)>)
    requires(not some_just<::std::remove_cvref_t<U>>) && (not detail::_some_in_place_type<::std::remove_cvref_t<U>>)
            && ::std::is_constructible_v<T, decltype(v)> && (not ::std::is_convertible_v<decltype(v), T>)
      : v_(FWD(v))
  {
  }

  /**
   * @brief Constructs the payload in place from the arguments
   *
   * @param args Arguments to construct the payload from
   */
  constexpr explicit just(::std::in_place_type_t<T>, auto &&...args) //
      noexcept(::std::is_nothrow_constructible_v<T, decltype(args)...>)
    requires ::std::is_constructible_v<T, decltype(args)...>
      : v_(FWD(args)...)
  {
  }

  /**
   * @brief Assignment from a value, through the payload's own assignment
   *
   * Assign-in-place is the whole meaning here - the payload is always a `T` - so this consults
   * `T`'s `operator=` alone, as copack's same-alternative arm does. Assigning the payload to
   * itself (`a = a.value()`) is a no-op by address identity.
   *
   * @param v Value to assign from
   * @return Reference to `*this`
   */
  template <typename U>
  constexpr just &operator=(U &&v) //
      noexcept(::std::is_nothrow_assignable_v<T &, decltype(v)>)
    requires(not some_just<::std::remove_cvref_t<U>>) && ::std::is_assignable_v<T &, decltype(v)>
  {
    if constexpr (::std::is_same_v<::std::remove_cvref_t<U>, T>) {
      if (::std::addressof(v) == ::std::addressof(v_))
        return *this;
    }
    v_ = FWD(v);
    return *this;
  }

  /**
   * @brief Destroys the payload and constructs a new one from the arguments, with the strong
   *        exception guarantee
   *
   * The mutation path for a payload that does not support assignment. Construction that can throw
   * goes through a temporary, relocated by nothrow move. Arguments that refer into the payload
   * held will dangle, as with std::optional's and std::variant's emplace.
   *
   * @param args Arguments to construct the new payload from
   * @return Reference to the new payload
   */
  constexpr T &emplace(auto &&...args) //
      noexcept(::std::is_nothrow_constructible_v<T, decltype(args)...>)
    requires ::std::is_constructible_v<T, decltype(args)...>
             && (::std::is_nothrow_constructible_v<T, decltype(args)...> || ::std::is_nothrow_move_constructible_v<T>)
  {
    if constexpr (::std::is_nothrow_constructible_v<T, decltype(args)...>) {
      ::std::destroy_at(::std::addressof(v_));
      ::std::construct_at(::std::addressof(v_), FWD(args)...);
    } else {
      T tmp(FWD(args)...);
      ::std::destroy_at(::std::addressof(v_));
      ::std::construct_at(::std::addressof(v_), ::std::move(tmp));
    }
    return v_;
  }

  /**
   * @brief Accesses the payload
   *
   * @return Reference to the payload, in `*this`'s value category
   */
  [[nodiscard]] constexpr T &value() & noexcept { return v_; }
  [[nodiscard]] constexpr T const &value() const & noexcept { return v_; }
  [[nodiscard]] constexpr T &&value() && noexcept { return ::std::move(v_); }
  [[nodiscard]] constexpr T const &&value() const && noexcept { return ::std::move(v_); }

  /**
   * @brief Maps the payload through the callable, wrapping the result
   *
   * @param fn Callable applied on the payload
   * @return `just` of the callable's result; `just<void>` for a void result
   */
  template <typename Fn>
  [[nodiscard]] constexpr auto transform(Fn &&fn) & //
      noexcept(detail::_is_nothrow_applicable<Fn, T &>::value) -> typename detail::_just_transform_result<Fn, T &>::type
    requires detail::_is_applicable<Fn, T &>::value
  {
    using type = detail::_apply_result<Fn, T &>::type;
    static_assert(detail::_just_admissible_result<Fn, T &>);
    if constexpr (::std::is_void_v<type>) {
      detail::_apply(FWD(fn), v_);
      return just<type>{};
    } else if constexpr (detail::_just_payload<type>)
      return just<type>{detail::_just_from_invoke,
                        [&fn, this]() -> decltype(auto) { return detail::_apply(FWD(fn), v_); }};
    else
      ::pfn::unreachable(); // LCOV_EXCL_LINE - rejected by the static_assert above
  }

  template <typename Fn>
  [[nodiscard]] constexpr auto transform(Fn &&fn) const & //
      noexcept(detail::_is_nothrow_applicable<Fn, T const &>::value) ->
      typename detail::_just_transform_result<Fn, T const &>::type
    requires detail::_is_applicable<Fn, T const &>::value
  {
    using type = detail::_apply_result<Fn, T const &>::type;
    static_assert(detail::_just_admissible_result<Fn, T const &>);
    if constexpr (::std::is_void_v<type>) {
      detail::_apply(FWD(fn), v_);
      return just<type>{};
    } else if constexpr (detail::_just_payload<type>)
      return just<type>{detail::_just_from_invoke,
                        [&fn, this]() -> decltype(auto) { return detail::_apply(FWD(fn), v_); }};
    else
      ::pfn::unreachable(); // LCOV_EXCL_LINE - rejected by the static_assert above
  }

  template <typename Fn>
  [[nodiscard]] constexpr auto transform(Fn &&fn) && //
      noexcept(detail::_is_nothrow_applicable<Fn, T &&>::value) ->
      typename detail::_just_transform_result<Fn, T &&>::type
    requires detail::_is_applicable<Fn, T &&>::value
  {
    using type = detail::_apply_result<Fn, T &&>::type;
    static_assert(detail::_just_admissible_result<Fn, T &&>);
    if constexpr (::std::is_void_v<type>) {
      detail::_apply(FWD(fn), ::std::move(v_));
      return just<type>{};
    } else if constexpr (detail::_just_payload<type>)
      return just<type>{detail::_just_from_invoke,
                        [&fn, this]() -> decltype(auto) { return detail::_apply(FWD(fn), ::std::move(v_)); }};
    else
      ::pfn::unreachable(); // LCOV_EXCL_LINE - rejected by the static_assert above
  }

  template <typename Fn>
  [[nodiscard]] constexpr auto transform(Fn &&fn) const && //
      noexcept(detail::_is_nothrow_applicable<Fn, T const &&>::value) ->
      typename detail::_just_transform_result<Fn, T const &&>::type
    requires detail::_is_applicable<Fn, T const &&>::value
  {
    using type = detail::_apply_result<Fn, T const &&>::type;
    static_assert(detail::_just_admissible_result<Fn, T const &&>);
    if constexpr (::std::is_void_v<type>) {
      detail::_apply(FWD(fn), ::std::move(v_));
      return just<type>{};
    } else if constexpr (detail::_just_payload<type>)
      return just<type>{detail::_just_from_invoke,
                        [&fn, this]() -> decltype(auto) { return detail::_apply(FWD(fn), ::std::move(v_)); }};
    else
      ::pfn::unreachable(); // LCOV_EXCL_LINE - rejected by the static_assert above
  }

  /**
   * @brief Binds the payload through the callable, which must return a `just`
   *
   * @param fn Callable applied on the payload
   * @return The callable's own `just`
   */
  template <typename Fn>
  [[nodiscard]] constexpr auto and_then(Fn &&fn) & //
      noexcept(detail::_is_nothrow_applicable<Fn, T &>::value)
          -> ::std::remove_cvref_t<typename detail::_apply_result<Fn, T &>::type>
    requires detail::_is_applicable<Fn, T &>::value
  {
    // the member is the carrier's own bind; the cross-carrier bind lives in the and_then functor
    static_assert(some_just<::std::remove_cvref_t<typename detail::_apply_result<Fn, T &>::type>>);
    return detail::_apply(FWD(fn), v_);
  }

  template <typename Fn>
  [[nodiscard]] constexpr auto and_then(Fn &&fn) const & //
      noexcept(detail::_is_nothrow_applicable<Fn, T const &>::value)
          -> ::std::remove_cvref_t<typename detail::_apply_result<Fn, T const &>::type>
    requires detail::_is_applicable<Fn, T const &>::value
  {
    static_assert(some_just<::std::remove_cvref_t<typename detail::_apply_result<Fn, T const &>::type>>);
    return detail::_apply(FWD(fn), v_);
  }

  template <typename Fn>
  [[nodiscard]] constexpr auto and_then(Fn &&fn) && //
      noexcept(detail::_is_nothrow_applicable<Fn, T &&>::value)
          -> ::std::remove_cvref_t<typename detail::_apply_result<Fn, T &&>::type>
    requires detail::_is_applicable<Fn, T &&>::value
  {
    static_assert(some_just<::std::remove_cvref_t<typename detail::_apply_result<Fn, T &&>::type>>);
    return detail::_apply(FWD(fn), ::std::move(v_));
  }

  template <typename Fn>
  [[nodiscard]] constexpr auto and_then(Fn &&fn) const && //
      noexcept(detail::_is_nothrow_applicable<Fn, T const &&>::value)
          -> ::std::remove_cvref_t<typename detail::_apply_result<Fn, T const &&>::type>
    requires detail::_is_applicable<Fn, T const &&>::value
  {
    static_assert(some_just<::std::remove_cvref_t<typename detail::_apply_result<Fn, T const &&>::type>>);
    return detail::_apply(FWD(fn), ::std::move(v_));
  }

  /**
   * @brief Eliminates the payload through the callable
   *
   * The payload is handed over exactly as `fn::apply` would hand it - a `pack` or tuple-like
   * payload by elements, anything else whole - and trailing arguments follow the content.
   *
   * @param fn Callable applied on the payload
   * @param args Additional arguments, appended after the payload's content
   * @return The callable's result
   */
  template <typename Fn, typename... Args>
  [[nodiscard]] constexpr auto apply(Fn &&fn, Args &&...args) & //
      noexcept(detail::_is_nothrow_applicable<Fn, T &, Args...>::value) -> decltype(auto)
    requires detail::_is_applicable<Fn, T &, Args...>::value
  {
    return detail::_apply(FWD(fn), v_, FWD(args)...);
  }

  template <typename Fn, typename... Args>
  [[nodiscard]] constexpr auto apply(Fn &&fn, Args &&...args) const & //
      noexcept(detail::_is_nothrow_applicable<Fn, T const &, Args...>::value) -> decltype(auto)
    requires detail::_is_applicable<Fn, T const &, Args...>::value
  {
    return detail::_apply(FWD(fn), v_, FWD(args)...);
  }

  template <typename Fn, typename... Args>
  [[nodiscard]] constexpr auto apply(Fn &&fn, Args &&...args) && //
      noexcept(detail::_is_nothrow_applicable<Fn, T &&, Args...>::value) -> decltype(auto)
    requires detail::_is_applicable<Fn, T &&, Args...>::value
  {
    return detail::_apply(FWD(fn), ::std::move(v_), FWD(args)...);
  }

  template <typename Fn, typename... Args>
  [[nodiscard]] constexpr auto apply(Fn &&fn, Args &&...args) const && //
      noexcept(detail::_is_nothrow_applicable<Fn, T const &&, Args...>::value) -> decltype(auto)
    requires detail::_is_applicable<Fn, T const &&, Args...>::value
  {
    return detail::_apply(FWD(fn), ::std::move(v_), FWD(args)...);
  }

  /**
   * @brief Eliminates the payload through the callable, converting the result to `Ret`
   *
   * @tparam Ret Type the result converts to
   * @param fn Callable applied on the payload
   * @param args Additional arguments, appended after the payload's content
   * @return The callable's result, converted to `Ret`
   */
  template <typename Ret, typename Fn, typename... Args>
  [[nodiscard]] constexpr auto apply_r(Fn &&fn, Args &&...args) & //
      noexcept(detail::_is_nothrow_applicable_r<Ret, Fn, T &, Args...>::value) -> Ret
    requires detail::_is_applicable_r<Ret, Fn, T &, Args...>::value
  {
    return detail::_apply_r<Ret>(FWD(fn), v_, FWD(args)...);
  }

  template <typename Ret, typename Fn, typename... Args>
  [[nodiscard]] constexpr auto apply_r(Fn &&fn, Args &&...args) const & //
      noexcept(detail::_is_nothrow_applicable_r<Ret, Fn, T const &, Args...>::value) -> Ret
    requires detail::_is_applicable_r<Ret, Fn, T const &, Args...>::value
  {
    return detail::_apply_r<Ret>(FWD(fn), v_, FWD(args)...);
  }

  template <typename Ret, typename Fn, typename... Args>
  [[nodiscard]] constexpr auto apply_r(Fn &&fn, Args &&...args) && //
      noexcept(detail::_is_nothrow_applicable_r<Ret, Fn, T &&, Args...>::value) -> Ret
    requires detail::_is_applicable_r<Ret, Fn, T &&, Args...>::value
  {
    return detail::_apply_r<Ret>(FWD(fn), ::std::move(v_), FWD(args)...);
  }

  template <typename Ret, typename Fn, typename... Args>
  [[nodiscard]] constexpr auto apply_r(Fn &&fn, Args &&...args) const && //
      noexcept(detail::_is_nothrow_applicable_r<Ret, Fn, T const &&, Args...>::value) -> Ret
    requires detail::_is_applicable_r<Ret, Fn, T const &&, Args...>::value
  {
    return detail::_apply_r<Ret>(FWD(fn), ::std::move(v_), FWD(args)...);
  }

  /**
   * @brief Eliminates the payload through the callable, keyed by the payload's type
   *
   * The arm receives `std::in_place_type<T>` followed by the payload as `apply_type` hands it
   * over on `copack` and `choice` - a tuple-like payload's elements form is the row's one
   * signature - and trailing arguments follow the content.
   *
   * @param fn Callable applied on the tag and the payload
   * @param args Additional arguments, appended after the payload's content
   * @return The callable's result
   */
  template <typename Fn, typename... Args>
  [[nodiscard]] constexpr auto apply_type(Fn &&fn, Args &&...args) & //
      noexcept(noexcept(detail::_apply_tagged<::std::in_place_type_t<T>>(FWD(fn), v_, FWD(args)...))) -> decltype(auto)
    requires requires { detail::_apply_tagged<::std::in_place_type_t<T>>(FWD(fn), v_, FWD(args)...); }
  {
    return detail::_apply_tagged<::std::in_place_type_t<T>>(FWD(fn), v_, FWD(args)...);
  }

  template <typename Fn, typename... Args>
  [[nodiscard]] constexpr auto apply_type(Fn &&fn, Args &&...args) const & //
      noexcept(noexcept(detail::_apply_tagged<::std::in_place_type_t<T>>(FWD(fn), v_, FWD(args)...))) -> decltype(auto)
    requires requires { detail::_apply_tagged<::std::in_place_type_t<T>>(FWD(fn), v_, FWD(args)...); }
  {
    return detail::_apply_tagged<::std::in_place_type_t<T>>(FWD(fn), v_, FWD(args)...);
  }

  template <typename Fn, typename... Args>
  [[nodiscard]] constexpr auto apply_type(Fn &&fn, Args &&...args) && //
      noexcept(noexcept(detail::_apply_tagged<::std::in_place_type_t<T>>(FWD(fn), ::std::move(v_), FWD(args)...)))
          -> decltype(auto)
    requires requires { detail::_apply_tagged<::std::in_place_type_t<T>>(FWD(fn), ::std::move(v_), FWD(args)...); }
  {
    return detail::_apply_tagged<::std::in_place_type_t<T>>(FWD(fn), ::std::move(v_), FWD(args)...);
  }

  template <typename Fn, typename... Args>
  [[nodiscard]] constexpr auto apply_type(Fn &&fn, Args &&...args) const && //
      noexcept(noexcept(detail::_apply_tagged<::std::in_place_type_t<T>>(FWD(fn), ::std::move(v_), FWD(args)...)))
          -> decltype(auto)
    requires requires { detail::_apply_tagged<::std::in_place_type_t<T>>(FWD(fn), ::std::move(v_), FWD(args)...); }
  {
    return detail::_apply_tagged<::std::in_place_type_t<T>>(FWD(fn), ::std::move(v_), FWD(args)...);
  }

  /**
   * @brief Eliminates the payload through the callable, keyed by the payload's type, converting
   *        the result to `Ret`
   *
   * @tparam Ret Type the result converts to
   * @param fn Callable applied on the tag and the payload
   * @param args Additional arguments, appended after the payload's content
   * @return The callable's result, converted to `Ret`
   */
  template <typename Ret, typename Fn, typename... Args>
  [[nodiscard]] constexpr auto apply_type_r(Fn &&fn, Args &&...args) & //
      noexcept(noexcept(detail::_apply_tagged_r<Ret, ::std::in_place_type_t<T>>(FWD(fn), v_, FWD(args)...))) -> Ret
    requires requires { detail::_apply_tagged_r<Ret, ::std::in_place_type_t<T>>(FWD(fn), v_, FWD(args)...); }
  {
    return detail::_apply_tagged_r<Ret, ::std::in_place_type_t<T>>(FWD(fn), v_, FWD(args)...);
  }

  template <typename Ret, typename Fn, typename... Args>
  [[nodiscard]] constexpr auto apply_type_r(Fn &&fn, Args &&...args) const & //
      noexcept(noexcept(detail::_apply_tagged_r<Ret, ::std::in_place_type_t<T>>(FWD(fn), v_, FWD(args)...))) -> Ret
    requires requires { detail::_apply_tagged_r<Ret, ::std::in_place_type_t<T>>(FWD(fn), v_, FWD(args)...); }
  {
    return detail::_apply_tagged_r<Ret, ::std::in_place_type_t<T>>(FWD(fn), v_, FWD(args)...);
  }

  template <typename Ret, typename Fn, typename... Args>
  [[nodiscard]] constexpr auto apply_type_r(Fn &&fn, Args &&...args) && //
      noexcept(noexcept(detail::_apply_tagged_r<Ret, ::std::in_place_type_t<T>>(FWD(fn), ::std::move(v_),
                                                                                FWD(args)...))) -> Ret
    requires requires {
      detail::_apply_tagged_r<Ret, ::std::in_place_type_t<T>>(FWD(fn), ::std::move(v_), FWD(args)...);
    }
  {
    return detail::_apply_tagged_r<Ret, ::std::in_place_type_t<T>>(FWD(fn), ::std::move(v_), FWD(args)...);
  }

  template <typename Ret, typename Fn, typename... Args>
  [[nodiscard]] constexpr auto apply_type_r(Fn &&fn, Args &&...args) const && //
      noexcept(noexcept(detail::_apply_tagged_r<Ret, ::std::in_place_type_t<T>>(FWD(fn), ::std::move(v_),
                                                                                FWD(args)...))) -> Ret
    requires requires {
      detail::_apply_tagged_r<Ret, ::std::in_place_type_t<T>>(FWD(fn), ::std::move(v_), FWD(args)...);
    }
  {
    return detail::_apply_tagged_r<Ret, ::std::in_place_type_t<T>>(FWD(fn), ::std::move(v_), FWD(args)...);
  }

private:
  template <typename> friend struct just;

  template <typename Fn> constexpr explicit just(detail::_just_from_invoke_t, Fn &&make) : v_(FWD(make)()) {}
};

/**
 * @brief The identity carrier with nothing to carry: the family's unit as a value
 *
 * `just{}` (deduced) names it - a success with no payload, as `expected<void, copack<>>` in its
 * one state. Modeled on `expected<void, E>`: `value()` observes nothing, the callables of
 * `transform` and `and_then` are invoked without a value, and the `apply` family's one arm
 * receives the trailing arguments alone (`apply_type` prepends `std::in_place_type<void>`).
 */
template <> struct just<void> {
  /**
   * @brief The type of the value side
   */
  using value_type = void;

  /**
   * @brief Default constructor
   */
  constexpr just() = default;
  /**
   * @brief Constructs the alternative named by the tag, in place from the arguments
   */
  constexpr explicit just(::std::in_place_type_t<void>) noexcept {}
  /**
   * @brief Constructs the value in place from the arguments
   */
  constexpr explicit just(::std::in_place_t) noexcept {}

  /**
   * @brief Equality; every `just` compares equal to every other
   */
  [[nodiscard]] constexpr bool operator==(just const &) const noexcept = default;

  /**
   * @brief Observes the payload; there is nothing to observe
   */
  constexpr void value() const noexcept {} // NOSONAR cpp:S1186 void payload

  /**
   * @brief Maps through the callable, invoked with no arguments
   *
   * @param fn Callable to invoke
   * @return `just` of the callable's result; `just<void>` for a void result
   */
  template <typename Fn>
  [[nodiscard]] constexpr auto transform(Fn &&fn) const //
      noexcept(detail::_is_nothrow_applicable<Fn>::value) -> typename detail::_just_transform_result<Fn>::type
    requires detail::_is_applicable<Fn>::value
  {
    using type = detail::_apply_result<Fn>::type;
    static_assert(detail::_just_admissible_result<Fn>);
    if constexpr (::std::is_void_v<type>) {
      detail::_apply(FWD(fn));
      return just<type>{};
    } else if constexpr (detail::_just_payload<type>)
      return just<type>{detail::_just_from_invoke, [&fn]() -> decltype(auto) { return detail::_apply(FWD(fn)); }};
    else
      ::pfn::unreachable(); // LCOV_EXCL_LINE - rejected by the static_assert above
  }

  /**
   * @brief Binds through the callable, invoked with no arguments; it must return a `just`
   *
   * @param fn Callable to invoke
   * @return The callable's own `just`
   */
  template <typename Fn>
  [[nodiscard]] constexpr auto and_then(Fn &&fn) const //
      noexcept(detail::_is_nothrow_applicable<Fn>::value)
          -> ::std::remove_cvref_t<typename detail::_apply_result<Fn>::type>
    requires detail::_is_applicable<Fn>::value
  {
    // the member is the carrier's own bind; the cross-carrier bind lives in the and_then functor
    static_assert(some_just<::std::remove_cvref_t<typename detail::_apply_result<Fn>::type>>);
    return detail::_apply(FWD(fn));
  }

  /**
   * @brief Eliminates through the callable, invoked with the trailing arguments alone
   *
   * @param fn Callable to invoke
   * @param args Arguments the callable is invoked with
   * @return The callable's result
   */
  template <typename Fn, typename... Args>
  [[nodiscard]] constexpr auto apply(Fn &&fn, Args &&...args) const //
      noexcept(detail::_is_nothrow_applicable<Fn, Args...>::value) -> decltype(auto)
    requires detail::_is_applicable<Fn, Args...>::value
  {
    return detail::_apply(FWD(fn), FWD(args)...);
  }

  /**
   * @brief Eliminates through the callable, converting the result to `Ret`
   *
   * @tparam Ret Type the result converts to
   * @param fn Callable to invoke
   * @param args Arguments the callable is invoked with
   * @return The callable's result, converted to `Ret`
   */
  template <typename Ret, typename Fn, typename... Args>
  [[nodiscard]] constexpr auto apply_r(Fn &&fn, Args &&...args) const //
      noexcept(detail::_is_nothrow_applicable_r<Ret, Fn, Args...>::value) -> Ret
    requires detail::_is_applicable_r<Ret, Fn, Args...>::value
  {
    return detail::_apply_r<Ret>(FWD(fn), FWD(args)...);
  }

  /**
   * @brief Eliminates through the callable, keyed by the payload's type
   *
   * @param fn Callable invoked with `std::in_place_type<void>` and the trailing arguments
   * @param args Arguments following the tag
   * @return The callable's result
   */
  template <typename Fn, typename... Args>
  [[nodiscard]] constexpr auto apply_type(Fn &&fn, Args &&...args) const //
      noexcept(detail::_is_nothrow_applicable<Fn, ::std::in_place_type_t<void>, Args &&...>::value) -> decltype(auto)
    requires detail::_is_applicable<Fn, ::std::in_place_type_t<void>, Args &&...>::value
  {
    return detail::_apply(FWD(fn), ::std::in_place_type_t<void>{}, FWD(args)...);
  }

  /**
   * @brief Eliminates through the callable, keyed by the payload's type, converting the result
   *        to `Ret`
   *
   * @tparam Ret Type the result converts to
   * @param fn Callable invoked with `std::in_place_type<void>` and the trailing arguments
   * @param args Arguments following the tag
   * @return The callable's result, converted to `Ret`
   */
  template <typename Ret, typename Fn, typename... Args>
  [[nodiscard]] constexpr auto apply_type_r(Fn &&fn, Args &&...args) const //
      noexcept(detail::_is_nothrow_applicable_r<Ret, Fn, ::std::in_place_type_t<void>, Args &&...>::value) -> Ret
    requires detail::_is_applicable_r<Ret, Fn, ::std::in_place_type_t<void>, Args &&...>::value
  {
    return detail::_apply_r<Ret>(FWD(fn), ::std::in_place_type_t<void>{}, FWD(args)...);
  }
};

/**
 * @brief Compares the payloads of two `just` values
 */
template <typename T, typename U>
[[nodiscard]] constexpr bool operator==(just<T> const &lh, just<U> const &rh) //
    noexcept(noexcept(lh.value() == rh.value()))
  requires requires {
    { lh.value() == rh.value() } -> ::std::convertible_to<bool>;
  }
{
  return lh.value() == rh.value();
}

/**
 * @brief Compares the payload with a value
 */
template <typename T, typename U>
[[nodiscard]] constexpr bool operator==(just<T> const &lh, U const &rh) //
    noexcept(noexcept(lh.value() == rh))
  requires(not some_just<U>) && requires {
    { lh.value() == rh } -> ::std::convertible_to<bool>;
  }
{
  return lh.value() == rh;
}

// CTAD for just, including the deduced spelling of the void carrier: just{}
namespace detail {
template <typename Lh, typename Rh>
using _just_fold_t = decltype(_fold_detail::fold<typename ::std::remove_cvref_t<Lh>::value_type,
                                                 typename ::std::remove_cvref_t<Rh>::value_type>(
    ::std::declval<Lh>().value(), ::std::declval<Rh>().value()));
template <typename Lh, typename Rh>
constexpr inline bool _nothrow_just_fold
    = noexcept(_fold_detail::fold<typename ::std::remove_cvref_t<Lh>::value_type,
                                  typename ::std::remove_cvref_t<Rh>::value_type>(::std::declval<Lh>().value(),
                                                                                  ::std::declval<Rh>().value()))
      && ::std::is_nothrow_constructible_v<just<_just_fold_t<Lh, Rh>>, _just_fold_t<Lh, Rh>>;
} // namespace detail

// The conjunction inside the cluster: just & just folds the payloads and stays just, and
// just<void> is the product's unit - it elides, whatever the other operand.
template <typename Lh, typename Rh>
  requires detail::_some_just<Lh> && detail::_some_just<Rh>
           && (not ::std::is_void_v<typename ::std::remove_cvref_t<Lh>::value_type>)
           && (not ::std::is_void_v<typename ::std::remove_cvref_t<Rh>::value_type>)
[[nodiscard]] constexpr auto operator&(Lh &&lh, Rh &&rh) //
    noexcept(detail::_nothrow_just_fold<Lh, Rh>)
{
  using VL = ::std::remove_cvref_t<Lh>::value_type;
  using VR = ::std::remove_cvref_t<Rh>::value_type;
  return just<detail::_just_fold_t<Lh, Rh>>{::fn::detail::_fold_detail::fold<VL, VR>(FWD(lh).value(), FWD(rh).value())};
}

template <typename Lh, typename Rh>
  requires detail::_some_just<Lh> && ::std::is_void_v<typename ::std::remove_cvref_t<Lh>::value_type>
           && detail::_some_just<Rh>
[[nodiscard]] constexpr auto operator&(Lh &&, Rh &&rh) //
    noexcept(::std::is_nothrow_constructible_v<::std::remove_cvref_t<Rh>, Rh>) -> ::std::remove_cvref_t<Rh>
{
  return ::std::remove_cvref_t<Rh>{FWD(rh)};
}

template <typename Lh, typename Rh>
  requires detail::_some_just<Lh> && (not ::std::is_void_v<typename ::std::remove_cvref_t<Lh>::value_type>)
           && detail::_some_just<Rh> && ::std::is_void_v<typename ::std::remove_cvref_t<Rh>::value_type>
[[nodiscard]] constexpr auto operator&(Lh &&lh, Rh &&) //
    noexcept(::std::is_nothrow_constructible_v<::std::remove_cvref_t<Lh>, Lh>) -> ::std::remove_cvref_t<Lh>
{
  return ::std::remove_cvref_t<Lh>{FWD(lh)};
}

template <typename T> just(T) -> just<T>;
template <typename T> explicit just(::std::in_place_type_t<T>, auto &&...) -> just<T>;
just() -> just<void>;
explicit just(::std::in_place_t) -> just<void>;

} // namespace LIBFN_VERSION
} // namespace fn

// ---------- BEGIN fn/detail/macro_end.hpp ----------
// Deliberately no include guard: see fn/detail/macro_begin.hpp.

#undef FWD // NOSONAR cpp:S959 paired with the define in macro_begin.hpp
#pragma pop_macro("FWD")

#undef DEDUCED_RETURN // NOSONAR cpp:S959 paired with the define in macro_begin.hpp
#pragma pop_macro("DEDUCED_RETURN")
// ---------- END fn/detail/macro_end.hpp ----------

// ---------- RESUME fn/just.hpp ----------

#endif // INCLUDE_FN_JUST
// ---------- END fn/just.hpp ----------

// ---------- RESUME fn/choice.hpp ----------

// ---------- RESUME fn/choice.hpp ----------

// ---------- RESUME fn/choice.hpp ----------

// ---------- BEGIN fn/detail/macro_begin.hpp ----------
// Deliberately no include guard: this header and fn/detail/macro_end.hpp bracket the section of a
// header that uses the macros below; push_macro/pop_macro make the bracketing safe under nesting
// and preserve any prior user definition.

#pragma push_macro("FWD")
#undef FWD // NOSONAR cpp:S959 saved by push_macro above

// This FWD macro is a functional equivalent to std::forward<decltype(v)>(v),
// but it saves compilation time (and typing) when used frequently.
#define FWD(...) static_cast<decltype(__VA_ARGS__) &&>(__VA_ARGS__)

#pragma push_macro("DEDUCED_RETURN")
#undef DEDUCED_RETURN // NOSONAR cpp:S959 saved by push_macro above

// Spell a function's deduced return type explicitly on MSVC only. MSVC mis-resolves a deduced
// (`auto`/`decltype(auto)`) return whose type derives from a body-local alias, leaking it as an
// opaque dependent type; an explicit trailing return type is the fix. Every other compiler keeps
// `decltype(auto)` — the natural spelling — which by construction deduces `decltype(EXPR)` on
// `return EXPR;`, so the two are the same type and this is a no-op off MSVC.
//
// Confining `decltype(EXPR)` to MSVC also keeps it off clang <= 20, which in C++23 substitutes a
// non-viable constrained overload's trailing return type BEFORE its requires-clause rejects it
// (fixed clang 21), so the explicit form would fail to compile instead of removing the non-viable
// function from the overload set.
#ifndef _MSC_VER
#define DEDUCED_RETURN(...) decltype(auto)
#else
#define DEDUCED_RETURN(...) decltype(__VA_ARGS__)
#endif
// ---------- END fn/detail/macro_begin.hpp ----------

// ---------- RESUME fn/choice.hpp ----------

namespace fn {
inline namespace LIBFN_VERSION {

/**
 * @brief Checks if a type is a `choice` (with any alternatives)
 *
 * @tparam T Type to check, possibly cv-ref qualified
 */
template <typename T>
concept some_choice = detail::_some_choice<T>;

template <> struct choice<>; // Intentionally incomplete

namespace detail {
template <typename T>
static constexpr bool _is_valid_choice_subtype //
    = (not ::std::is_same_v<void, T>)          //
    &&(not ::std::is_reference_v<T>)           //
    &&(not some_copack<T>)                     //
    &&(not some_in_place_type<T>)              //
    &&::std::is_same_v<T, ::std::remove_cv_t<T>>;
}

/**
 * @brief The identity carrier over a coproduct: always holds one of the alternatives
 *
 * A never-failing computation whose result is one of `Ts...` - the one canonical spelling of that
 * shape, as `just` over a copack is rejected. Where a bare `copack` is self-flattening data, a
 * `choice` is an atom: mapping keeps a returned choice whole, and only `and_then` joins the
 * branches' choices away into the normalized superset. The alternatives obey the same canonical
 * form as `copack`'s - flat, unique, sorted - so spell `choice_for`; `choice<>` is deliberately
 * incomplete, an always-present alternative needing at least one alternative to exist. A
 * structural type when its alternatives are.
 *
 * @tparam Ts The alternatives - flat, unique and sorted in the canonical order
 */
template <typename... Ts>
  requires(sizeof...(Ts) > 0)
struct choice<Ts...> : copack<Ts...> {
  static_assert((... && detail::_is_valid_choice_subtype<Ts>));
  static_assert(::std::same_as<typename detail::normalized<Ts...>::template apply<::fn::choice>, choice>);
  using _impl = copack<Ts...>;
  /**
   * @brief The copack of alternatives this choice carries
   */
  using value_type = _impl;

  /**
   * @brief The number of alternatives
   */
  static constexpr ::std::size_t size = sizeof...(Ts);
  /**
   * @brief The I-th alternative in the canonical order
   */
  template <::std::size_t I> using select_nth = detail::select_nth_t<I, Ts...>;
  /**
   * @brief Whether `T` is one of the alternatives
   */
  template <typename T> static constexpr bool has_type = _impl::template has_type<T>;

  template <typename Ret>
  [[nodiscard]] constexpr auto
  _invoke(auto &&fn) const & noexcept(detail::_is_nothrow_rtst_invocable<Ret, decltype(fn), choice const &>)
  {
    return detail::invoke_type_variadic_union<Ret, typename _impl::data_t>(this->data, this->index, FWD(fn));
  }

  template <typename Ret>
  [[nodiscard]] constexpr auto
  _invoke(auto &&fn) && noexcept(detail::_is_nothrow_rtst_invocable<Ret, decltype(fn), choice &&>)
  {
    return detail::invoke_type_variadic_union<Ret, typename _impl::data_t>( //
        ::std::move(*this).data, ::std::move(*this).index, FWD(fn));
  }

  /**
   * @brief Constructs the alternative matching the value's decayed type
   *
   * Explicit exactly where the conversion to that alternative is.
   *
   * @param v Value of one alternative
   */
  template <typename T>
  constexpr choice(T &&v) // NOSONAR cpp:S1709,S6458 implicit arm of the explicit pair; has_type excludes self
      noexcept(::std::is_nothrow_constructible_v<_impl, ::std::in_place_type_t<::std::remove_cvref_t<T>>, decltype(v)>)
    requires has_type<::std::remove_cvref_t<T>>
             && (::std::is_constructible_v<_impl, ::std::in_place_type_t<::std::remove_cvref_t<T>>, decltype(v)>)
             && (::std::is_convertible_v<decltype(v), ::std::remove_cvref_t<T>>)
      : _impl(::std::in_place_type<::std::remove_cvref_t<T>>, FWD(v))
  {
  }

  template <typename T>
  constexpr explicit choice(T &&v) // NOSONAR cpp:S6458 has_type excludes self
      noexcept(::std::is_nothrow_constructible_v<_impl, ::std::in_place_type_t<::std::remove_cvref_t<T>>, decltype(v)>)
    requires has_type<::std::remove_cvref_t<T>>
             && (::std::is_constructible_v<_impl, ::std::in_place_type_t<::std::remove_cvref_t<T>>, decltype(v)>)
             && (not ::std::is_convertible_v<decltype(v), ::std::remove_cvref_t<T>>)
      : _impl(::std::in_place_type<::std::remove_cvref_t<T>>, FWD(v))
  {
  }

  /**
   * @brief Constructs the alternative `T` in place from the arguments
   *
   * @tparam T The alternative to construct
   * @param d Tag naming the alternative
   * @param args Arguments to construct the alternative from
   */
  template <typename T>
  constexpr explicit choice(::std::in_place_type_t<T> d, auto &&...args) //
      noexcept(::std::is_nothrow_constructible_v<_impl, ::std::in_place_type_t<T>, decltype(args)...>)
    requires has_type<T> && ::std::is_constructible_v<_impl, ::std::in_place_type_t<T>, decltype(args)...>
      : _impl(d, FWD(args)...)
  {
  }

  /**
   * @brief Widening constructor from a copack over a subset of the alternatives
   *
   * A copack converts implicitly into any choice that can hold its alternatives: the lift from
   * data to the never-failing carrier over it.
   *
   * @param v The copack to lift
   */
  template <typename... Tx>
  constexpr choice(copack<Tx...> const &v) // NOSONAR cpp:S1709 implicit widening by design
      noexcept(::std::is_nothrow_constructible_v<_impl, ::std::in_place_type_t<copack<Tx...>>, copack<Tx...> const &>)
    requires detail::is_superset_of<choice, choice<Tx...>>
             && (::std::is_constructible_v<_impl, ::std::in_place_type_t<copack<Tx...>>, copack<Tx...> const &>)
      : _impl(::std::in_place_type<copack<Tx...>>, FWD(v))
  {
  }

  /**
   * @brief Widening constructor from a copack over a subset of the alternatives
   */
  template <typename... Tx>
  constexpr choice(copack<Tx...> &&v) // NOSONAR cpp:S1709 implicit widening by design
      noexcept(::std::is_nothrow_constructible_v<_impl, ::std::in_place_type_t<copack<Tx...>>, copack<Tx...>>)
    requires detail::is_superset_of<choice, choice<Tx...>>
             && (::std::is_constructible_v<_impl, ::std::in_place_type_t<copack<Tx...>>, copack<Tx...>>)
      : _impl(::std::in_place_type<copack<Tx...>>, FWD(v))
  {
  }

  /**
   * @brief Widening constructor from a copack whose type is spelled as a tag
   *
   * @param v The copack to lift
   */
  template <typename... Tx>
  constexpr choice(::std::in_place_type_t<copack<Tx...>>, some_copack auto &&v) //
      noexcept(::std::is_nothrow_constructible_v<_impl, ::std::in_place_type_t<copack<Tx...>>, decltype(v)>)
    requires ::std::is_same_v<::std::remove_cvref_t<decltype(v)>, copack<Tx...>>
             && detail::is_superset_of<choice, choice<Tx...>>
      : _impl(::std::in_place_type<copack<Tx...>>, FWD(v))
  {
  }

  /**
   * @brief Copy constructor
   */
  constexpr choice(choice const &other) = default;
  /**
   * @brief Move constructor
   */
  constexpr choice(choice &&other) = default;
  /**
   * @brief Destructor
   */
  constexpr ~choice() = default;

  // Declared because the move constructor above would otherwise delete the implicit copy assignment
  // and suppress the implicit move assignment. Defaulted, so both inherit the base copack's - its
  // constraints, its strong guarantee, and its computed noexcept (which an explicit one here would
  // contradict, and thereby delete).
  /**
   * @brief Copy assignment
   */
  constexpr choice &operator=(choice const &other) = default;
  /**
   * @brief Move assignment
   */
  constexpr choice &operator=(choice &&other) = default;

  // choice declares its copy and move assignment, and a declared operator= hides every base
  // overload - copack's widening assignment must be restated here to exist at all. Delegating keeps
  // the answer copack's, and admits a copack over the same alternatives, which would otherwise pay for
  // the temporary the widening constructor builds.
  /**
   * @brief Widening assignment from a copack over a subset of the alternatives
   */
  template <typename... Tx>
  constexpr choice &operator=(copack<Tx...> const &arg) //
      noexcept(::std::is_nothrow_assignable_v<copack<Ts...> &, copack<Tx...> const &>)
    requires ::std::is_assignable_v<copack<Ts...> &, copack<Tx...> const &>
  {
    static_cast<copack<Ts...> &>(*this) = arg;
    return *this;
  }
  /**
   * @brief Widening assignment from a copack over a subset of the alternatives
   */
  template <typename... Tx>
  constexpr choice &operator=(copack<Tx...> &&arg) //
      noexcept(::std::is_nothrow_assignable_v<copack<Ts...> &, copack<Tx...>>)
    requires ::std::is_assignable_v<copack<Ts...> &, copack<Tx...>>
  {
    static_cast<copack<Ts...> &>(*this) = ::std::move(arg);
    return *this;
  }

  // The delegating value assignment restates copack's for the same name-hiding reason. Copack- and
  // choice-typed sources are excluded to leave them to the assignments above: for a non-const
  // lvalue source a forwarding reference would otherwise outrank their `const &` bindings.
  /**
   * @brief Assignment from a value
   */
  template <typename U>
  constexpr choice &operator=(U &&v) //
      noexcept(::std::is_nothrow_assignable_v<copack<Ts...> &, decltype(v)>)
    requires(not some_copack<U>) && (not some_choice<U>) && ::std::is_assignable_v<copack<Ts...> &, decltype(v)>
  {
    static_cast<copack<Ts...> &>(*this) = FWD(v);
    return *this;
  }

  /**
   * @brief Accesses the alternatives as the underlying `copack`
   *
   * Always present - a choice cannot fail - so the access is total, never throwing.
   *
   * @return Reference to `*this` as its `copack` base, in `*this`'s value category
   */
  [[nodiscard]] constexpr value_type &value() & noexcept { return *this; }
  [[nodiscard]] constexpr value_type const &value() const & noexcept { return *this; }
  [[nodiscard]] constexpr value_type &&value() && noexcept { return ::std::move(*this); }
  [[nodiscard]] constexpr value_type const &&value() const && noexcept { return ::std::move(*this); }

  /**
   * @brief Eliminates the choice: the active alternative routes into the callable
   *
   * Exactly `copack`'s `apply`, over the alternatives: exhaustive dispatch by ordinary overload
   * resolution, one deduced result type, a tuple-like alternative unpacked one level into its
   * elements, trailing arguments after the content.
   *
   * @param fn Callable applied on the active alternative; `fn::overload` fuses arms into one
   * @param args Additional arguments, appended after the alternative's content
   * @return The callable's result
   */
  template <typename Fn, typename... Args>
  [[nodiscard]] constexpr auto apply(Fn &&fn, Args &&...args) & noexcept(
      detail::_is_nothrow_rts_applicable<typename detail::_copack_apply_result<
                                             detail::_apply_autodetect_tag, decltype(fn), choice &, Args &&...>::type,
                                         Fn &&, choice &, Args &&...>)
    requires typelist_applicable<Fn, choice &, Args &&...>
  {
    using type = detail::_copack_apply_result<detail::_apply_autodetect_tag, decltype(fn), choice &, Args &&...>::type;
    return detail::apply_variadic_union<type, typename _impl::data_t>(_impl::data, _impl::index, FWD(fn), FWD(args)...);
  }

  template <typename Fn, typename... Args>
  [[nodiscard]] constexpr auto apply(Fn &&fn, Args &&...args) const & noexcept(
      detail::_is_nothrow_rts_applicable<
          typename detail::_copack_apply_result<detail::_apply_autodetect_tag, decltype(fn), choice const &,
                                                Args &&...>::type,
          Fn &&, choice const &, Args &&...>)
    requires typelist_applicable<Fn, choice const &, Args &&...>
  {
    using type
        = detail::_copack_apply_result<detail::_apply_autodetect_tag, decltype(fn), choice const &, Args &&...>::type;
    return detail::apply_variadic_union<type, typename _impl::data_t>(_impl::data, _impl::index, FWD(fn), FWD(args)...);
  }

  template <typename Fn, typename... Args>
  [[nodiscard]] constexpr auto apply(Fn &&fn, Args &&...args) && noexcept(
      detail::_is_nothrow_rts_applicable<typename detail::_copack_apply_result<
                                             detail::_apply_autodetect_tag, decltype(fn), choice &&, Args &&...>::type,
                                         Fn &&, choice &&, Args &&...>)
    requires typelist_applicable<Fn, choice &&, Args &&...>
  {
    using type = detail::_copack_apply_result<detail::_apply_autodetect_tag, decltype(fn), choice &&, Args &&...>::type;
    return detail::apply_variadic_union<type, typename _impl::data_t>(::std::move(_impl::data), _impl::index, FWD(fn),
                                                                      FWD(args)...);
  }

  template <typename Fn, typename... Args>
  [[nodiscard]] constexpr auto apply(Fn &&fn, Args &&...args) const && noexcept(
      detail::_is_nothrow_rts_applicable<
          typename detail::_copack_apply_result<detail::_apply_autodetect_tag, decltype(fn), choice const &&,
                                                Args &&...>::type,
          Fn &&, choice const &&, Args &&...>)
    requires typelist_applicable<Fn, choice const &&, Args &&...>
  {
    using type
        = detail::_copack_apply_result<detail::_apply_autodetect_tag, decltype(fn), choice const &&, Args &&...>::type;
    return detail::apply_variadic_union<type, typename _impl::data_t>(::std::move(_impl::data), _impl::index, FWD(fn),
                                                                      FWD(args)...);
  }

  /**
   * @brief Eliminates the choice, converting each branch's result to `T`
   *
   * @tparam T Type the results convert to
   * @param fn Callable applied on the active alternative
   * @param args Additional arguments, appended after the alternative's content
   * @return The callable's result, converted to `T`
   */
  template <typename T, typename Fn, typename... Args>
  [[nodiscard]] constexpr auto apply_r(Fn &&fn, Args &&...args) & noexcept(
      detail::_is_nothrow_rts_applicable<
          typename detail::_copack_apply_result<T, decltype(fn), choice &, Args &&...>::type, Fn &&, choice &,
          Args &&...>)
    requires typelist_applicable<Fn, choice &, Args &&...>
  {
    using type = detail::_copack_apply_result<T, decltype(fn), choice &, Args &&...>::type;
    return detail::apply_variadic_union<type, typename _impl::data_t>(_impl::data, _impl::index, FWD(fn), FWD(args)...);
  }

  template <typename T, typename Fn, typename... Args>
  [[nodiscard]] constexpr auto apply_r(Fn &&fn, Args &&...args) const & noexcept(
      detail::_is_nothrow_rts_applicable<
          typename detail::_copack_apply_result<T, decltype(fn), choice const &, Args &&...>::type, Fn &&,
          choice const &, Args &&...>)
    requires typelist_applicable<Fn, choice const &, Args &&...>
  {
    using type = detail::_copack_apply_result<T, decltype(fn), choice const &, Args &&...>::type;
    return detail::apply_variadic_union<type, typename _impl::data_t>(_impl::data, _impl::index, FWD(fn), FWD(args)...);
  }

  template <typename T, typename Fn, typename... Args>
  [[nodiscard]] constexpr auto apply_r(Fn &&fn, Args &&...args) && noexcept(
      detail::_is_nothrow_rts_applicable<
          typename detail::_copack_apply_result<T, decltype(fn), choice &&, Args &&...>::type, Fn &&, choice &&,
          Args &&...>)
    requires typelist_applicable<Fn, choice &&, Args &&...>
  {
    using type = detail::_copack_apply_result<T, decltype(fn), choice &&, Args &&...>::type;
    return detail::apply_variadic_union<type, typename _impl::data_t>(::std::move(_impl::data), _impl::index, FWD(fn),
                                                                      FWD(args)...);
  }

  template <typename T, typename Fn, typename... Args>
  [[nodiscard]] constexpr auto apply_r(Fn &&fn, Args &&...args) const && noexcept(
      detail::_is_nothrow_rts_applicable<
          typename detail::_copack_apply_result<T, decltype(fn), choice const &&, Args &&...>::type, Fn &&,
          choice const &&, Args &&...>)
    requires typelist_applicable<Fn, choice const &&, Args &&...>
  {
    using type = detail::_copack_apply_result<T, decltype(fn), choice const &&, Args &&...>::type;
    return detail::apply_variadic_union<type, typename _impl::data_t>(::std::move(_impl::data), _impl::index, FWD(fn),
                                                                      FWD(args)...);
  }

  /**
   * @brief Eliminates the choice, keyed by the alternative's type
   *
   * The active arm receives `std::in_place_type<T>` for the alternative held, followed by its
   * content as `copack`'s `apply_type` hands it over.
   *
   * @param fn Callable applied on the tag and the alternative's content
   * @param args Additional arguments, appended after the content
   * @return The callable's result
   */
  template <typename Fn, typename... Args>
  [[nodiscard]] constexpr auto apply_type(Fn &&fn, Args &&...args) & noexcept(
      detail::_is_nothrow_rtst_invocable<
          typename detail::_copack_invoke_type_result<detail::_apply_autodetect_tag, detail::_apply_type_fn<Fn>,
                                                      choice &, Args &&...>::type,
          detail::_apply_type_fn<Fn>, choice &, Args &&...>) ->
      typename detail::_copack_invoke_type_result<detail::_apply_autodetect_tag, detail::_apply_type_fn<Fn>, choice &,
                                                  Args &&...>::type
    requires detail::_typelist_type_invocable<detail::_apply_type_fn<Fn>, choice &, Args &&...>
  {
    using type = detail::_copack_invoke_type_result<detail::_apply_autodetect_tag, detail::_apply_type_fn<Fn>, choice &,
                                                    Args &&...>::type;
    return detail::invoke_type_variadic_union<type, typename _impl::data_t>(
        _impl::data, _impl::index, detail::_apply_type_fn<Fn>{FWD(fn)}, FWD(args)...);
  }

  template <typename Fn, typename... Args>
  [[nodiscard]] constexpr auto apply_type(Fn &&fn, Args &&...args) const & noexcept(
      detail::_is_nothrow_rtst_invocable<
          typename detail::_copack_invoke_type_result<detail::_apply_autodetect_tag, detail::_apply_type_fn<Fn>,
                                                      choice const &, Args &&...>::type,
          detail::_apply_type_fn<Fn>, choice const &, Args &&...>) ->
      typename detail::_copack_invoke_type_result<detail::_apply_autodetect_tag, detail::_apply_type_fn<Fn>,
                                                  choice const &, Args &&...>::type
    requires detail::_typelist_type_invocable<detail::_apply_type_fn<Fn>, choice const &, Args &&...>
  {
    using type = detail::_copack_invoke_type_result<detail::_apply_autodetect_tag, detail::_apply_type_fn<Fn>,
                                                    choice const &, Args &&...>::type;
    return detail::invoke_type_variadic_union<type, typename _impl::data_t>(
        _impl::data, _impl::index, detail::_apply_type_fn<Fn>{FWD(fn)}, FWD(args)...);
  }

  template <typename Fn, typename... Args>
  [[nodiscard]] constexpr auto apply_type(Fn &&fn, Args &&...args) && noexcept(
      detail::_is_nothrow_rtst_invocable<
          typename detail::_copack_invoke_type_result<detail::_apply_autodetect_tag, detail::_apply_type_fn<Fn>,
                                                      choice &&, Args &&...>::type,
          detail::_apply_type_fn<Fn>, choice &&, Args &&...>) ->
      typename detail::_copack_invoke_type_result<detail::_apply_autodetect_tag, detail::_apply_type_fn<Fn>, choice &&,
                                                  Args &&...>::type
    requires detail::_typelist_type_invocable<detail::_apply_type_fn<Fn>, choice &&, Args &&...>
  {
    using type = detail::_copack_invoke_type_result<detail::_apply_autodetect_tag, detail::_apply_type_fn<Fn>,
                                                    choice &&, Args &&...>::type;
    return detail::invoke_type_variadic_union<type, typename _impl::data_t>(
        ::std::move(_impl::data), _impl::index, detail::_apply_type_fn<Fn>{FWD(fn)}, FWD(args)...);
  }

  template <typename Fn, typename... Args>
  [[nodiscard]] constexpr auto apply_type(Fn &&fn, Args &&...args) const && noexcept(
      detail::_is_nothrow_rtst_invocable<
          typename detail::_copack_invoke_type_result<detail::_apply_autodetect_tag, detail::_apply_type_fn<Fn>,
                                                      choice const &&, Args &&...>::type,
          detail::_apply_type_fn<Fn>, choice const &&, Args &&...>) ->
      typename detail::_copack_invoke_type_result<detail::_apply_autodetect_tag, detail::_apply_type_fn<Fn>,
                                                  choice const &&, Args &&...>::type
    requires detail::_typelist_type_invocable<detail::_apply_type_fn<Fn>, choice const &&, Args &&...>
  {
    using type = detail::_copack_invoke_type_result<detail::_apply_autodetect_tag, detail::_apply_type_fn<Fn>,
                                                    choice const &&, Args &&...>::type;
    return detail::invoke_type_variadic_union<type, typename _impl::data_t>(
        ::std::move(_impl::data), _impl::index, detail::_apply_type_fn<Fn>{FWD(fn)}, FWD(args)...);
  }

  /**
   * @brief Eliminates the choice, keyed by the alternative's type, converting the result to `Ret`
   *
   * @tparam Ret Type the results convert to
   * @param fn Callable applied on the tag and the alternative's content
   * @param args Additional arguments, appended after the content
   * @return The callable's result, converted to `Ret`
   */
  template <typename Ret, typename Fn, typename... Args>
  [[nodiscard]] constexpr auto apply_type_r(Fn &&fn, Args &&...args) & noexcept(
      detail::_is_nothrow_rtst_invocable<Ret, detail::_apply_type_fn<Fn>, choice &, Args &&...>) -> Ret
    requires detail::_typelist_type_invocable_r<Ret, detail::_apply_type_fn<Fn>, choice &, Args &&...>
  {
    using type = detail::_copack_invoke_type_result<Ret, detail::_apply_type_fn<Fn>, choice &, Args &&...>::type;
    return detail::invoke_type_variadic_union<type, typename _impl::data_t>(
        _impl::data, _impl::index, detail::_apply_type_fn<Fn>{FWD(fn)}, FWD(args)...);
  }

  template <typename Ret, typename Fn, typename... Args>
  [[nodiscard]] constexpr auto apply_type_r(Fn &&fn, Args &&...args) const & noexcept(
      detail::_is_nothrow_rtst_invocable<Ret, detail::_apply_type_fn<Fn>, choice const &, Args &&...>) -> Ret
    requires detail::_typelist_type_invocable_r<Ret, detail::_apply_type_fn<Fn>, choice const &, Args &&...>
  {
    using type = detail::_copack_invoke_type_result<Ret, detail::_apply_type_fn<Fn>, choice const &, Args &&...>::type;
    return detail::invoke_type_variadic_union<type, typename _impl::data_t>(
        _impl::data, _impl::index, detail::_apply_type_fn<Fn>{FWD(fn)}, FWD(args)...);
  }

  template <typename Ret, typename Fn, typename... Args>
  [[nodiscard]] constexpr auto apply_type_r(Fn &&fn, Args &&...args) && noexcept(
      detail::_is_nothrow_rtst_invocable<Ret, detail::_apply_type_fn<Fn>, choice &&, Args &&...>) -> Ret
    requires detail::_typelist_type_invocable_r<Ret, detail::_apply_type_fn<Fn>, choice &&, Args &&...>
  {
    using type = detail::_copack_invoke_type_result<Ret, detail::_apply_type_fn<Fn>, choice &&, Args &&...>::type;
    return detail::invoke_type_variadic_union<type, typename _impl::data_t>(
        ::std::move(_impl::data), _impl::index, detail::_apply_type_fn<Fn>{FWD(fn)}, FWD(args)...);
  }

  template <typename Ret, typename Fn, typename... Args>
  [[nodiscard]] constexpr auto apply_type_r(Fn &&fn, Args &&...args) const && noexcept(
      detail::_is_nothrow_rtst_invocable<Ret, detail::_apply_type_fn<Fn>, choice const &&, Args &&...>) -> Ret
    requires detail::_typelist_type_invocable_r<Ret, detail::_apply_type_fn<Fn>, choice const &&, Args &&...>
  {
    using type = detail::_copack_invoke_type_result<Ret, detail::_apply_type_fn<Fn>, choice const &&, Args &&...>::type;
    return detail::invoke_type_variadic_union<type, typename _impl::data_t>(
        ::std::move(_impl::data), _impl::index, detail::_apply_type_fn<Fn>{FWD(fn)}, FWD(args)...);
  }

  // NOTE Monadic operations, only `and_then` and `transform` are supported
  /**
   * @brief Maps the alternatives, the branch results forming a new normalized choice
   *
   * As `copack`'s `transform`, staying a carrier: the branch results flatten, deduplicate and
   * sort. A returned `choice` stays whole - an atom, nested as one alternative - where a returned
   * bare `copack` dissolves into the set.
   *
   * @param fn Callable applied on the active alternative; `fn::overload` fuses arms into one
   * @return A choice of the normalized branch-result set, holding the active branch's result
   */
  template <typename Fn>
  [[nodiscard]] constexpr auto transform(Fn &&fn) & noexcept(
      detail::_is_nothrow_rts_applicable<
          typename detail::_copack_apply_result<detail::_collapsing_copack_tag, decltype(fn), choice &>::type, Fn &&,
          choice &>) -> typename detail::_copack_apply_result<detail::_collapsing_copack_tag, Fn &&, choice &>::type
    requires typelist_applicable<Fn, choice &>
  {
    using type = detail::_copack_apply_result<detail::_collapsing_copack_tag, decltype(fn), choice &>::type;
    return detail::apply_variadic_union<type, typename _impl::data_t>(_impl::data, _impl::index, FWD(fn));
  }

  template <typename Fn>
  [[nodiscard]] constexpr auto transform(Fn &&fn) const & noexcept(
      detail::_is_nothrow_rts_applicable<
          typename detail::_copack_apply_result<detail::_collapsing_copack_tag, decltype(fn), choice const &>::type,
          Fn &&, choice const &>) ->
      typename detail::_copack_apply_result<detail::_collapsing_copack_tag, Fn &&, choice const &>::type
    requires typelist_applicable<Fn, choice const &>
  {
    using type = detail::_copack_apply_result<detail::_collapsing_copack_tag, decltype(fn), choice const &>::type;
    return detail::apply_variadic_union<type, typename _impl::data_t>(_impl::data, _impl::index, FWD(fn));
  }

  template <typename Fn>
  [[nodiscard]] constexpr auto transform(Fn &&fn) && noexcept(
      detail::_is_nothrow_rts_applicable<
          typename detail::_copack_apply_result<detail::_collapsing_copack_tag, decltype(fn), choice &&>::type, Fn &&,
          choice &&>) -> typename detail::_copack_apply_result<detail::_collapsing_copack_tag, Fn &&, choice &&>::type
    requires typelist_applicable<Fn, choice &&>
  {
    using type = detail::_copack_apply_result<detail::_collapsing_copack_tag, decltype(fn), choice &&>::type;
    return detail::apply_variadic_union<type, typename _impl::data_t>(::std::move(_impl::data), _impl::index, FWD(fn));
  }

  template <typename Fn>
  [[nodiscard]] constexpr auto transform(Fn &&fn) const && noexcept(
      detail::_is_nothrow_rts_applicable<
          typename detail::_copack_apply_result<detail::_collapsing_copack_tag, decltype(fn), choice const &&>::type,
          Fn &&, choice const &&>) ->
      typename detail::_copack_apply_result<detail::_collapsing_copack_tag, Fn &&, choice const &&>::type
    requires typelist_applicable<Fn, choice const &&>
  {
    using type = detail::_copack_apply_result<detail::_collapsing_copack_tag, decltype(fn), choice const &&>::type;
    return detail::apply_variadic_union<type, typename _impl::data_t>(::std::move(_impl::data), _impl::index, FWD(fn));
  }

  /**
   * @brief Binds the alternatives: every branch returns a `choice`, joined into the superset
   *
   * The member is the carrier's own bind: each branch's returned choice splices its alternatives
   * into one normalized superset choice. A branch returning a bare value belongs to `transform`
   * instead, and is rejected with a named diagnostic; branches converging on another carrier kind
   * belong to the pipeline `fn::and_then`, the licensed cross-carrier place.
   *
   * @param fn Callable applied on the active alternative; `fn::overload` fuses arms into one
   * @return The normalized superset choice of the branches' alternatives
   */
  template <typename Fn>
  constexpr auto and_then(Fn &&fn) & noexcept(
      detail::_is_nothrow_rts_applicable<
          typename detail::_copack_apply_result<detail::_joining_superset_tag<choice>, decltype(fn), choice &>::type,
          Fn &&, choice &>) ->
      typename detail::_copack_apply_result<detail::_joining_superset_tag<choice>, Fn &&, choice &>::type
    requires typelist_applicable<Fn, choice &>
  {
    using type = detail::_copack_apply_result<detail::_joining_superset_tag<choice>, decltype(fn), choice &>::type;
    static_assert(some_choice<type>);
    return detail::apply_variadic_union<type, typename _impl::data_t>(_impl::data, _impl::index, FWD(fn));
  }

  template <typename Fn>
  constexpr auto and_then(Fn &&fn) const & noexcept(
      detail::_is_nothrow_rts_applicable<typename detail::_copack_apply_result<detail::_joining_superset_tag<choice>,
                                                                               decltype(fn), choice const &>::type,
                                         Fn &&, choice const &>) ->
      typename detail::_copack_apply_result<detail::_joining_superset_tag<choice>, Fn &&, choice const &>::type
    requires typelist_applicable<Fn, choice const &>
  {
    using type
        = detail::_copack_apply_result<detail::_joining_superset_tag<choice>, decltype(fn), choice const &>::type;
    static_assert(some_choice<type>);
    return detail::apply_variadic_union<type, typename _impl::data_t>(_impl::data, _impl::index, FWD(fn));
  }

  template <typename Fn>
  constexpr auto and_then(Fn &&fn) && noexcept(
      detail::_is_nothrow_rts_applicable<
          typename detail::_copack_apply_result<detail::_joining_superset_tag<choice>, decltype(fn), choice &&>::type,
          Fn &&, choice &&>) ->
      typename detail::_copack_apply_result<detail::_joining_superset_tag<choice>, Fn &&, choice &&>::type
    requires typelist_applicable<Fn, choice &&>
  {
    using type = detail::_copack_apply_result<detail::_joining_superset_tag<choice>, decltype(fn), choice &&>::type;
    static_assert(some_choice<type>);
    return detail::apply_variadic_union<type, typename _impl::data_t>(::std::move(_impl::data), _impl::index, FWD(fn));
  }

  template <typename Fn>
  constexpr auto and_then(Fn &&fn) const && noexcept(
      detail::_is_nothrow_rts_applicable<typename detail::_copack_apply_result<detail::_joining_superset_tag<choice>,
                                                                               decltype(fn), choice const &&>::type,
                                         Fn &&, choice const &&>) ->
      typename detail::_copack_apply_result<detail::_joining_superset_tag<choice>, Fn &&, choice const &&>::type
    requires typelist_applicable<Fn, choice const &&>
  {
    using type
        = detail::_copack_apply_result<detail::_joining_superset_tag<choice>, decltype(fn), choice const &&>::type;
    static_assert(some_choice<type>);
    return detail::apply_variadic_union<type, typename _impl::data_t>(::std::move(_impl::data), _impl::index, FWD(fn));
  }
};

// CTAD for single-element choice
namespace detail {
template <typename T> struct _rechoice;
template <typename... Ts> struct _rechoice<copack<Ts...>> {
  using type = choice<Ts...>;
};
template <typename Lh, typename Rh>
using _choice_fold_t = decltype(_fold_detail::fold<typename ::std::remove_cvref_t<Lh>::value_type,
                                                   typename ::std::remove_cvref_t<Rh>::value_type>(
    ::std::declval<Lh>().value(), ::std::declval<Rh>().value()));
template <typename Lh, typename Rh>
constexpr inline bool _nothrow_choice_fold
    = noexcept(_fold_detail::fold<typename ::std::remove_cvref_t<Lh>::value_type,
                                  typename ::std::remove_cvref_t<Rh>::value_type>(::std::declval<Lh>().value(),
                                                                                  ::std::declval<Rh>().value()))
      && ::std::is_nothrow_constructible_v<typename _rechoice<_choice_fold_t<Lh, Rh>>::type, _choice_fold_t<Lh, Rh>>;
} // namespace detail

// The conjunction inside the cluster, choice on either side: the copack distributes through the
// value product, so the fold answers a copack of packs and the result stays a choice. just<void>
// is the product's unit and elides.
// The description below covers every `&` over carriers, not just this arm: the reference renders
// one description per parameter-type signature, and all of them share `(Lh &&, Rh &&)`, of which
// this is the first doxygen reports. The arms in expected.hpp and optional.hpp carry theirs as
// ordinary comments for the same reason.
/**
 * @brief The conjunction of carriers: values multiply into a `pack`, errors sum into a `copack`
 *
 * `a & b` succeeds only where both operands do, the values folding into one `pack` - a `void`
 * side elides, and a copack value distributes into a copack of packs. What the failure side
 * carries depends on the carrier: an `expected` holds the leftmost failing operand's error, an
 * identical pair of error types staying as it is and any other pair summing into its normalized
 * `copack_for`, grading not required of the operands; an `optional` is simply empty, its unit
 * error needing no summing; a `choice` or `just` cannot fail, so the fold is total. Both operands
 * are fully constructed before the operator runs: an error-selection rule, not short-circuiting.
 * An identity-cluster operand contributes its value and no error term.
 *
 * @param lh Left operand
 * @param rh Right operand
 * @return The carrier of the folded value product, over the summed failure side
 */
template <typename Lh, typename Rh>
  requires(detail::_some_choice<Lh> || detail::_some_choice<Rh>) && (detail::_some_just<Lh> || detail::_some_choice<Lh>)
          && (detail::_some_just<Rh> || detail::_some_choice<Rh>)
          && (not ::std::is_void_v<typename ::std::remove_cvref_t<Lh>::value_type>)
          && (not ::std::is_void_v<typename ::std::remove_cvref_t<Rh>::value_type>)
[[nodiscard]] constexpr auto operator&(Lh &&lh, Rh &&rh) //
    noexcept(detail::_nothrow_choice_fold<Lh, Rh>)
{
  using VL = ::std::remove_cvref_t<Lh>::value_type;
  using VR = ::std::remove_cvref_t<Rh>::value_type;
  using type = typename detail::_rechoice<detail::_choice_fold_t<Lh, Rh>>::type;
  return type{::fn::detail::_fold_detail::fold<VL, VR>(FWD(lh).value(), FWD(rh).value())};
}

template <typename Lh, typename Rh>
  requires detail::_some_just<Lh> && ::std::is_void_v<typename ::std::remove_cvref_t<Lh>::value_type>
           && detail::_some_choice<Rh>
[[nodiscard]] constexpr auto operator&(Lh &&, Rh &&rh) //
    noexcept(::std::is_nothrow_constructible_v<::std::remove_cvref_t<Rh>, Rh>) -> ::std::remove_cvref_t<Rh>
{
  return ::std::remove_cvref_t<Rh>{FWD(rh)};
}

template <typename Lh, typename Rh>
  requires detail::_some_choice<Lh> && detail::_some_just<Rh>
           && ::std::is_void_v<typename ::std::remove_cvref_t<Rh>::value_type>
[[nodiscard]] constexpr auto operator&(Lh &&lh, Rh &&) //
    noexcept(::std::is_nothrow_constructible_v<::std::remove_cvref_t<Lh>, Lh>) -> ::std::remove_cvref_t<Lh>
{
  return ::std::remove_cvref_t<Lh>{FWD(lh)};
}

namespace detail {
template <typename T>
concept _identity_expected = _some_expected<T> && empty_copack<typename ::std::remove_cvref_t<T>::error_type>;
template <typename T>
concept _cluster_operand = _some_just<T> || _some_choice<T> || _identity_expected<T>;
template <typename T>
concept _some_carrier = _some_expected<T> || _some_optional<T> || _some_just<T> || _some_choice<T>;

// How a side enters the total disjunction's result: not at all (dead), as the unit pack<>, or as
// its value - the three-way split keeps the dead and void conjuncts from naming an accessor.
template <typename T>
constexpr inline int _inject_kind
    = ::std::is_void_v<typename ::std::remove_cvref_t<T>::value_type> ? 1 : (::fn::detail::_dead_value<T> ? 0 : 2);
template <int Kind, typename Type, typename Side> struct _nothrow_total_inject {
  static constexpr bool value = true;
};
template <typename Type, typename Side> struct _nothrow_total_inject<1, Type, Side> {
  static constexpr bool value = ::std::is_nothrow_constructible_v<Type, pack<>>;
};
template <typename Type, typename Side> struct _nothrow_total_inject<2, Type, Side> {
  static constexpr bool value = ::std::is_nothrow_constructible_v<Type, decltype(::std::declval<Side>().value())>;
};

// Type stays a template parameter so both branches are dependent: a non-dependent discarded
// statement would still be checked against choices without a pack<> alternative.
template <typename Type, typename Side>
[[nodiscard]] constexpr auto _total_inject(Side &&side) //
    noexcept(_nothrow_total_inject<_inject_kind<Side>, Type, Side>::value) -> Type
{
  if constexpr (::std::is_void_v<typename ::std::remove_cvref_t<Side>::value_type>)
    return Type{pack<>{}};
  else
    return Type{FWD(side).value()};
}
} // namespace detail

// The total disjunction: a cluster operand - just, choice, or the identity expected - puts an
// uninhabited factor into the error product, so the result never fails and collapses into the
// cluster: just when the value sum stays one bare type, choice when the union is genuine. The
// leftmost engaged operand wins; a cluster operand is always engaged.
// As with `&` above, this arm carries the description for every `|` over carriers.
/**
 * @brief The disjunction of carriers: values sum into a `copack`, errors multiply into a `pack`
 *
 * `a | b` yields the leftmost operand that worked, its value injected into the sum of the value
 * types - a same-type pair stays bare, and a `void` side enters a genuine sum as `pack<>`. What
 * remains when none worked depends on the carrier: an `expected` holds the product of every
 * error, all evidence kept positionally; an `optional` is simply empty, its unit errors vanishing
 * in that product; a `choice` or `just` always works, so the disjunction is total. Both operands
 * are fully constructed before the operator runs: a value-selection rule, not a lazy fallback. An
 * identity-cluster operand makes the whole disjunction total, collapsing the result into `just`
 * or `choice`.
 *
 * @param lh Left operand
 * @param rh Right operand
 * @return The carrier of the summed value side, over the error product
 */
template <typename Lh, typename Rh>
  requires(detail::_cluster_operand<Lh> || detail::_cluster_operand<Rh>) //
          && detail::_some_carrier<Lh> && detail::_some_carrier<Rh>
          && (not ::std::is_void_v<typename ::std::remove_cvref_t<Lh>::value_type>)
          && ::std::is_same_v<typename ::std::remove_cvref_t<Lh>::value_type,
                              typename ::std::remove_cvref_t<Rh>::value_type>
          && (not some_copack<typename ::std::remove_cvref_t<Lh>::value_type>)
[[nodiscard]] constexpr auto operator|(Lh &&lh, Rh &&rh) //
    noexcept(detail::_nothrow_total_inject<detail::_inject_kind<Lh>,
                                           ::fn::just<typename ::std::remove_cvref_t<Lh>::value_type>, Lh>::value
             && detail::_nothrow_total_inject<detail::_inject_kind<Rh>,
                                              ::fn::just<typename ::std::remove_cvref_t<Lh>::value_type>, Rh>::value)
{
  using type = ::fn::just<typename ::std::remove_cvref_t<Lh>::value_type>;
  if constexpr (detail::_cluster_operand<Lh>) {
    return type{FWD(lh).value()};
  } else {
    if (lh.has_value())
      return type{FWD(lh).value()};
    return type{FWD(rh).value()};
  }
}

template <typename Lh, typename Rh>
  requires(detail::_cluster_operand<Lh> || detail::_cluster_operand<Rh>) //
          && detail::_some_carrier<Lh> && detail::_some_carrier<Rh>
          && ::std::is_same_v<typename ::std::remove_cvref_t<Lh>::value_type,
                              typename ::std::remove_cvref_t<Rh>::value_type>
          && some_copack<typename ::std::remove_cvref_t<Lh>::value_type>
[[nodiscard]] constexpr auto operator|(Lh &&lh, Rh &&rh) //
    noexcept(detail::_nothrow_total_inject<
                 detail::_inject_kind<Lh>,
                 typename detail::_rechoice<typename ::std::remove_cvref_t<Lh>::value_type>::type, Lh>::value
             && detail::_nothrow_total_inject<
                 detail::_inject_kind<Rh>,
                 typename detail::_rechoice<typename ::std::remove_cvref_t<Lh>::value_type>::type, Rh>::value)
{
  using type = typename detail::_rechoice<typename ::std::remove_cvref_t<Lh>::value_type>::type;
  if constexpr (detail::_cluster_operand<Lh>) {
    return type{FWD(lh).value()};
  } else {
    if (lh.has_value())
      return type{FWD(lh).value()};
    return type{FWD(rh).value()};
  }
}

template <typename Lh, typename Rh>
  requires(detail::_cluster_operand<Lh> || detail::_cluster_operand<Rh>) //
          && detail::_some_carrier<Lh> && detail::_some_carrier<Rh>
          && ::std::is_void_v<typename ::std::remove_cvref_t<Lh>::value_type>
          && ::std::is_void_v<typename ::std::remove_cvref_t<Rh>::value_type>
[[nodiscard]] constexpr auto operator|(Lh &&, Rh &&) noexcept -> ::fn::just<void>
{
  return ::fn::just<void>{};
}

template <typename Lh, typename Rh>
  requires(detail::_cluster_operand<Lh> || detail::_cluster_operand<Rh>) //
          && detail::_some_carrier<Lh> && detail::_some_carrier<Rh>
          && (not ::std::is_same_v<typename ::std::remove_cvref_t<Lh>::value_type,
                                   typename ::std::remove_cvref_t<Rh>::value_type>)
[[nodiscard]] constexpr auto operator|(Lh &&lh, Rh &&rh) //
    noexcept(
        detail::_nothrow_total_inject<detail::_inject_kind<Lh>,
                                      typename detail::_rechoice<::fn::detail::_disjoined_t<Lh, Rh>>::type, Lh>::value
        && detail::_nothrow_total_inject<
            detail::_inject_kind<Rh>, typename detail::_rechoice<::fn::detail::_disjoined_t<Lh, Rh>>::type, Rh>::value)
{
  using type = typename detail::_rechoice<::fn::detail::_disjoined_t<Lh, Rh>>::type;
  if constexpr (detail::_cluster_operand<Lh>) {
    return detail::_total_inject<type>(FWD(lh));
  } else {
    if constexpr (not ::fn::detail::_dead_value<Lh>) {
      if (lh.has_value())
        return detail::_total_inject<type>(FWD(lh));
    }
    return detail::_total_inject<type>(FWD(rh));
  }
}

template <typename T> explicit choice(::std::in_place_type_t<T>, auto &&...) -> choice<T>;
template <typename T> explicit choice(T) -> choice<T>;

/**
 * @brief Compares two choices: equal when they hold the same alternative type with equal values
 *
 * The alternative sets need not match; an alternative the other side cannot hold compares unequal
 * without being compared.
 *
 * @param lh Left choice
 * @param rh Right choice
 * @return Whether the active alternatives are the same type with equal values
 */
template <typename... Ts, typename... Tx>
[[nodiscard]] constexpr bool operator==(choice<Ts...> const &lh, choice<Tx...> const &rh) noexcept
  requires(... && (::std::equality_comparable<Ts> || not detail::type_one_of<Ts, Tx...>))
          and (not ::std::is_same_v<choice<Ts...>, choice<Tx...>>)
{
  return lh.template _invoke<bool>([&rh]<typename T>(::std::in_place_type_t<T> d, auto const &lh) noexcept {
    if constexpr (::std::remove_cvref_t<decltype(rh)>::template has_type<T>) {
      return rh.has_value(d) && lh == *rh.get_ptr(d);
    } else {
      return false;
    }
  });
}

/**
 * @brief The negation of `==` for two choices
 *
 * @param lh Left choice
 * @param rh Right choice
 * @return Whether the choices differ in alternative type or value
 */
template <typename... Ts, typename... Tx>
[[nodiscard]] constexpr bool operator!=(choice<Ts...> const &lh, choice<Tx...> const &rh) noexcept
  requires(... && (::std::equality_comparable<Ts> || not detail::type_one_of<Ts, Tx...>))
{
  return not(lh == rh);
}

/**
 * @brief Builds the canonical `choice` for any list of types
 *
 * The construction alias over `choice`, exactly as `copack_for` stands to `copack`: flattens,
 * deduplicates and sorts into the canonical order. Spell `choice_for` rather than `choice`, so
 * that no spelling in your project is tied to one compiler's alternative order.
 *
 * @tparam Ts Types to combine - alternatives and copacks of them, in any order, duplicates allowed
 */
template <typename... Ts>
using choice_for
    = detail::_collapsing_copack::normalized<::fn::choice, detail::_collapsing_copack::flattened<Ts...>>::type;

} // namespace LIBFN_VERSION
} // namespace fn

// ---------- BEGIN fn/detail/macro_end.hpp ----------
// Deliberately no include guard: see fn/detail/macro_begin.hpp.

#undef FWD // NOSONAR cpp:S959 paired with the define in macro_begin.hpp
#pragma pop_macro("FWD")

#undef DEDUCED_RETURN // NOSONAR cpp:S959 paired with the define in macro_begin.hpp
#pragma pop_macro("DEDUCED_RETURN")
// ---------- END fn/detail/macro_end.hpp ----------

// ---------- RESUME fn/choice.hpp ----------

#endif // INCLUDE_FN_CHOICE
// ---------- END fn/choice.hpp ----------

// ---------- RESUME fn/and_then.hpp ----------

// ---------- BEGIN fn/concepts.hpp ----------
#ifndef INCLUDE_FN_CONCEPTS
#define INCLUDE_FN_CONCEPTS

// ---------- RESUME fn/concepts.hpp ----------

// ---------- RESUME fn/concepts.hpp ----------

// ---------- BEGIN fn/expected.hpp ----------
#ifndef INCLUDE_FN_EXPECTED
#define INCLUDE_FN_EXPECTED

// ---------- RESUME fn/expected.hpp ----------

// ---------- BEGIN pfn/expected.hpp ----------
#ifndef INCLUDE_PFN_EXPECTED
#define INCLUDE_PFN_EXPECTED

// ---------- RESUME pfn/expected.hpp ----------

#ifdef FWD
#pragma push_macro("FWD")
#define INCLUDE_PFN_EXPECTED__POP_FWD
#undef FWD // NOSONAR cpp:S959 saved by push_macro above
#endif

// Also defined in fn/detail/macro_begin.hpp but pfn headers are standalone
#define FWD(...) static_cast<decltype(__VA_ARGS__) &&>(__VA_ARGS__)

#ifdef ASSERT
#pragma push_macro("ASSERT")
#define INCLUDE_PFN_EXPECTED__POP_ASSERT
#undef ASSERT
#endif

// LIBFN_ASSERT is a customization point for the user
#ifdef LIBFN_ASSERT
#define ASSERT(...) LIBFN_ASSERT(__VA_ARGS__)
#else
#define ASSERT(...) assert((__VA_ARGS__) == true)
#endif

// This header is a polyfill for std::expected, tracking the C++ working draft
// and changes planned for the future standard revisions. As a deliberate extension,
// member functions whose `noexcept` specification is left unspecified by the
// standard are given a `noexcept` clause derived from the properties of the
// underlying types T, E and (where applicable) invocable arguments. Each such
// clause is marked inline with a "// extension" trailing comment.

namespace pfn {
inline namespace LIBFN_VERSION_BASE {

// [expected.bad], class template bad_expected_access
template <class E> class bad_expected_access;

/**
 * @brief The base exception type of every failed `expected` value access ([expected.bad.void])
 *
 * Thrown only as a `bad_expected_access<E>`; this specialization for `void` is the common base,
 * for handlers that do not care about the error type.
 *
 * Its members are the standard's, and specified where
 * the reference page for this entity points.
 */
template <> class bad_expected_access<void> : public ::std::exception {
protected:
  bad_expected_access() noexcept = default;
  bad_expected_access(bad_expected_access const &) noexcept = default;
  bad_expected_access(bad_expected_access &&) noexcept = default;
  bad_expected_access &operator=(bad_expected_access const &) noexcept = default;
  bad_expected_access &operator=(bad_expected_access &&) noexcept = default;
  ~bad_expected_access() noexcept = default;

public:
  [[nodiscard]] char const *what() const noexcept override
  {
    static char const msg_[] = "bad access to expected without expected value";
    return msg_;
  }
};

/**
 * @brief The exception thrown when `expected::value()` is called on an object holding an error
 *        ([expected.bad])
 *
 * Carries a copy of that error, exposed through `error()`.
 *
 *
 * Its members are the standard's, and specified where
 * the reference page for this entity points.
 * @tparam E Type of the carried error value
 */
template <class E> class bad_expected_access : public bad_expected_access<void> {
public:
  explicit bad_expected_access(E e) : e_(::std::move(e)) {}
  [[nodiscard]] char const *what() const noexcept override { return bad_expected_access<void>::what(); };
  E &error() & noexcept { return e_; }
  E const &error() const & noexcept { return e_; }
  E &&error() && noexcept { return ::std::move(e_); }
  E const &&error() const && noexcept { return ::std::move(e_); }

private:
  E e_; // NOSONAR cpp:S6226 MSVC ignores the attribute
};

/**
 * @brief Disambiguation tag selecting an `expected`'s error side in construction and emplacement
 *        ([expected.syn]); passed as the `pfn::unexpect` value
 *
 * Its members are the standard's, and specified where
 * the reference page for this entity points.
 */
constexpr inline struct unexpect_t {
  explicit unexpect_t() = default;
} unexpect{};

// [expected.unexpected]
template <class E> class unexpected;

namespace detail {
template <typename> constexpr bool _is_some_unexpected = false;
template <typename T> constexpr bool _is_some_unexpected<::pfn::unexpected<T>> = true;

template <typename T>
constexpr bool _is_valid_unexpected = //
    ::std::is_object_v<T>             // i.e. not a reference or void or function
    && not ::std::is_array_v<T>       //
    && not _is_some_unexpected<T>     //
    && not ::std::is_const_v<T>       //
    && not ::std::is_volatile_v<T>;

// Helper used as noexcept(...) operand where we want to evaluate both:
// * noexcept of an expression itself (e.g. operator==) AND
// * noexcept of the expression's implicit conversion to bool
// May only be used in unevaluated contexts; any ODR-use will trigger a link error.
constexpr bool _implicit_to_bool(bool) noexcept;

// Tag selecting the "direct-non-list-initialize a member from the result of std::invoke"
// constructors, required by transform/transform_error ([expected.object.monadic] and
// [expected.void.monadic]): the specified initialization is exactly `U u(invoke(...))` --
// guaranteed elision, so no extra move and an immovable U works -- which means the invoke
// expression itself must reach the member's initializer. Named _expected_* (mirroring
// optional.hpp's _optional_from_invoke_t) since both standalone headers share one namespace
// and may share a TU: a second definition of one name would collide.
constexpr inline struct _expected_from_invoke_t {
  explicit _expected_from_invoke_t() = default;
} _expected_from_invoke{};
} // namespace detail

/**
 * @brief The wrapper marking a value as an error: `std::unexpected` as specified for C++26
 *        ([expected.unexpected])
 *
 * Wraps `E` so that constructing or assigning an `expected` from it selects the error side.
 * Deviation: `operator==` carries a `noexcept` specification derived from `E` where the standard
 * leaves one unstated, marked `// extension` inline.
 *
 *
 * Its members are the standard's, and specified where
 * the reference page for this entity points.
 * @tparam E Type of the wrapped error value
 */
template <class E> class unexpected {
  static_assert(detail::_is_valid_unexpected<E>);

public:
  // [expected.un.cons], constructors
  constexpr unexpected(unexpected const &) = default;
  constexpr unexpected(unexpected &&) = default;

  template <class Err = E>
  constexpr explicit unexpected(Err &&e) noexcept(::std::is_nothrow_constructible_v<E, Err>)
    requires(not ::std::is_same_v<::std::remove_cvref_t<Err>, unexpected> &&        //
             not ::std::is_same_v<::std::remove_cvref_t<Err>, ::std::in_place_t> && //
             ::std::is_constructible_v<E, Err>)
      : e_(FWD(e))
  {
  }

  template <class... Args>
  constexpr explicit unexpected(::std::in_place_t /*ignored*/,
                                Args &&...a) noexcept(::std::is_nothrow_constructible_v<E, Args...>)
    requires ::std::is_constructible_v<E, Args...>
      : e_(FWD(a)...)
  {
  }

  template <class U, class... Args>
  constexpr explicit unexpected(::std::in_place_t /*ignored*/, ::std::initializer_list<U> i, Args &&...a) noexcept(
      ::std::is_nothrow_constructible_v<E, ::std::initializer_list<U> &, Args...>)
    requires ::std::is_constructible_v<E, ::std::initializer_list<U> &, Args...>
      : e_(i, FWD(a)...)
  {
  }

  constexpr unexpected &operator=(unexpected const &) = default;
  constexpr unexpected &operator=(unexpected &&) = default;

  // [expected.un.general], observers
  constexpr E const &error() const & noexcept { return e_; };
  constexpr E &error() & noexcept { return e_; };
  constexpr E const &&error() const && noexcept { return ::std::move(e_); };
  constexpr E &&error() && noexcept { return ::std::move(e_); };

  // [expected.un.swap], swap
  constexpr void swap(unexpected &other) noexcept(::std::is_nothrow_swappable_v<E>)
  {
    static_assert(::std::is_swappable_v<E>);
    using ::std::swap;
    swap(e_, other.e_);
  }

  // [expected.un.eq], equality operator
  template <class E2>
  constexpr friend bool operator==(unexpected const &x, unexpected<E2> const &y) //
      noexcept(noexcept(detail::_implicit_to_bool(x.error() == y.error())))      // extension
  {
    return x.error() == y.error();
  }

  // [expected.un.swap], friend swap
  constexpr friend void swap(unexpected &x, unexpected &y) noexcept(noexcept(x.swap(y)))
    requires ::std::is_swappable_v<E>
  {
    x.swap(y);
  }

private:
  E e_; // NOSONAR cpp:S6226 MSVC ignores the attribute
};

template <class E> unexpected(E) -> unexpected<E>;

namespace detail {
template <typename T, typename E>
constexpr bool _is_valid_expected =                                   //
    not ::std::is_reference_v<T>                                      //
    && not ::std::is_function_v<T>                                    //
    && not ::std::is_same_v<::std::remove_cv_t<T>, ::std::in_place_t> //
    && not ::std::is_same_v<::std::remove_cv_t<T>, unexpect_t>        //
    && not _is_some_unexpected<::std::remove_cv_t<T>>                 //
    && detail::_is_valid_unexpected<E>;

// Internal union wrapper for the value/error storage. Copy/move ctors
// are defaulted iff both `T` and `E` are trivially copy/move-constructible.
template <class T, class E> union _expected_union_t {
  using _value_t = T;
  T v_;
  E e_;

  template <typename S>
  constexpr explicit _expected_union_t(bool s, S &&src) //
      noexcept(::std::is_nothrow_constructible_v<T, decltype((FWD(src).v_))>
               && ::std::is_nothrow_constructible_v<E, decltype((FWD(src).e_))>)
  {
    if (s)
      ::std::construct_at(::std::addressof(v_), FWD(src).v_);
    else
      ::std::construct_at(::std::addressof(e_), FWD(src).e_);
  }

  constexpr _expected_union_t(_expected_union_t const &) = delete;
  constexpr _expected_union_t(_expected_union_t const &) noexcept //
    requires(::std::is_trivially_copy_constructible_v<T> && ::std::is_trivially_copy_constructible_v<E>)
  = default;
  constexpr _expected_union_t(_expected_union_t &&) = delete;
  constexpr _expected_union_t(_expected_union_t &&) noexcept //
    requires(::std::is_trivially_move_constructible_v<T> && ::std::is_trivially_move_constructible_v<E>)
  = default;
  constexpr _expected_union_t &operator=(_expected_union_t const &) = delete;
  constexpr _expected_union_t &operator=(_expected_union_t const &) noexcept //
    requires(::std::is_trivially_copy_assignable_v<T> && ::std::is_trivially_copy_assignable_v<E>)
  = default;
  constexpr _expected_union_t &operator=(_expected_union_t &&) = delete;
  constexpr _expected_union_t &operator=(_expected_union_t &&) noexcept //
    requires(::std::is_trivially_move_assignable_v<T> && ::std::is_trivially_move_assignable_v<E>)
  = default;

  template <class... Args>
  constexpr explicit _expected_union_t(::std::in_place_t /*ignored*/, Args &&...a) //
      noexcept(::std::is_nothrow_constructible_v<T, Args...>)
    requires ::std::is_constructible_v<T, Args...>
      : v_(FWD(a)...)
  {
  }
  template <class... Args>
  constexpr explicit _expected_union_t(unexpect_t /*ignored*/, Args &&...a) //
      noexcept(::std::is_nothrow_constructible_v<E, Args...>)
    requires ::std::is_constructible_v<E, Args...>
      : e_(FWD(a)...)
  {
  }

  // In the noexcept specs, a same-type (modulo cv) invoke result means guaranteed elision: the
  // invoke expression initializes the member directly and no constructor of T/E runs, so
  // probing is_nothrow_constructible (false e.g. for an immovable type) would be wrongly
  // pessimistic.
  template <typename Fn, typename... Args>
  constexpr explicit _expected_union_t(_expected_from_invoke_t /*ignored*/, ::std::in_place_t /*ignored*/, Fn &&fn,
                                       Args &&...args) //
      noexcept(::std::is_nothrow_invocable_v<Fn, Args...>
               && (::std::is_same_v<::std::remove_cv_t<::std::invoke_result_t<Fn, Args...>>, ::std::remove_cv_t<T>>
                   || ::std::is_nothrow_constructible_v<T, ::std::invoke_result_t<Fn, Args...>>))
      : v_(::std::invoke(FWD(fn), FWD(args)...))
  {
  }
  template <typename Fn, typename... Args>
  constexpr explicit _expected_union_t(_expected_from_invoke_t /*ignored*/, unexpect_t /*ignored*/, Fn &&fn,
                                       Args &&...args) //
      noexcept(::std::is_nothrow_invocable_v<Fn, Args...>
               && (::std::is_same_v<::std::remove_cv_t<::std::invoke_result_t<Fn, Args...>>, ::std::remove_cv_t<E>>
                   || ::std::is_nothrow_constructible_v<E, ::std::invoke_result_t<Fn, Args...>>))
      : e_(::std::invoke(FWD(fn), FWD(args)...))
  {
  }

  constexpr ~_expected_union_t() noexcept
    requires(::std::is_trivially_destructible_v<T> && ::std::is_trivially_destructible_v<E>)
  = default;
  constexpr ~_expected_union_t() noexcept {} // NOSONAR cpp:S3490 non-trivial arm of the conditionally-trivial pair

  // [expected.object.assign], implementation of reinit-expected
  template <typename New, typename Old, typename... Args>
  static constexpr void _reinit(New *newp, Old *oldp, Args &&...args) //
      noexcept(::std::is_nothrow_constructible_v<New, Args...>)
  {
    if constexpr (::std::is_nothrow_constructible_v<New, Args...>) {
      ::std::destroy_at(oldp);
      ::std::construct_at(newp, ::std::forward<Args>(args)...);
    } else if constexpr (::std::is_nothrow_move_constructible_v<New>) {
      New tmp(::std::forward<Args>(args)...);
      ::std::destroy_at(oldp);
      ::std::construct_at(newp, ::std::move(tmp));
    } else if constexpr (::std::is_trivially_copyable_v<Old>) {
      // Workaround for https://github.com/llvm/llvm-project/issues/196520:
      // clang on aarch64 sinks the snapshot load past the store-through-newp
      // when Old's TBAA tag differs from New's, corrupting the strong-EG
      // restoration on catch. A byte-buffer snapshot via std::memcpy is opaque
      // to TBAA, and preserving *oldp in place across the try (no destroy_at)
      // makes the catch a plain byte restore -- which for trivially-copyable
      // (and therefore trivially-destructible per [class.prop]/1). Old is
      // observationally identical to the destroy-and-recreate branch below.
      if (not ::std::is_constant_evaluated()) {
        alignas(Old) unsigned char _bytes[sizeof(Old)]; // NOSONAR cpp:S5945 raw byte snapshot
        ::std::memcpy(_bytes, oldp, sizeof(Old));
        try {
          ::std::construct_at(newp, ::std::forward<Args>(args)...);
        } catch (...) {
          ::std::memcpy(oldp, _bytes, sizeof(Old));
          throw;
        }
      } else {
        // LCOV_EXCL_START constant-evaluated only; runtime branches are above and below
        Old tmp(::std::move(*oldp));
        ::std::destroy_at(oldp);
        try {
          ::std::construct_at(newp, ::std::forward<Args>(args)...);
        } catch (...) {
          ::std::construct_at(oldp, ::std::move(tmp));
          throw;
        }
        // LCOV_EXCL_STOP
      }
    } else {
      Old tmp(::std::move(*oldp));
      ::std::destroy_at(oldp);
      try {
        ::std::construct_at(newp, ::std::forward<Args>(args)...);
      } catch (...) {
        ::std::construct_at(oldp, ::std::move(tmp));
        throw;
      }
    }
  }
};

template <class E> union _expected_union_t<void, E> {
  // _dummy_t placeholder, so the union always has an active member
  struct _dummy_t final {
    constexpr _dummy_t() noexcept = default;
  };

  using _value_t = _dummy_t;
  _dummy_t v_;
  E e_;

  template <typename S>
  constexpr explicit _expected_union_t(bool s, S &&src) //
      noexcept(::std::is_nothrow_constructible_v<E, decltype((FWD(src).e_))>)
  {
    if (s)
      ::std::construct_at(::std::addressof(v_));
    else
      ::std::construct_at(::std::addressof(e_), FWD(src).e_);
  }

  constexpr _expected_union_t(_expected_union_t const &) = delete;
  constexpr _expected_union_t(_expected_union_t const &) noexcept //
    requires(::std::is_trivially_copy_constructible_v<E>)
  = default;
  constexpr _expected_union_t(_expected_union_t &&) = delete;
  constexpr _expected_union_t(_expected_union_t &&) noexcept //
    requires(::std::is_trivially_move_constructible_v<E>)
  = default;
  constexpr _expected_union_t &operator=(_expected_union_t const &) = delete;
  constexpr _expected_union_t &operator=(_expected_union_t const &) noexcept //
    requires(::std::is_trivially_copy_assignable_v<E>)
  = default;
  constexpr _expected_union_t &operator=(_expected_union_t &&) = delete;
  constexpr _expected_union_t &operator=(_expected_union_t &&) noexcept //
    requires(::std::is_trivially_move_assignable_v<E>)
  = default;

  constexpr explicit _expected_union_t(::std::in_place_t /*ignored*/) noexcept
      : v_{} // NOSONAR cpp:S3230 activates the member
  {
  }

  template <class... Args>
  constexpr explicit _expected_union_t(unexpect_t /*ignored*/, Args &&...a) //
      noexcept(::std::is_nothrow_constructible_v<E, Args...>)
    requires ::std::is_constructible_v<E, Args...>
      : e_(FWD(a)...)
  {
  }

  template <typename Fn, typename... Args>
  // A same-type invoke result in the noexcept spec means guaranteed elision -- same
  // reasoning as the primary union's from-invoke constructors.
  constexpr explicit _expected_union_t(_expected_from_invoke_t /*ignored*/, unexpect_t /*ignored*/, Fn &&fn,
                                       Args &&...args) //
      noexcept(::std::is_nothrow_invocable_v<Fn, Args...>
               && (::std::is_same_v<::std::remove_cv_t<::std::invoke_result_t<Fn, Args...>>, ::std::remove_cv_t<E>>
                   || ::std::is_nothrow_constructible_v<E, ::std::invoke_result_t<Fn, Args...>>))
      : e_(::std::invoke(FWD(fn), FWD(args)...))
  {
  }

  constexpr ~_expected_union_t() noexcept
    requires(::std::is_trivially_destructible_v<E>)
  = default;
  constexpr ~_expected_union_t() noexcept {} // NOSONAR cpp:S3490 non-trivial arm of the conditionally-trivial pair

  // [expected.void.assign] mandates direct construction (no temporary).
  template <typename New, typename Old, typename... Args>
  static constexpr void _reinit(New *newp, Old *oldp, Args &&...args) //
      noexcept(::std::is_nothrow_constructible_v<New, Args...>)
  {
    if constexpr (::std::is_same_v<New, _dummy_t>) {
      ::std::destroy_at(oldp);
      ::std::construct_at(newp); // Never throws, since New is _dummy_t
    } else if constexpr (::std::is_nothrow_constructible_v<New, Args...>) {
      ::std::destroy_at(oldp);
      ::std::construct_at(newp, ::std::forward<Args>(args)...); // Never throws
    } else {
      ::std::destroy_at(oldp);
      try {
        ::std::construct_at(newp, ::std::forward<Args>(args)...);
      } catch (...) {
        ::std::construct_at(oldp); // Never throws, since Old is _dummy_t
        throw;
      }
    }
  }
};

template <typename> constexpr bool _is_expected_union = false;
template <typename T, typename E> constexpr bool _is_expected_union<_expected_union_t<T, E>> = true;

// Shared implementation base class for ::pfn::expected, both primary template
// and void specialization. Members are public since inheritance is private.
template <class T, class E, class Policy> struct _expected_base {
  using _storage_t = _expected_union_t<T, E>;
  // `_value_t` is `T` for non-void, and trivial `_dummy_t` for void.
  using _value_t = _storage_t::_value_t;
  _storage_t storage_;
  bool set_;

  // Constraint traits used by the converting ctors from sibling classes,
  // as defined in [expected.object.cons] and [expected.void.cons].
  template <class U, class G, class UF, class GF>
  using _can_convert_detail = ::std::bool_constant<                                                        //
      ::std::is_void_v<T>                                                                                  //
          ? (::std::is_void_v<U> && ::std::is_constructible_v<E, GF>                                       //
             && not ::std::is_constructible_v<unexpected<E>, typename Policy::template type<U, G> &>       //
             && not ::std::is_constructible_v<unexpected<E>, typename Policy::template type<U, G>>         //
             && not ::std::is_constructible_v<unexpected<E>, typename Policy::template type<U, G> const &> //
             && not ::std::is_constructible_v<unexpected<E>, typename Policy::template type<U, G> const>)  //
          : (not(::std::is_same_v<T, U> && ::std::is_same_v<E, G>)                                         //
             && ::std::is_constructible_v<T, UF>                                                           //
             && ::std::is_constructible_v<E, GF>                                                           //
             && not ::std::is_constructible_v<unexpected<E>, typename Policy::template type<U, G> &>       //
             && not ::std::is_constructible_v<unexpected<E>, typename Policy::template type<U, G>>         //
             && not ::std::is_constructible_v<unexpected<E>, typename Policy::template type<U, G> const &> //
             && not ::std::is_constructible_v<unexpected<E>, typename Policy::template type<U, G> const>   //
             && (::std::is_same_v<bool, ::std::remove_cv_t<T>>                                             //
                 || (not ::std::is_constructible_v<T, typename Policy::template type<U, G> &>              //
                     && not ::std::is_constructible_v<T, typename Policy::template type<U, G>>             //
                     && not ::std::is_constructible_v<T, typename Policy::template type<U, G> const &>     //
                     && not ::std::is_constructible_v<T, typename Policy::template type<U, G> const>       //
                     && not ::std::is_convertible_v<typename Policy::template type<U, G> &, T>             //
                     && not ::std::is_convertible_v<typename Policy::template type<U, G> &&, T>            //
                     && not ::std::is_convertible_v<typename Policy::template type<U, G> const &, T>       //
                     && not ::std::is_convertible_v<typename Policy::template type<U, G> const &&, T>)))>;

  // For T=void, U will be void, so `add_lvalue_reference_t<add_const_t<U>>` used to make the trait below well-formed
  template <class U, class G>
  using _can_copy_convert = _can_convert_detail<U, G, ::std::add_lvalue_reference_t<::std::add_const_t<U>>, G const &>;
  template <class U, class G> using _can_move_convert = _can_convert_detail<U, G, U, G>;

  template <class U>
  using _can_convert = ::std::bool_constant<                                                  //
      not ::std::is_void_v<T>                                                                 //
      && not ::std::is_same_v<::std::remove_cvref_t<U>, ::std::in_place_t>                    //
      && not ::std::is_same_v<::std::remove_cvref_t<U>, unexpect_t>                           // LWG4222
      && not ::std::is_same_v<typename Policy::template type<T, E>, ::std::remove_cvref_t<U>> //
      && not _is_some_unexpected<::std::remove_cvref_t<U>>                                    //
      && ::std::is_constructible_v<T, U>                                                      //
      && (not ::std::is_same_v<bool, ::std::remove_cv_t<T>>                                   //
          || not Policy::template is_specialization<::std::remove_cvref_t<U>>)>;

  // Constraint traits used by the converting assignment from sibling classes,
  // as defined in [expected.object.assign] and [expected.void.assign].
  //
  // For T=void, `_value_t` is the trivial `_dummy_t` so the `is_assignable_v<_value_t &, U>` substitution is
  // well-formed; the leading `not is_void_v<T>` guard then disables the trait.
  template <class U>
  using _can_convert_assign = ::std::bool_constant<                                           //
      not ::std::is_void_v<T>                                                                 //
      && not ::std::is_same_v<typename Policy::template type<T, E>, ::std::remove_cvref_t<U>> //
      && not _is_some_unexpected<::std::remove_cvref_t<U>>                                    //
      && ::std::is_constructible_v<_value_t, U>                                               //
      && ::std::is_assignable_v<_value_t &, U>                                                //
      && (::std::is_nothrow_constructible_v<_value_t, U>                                      //
          || ::std::is_nothrow_move_constructible_v<_value_t>                                 //
          || ::std::is_nothrow_move_constructible_v<E>)>;

  // Shared construction helper used by both the converting copy/move ctors
  // and same-type non-trivial copy/move ctors. Delegates the union's
  // member selection to _expected_union_t(bool, S&&), based on first parameter.
  template <typename S>
  constexpr explicit _expected_base(bool s, S &&src)
    requires(_is_expected_union<::std::remove_cvref_t<S>>)
      : storage_(s, FWD(src)), set_(s)
  {
  }

  // The wrapper's default, value (U&&) and unexpected<G> converting ctors forward directly to the
  // in_place / unexpect overloads below, so no dedicated overloads for those are provided here.
  template <class... Args>
  constexpr explicit _expected_base(::std::in_place_t /*ignored*/, Args &&...a) //
      noexcept(::std::is_nothrow_constructible_v<_storage_t, ::std::in_place_t, Args...>)
    requires ::std::is_constructible_v<_storage_t, ::std::in_place_t, Args...>
      : storage_(::std::in_place, FWD(a)...), set_(true)
  {
  }
  template <class U, class... Args>
  constexpr explicit _expected_base(::std::in_place_t /*ignored*/, ::std::initializer_list<U> il, Args &&...a) //
      noexcept(::std::is_nothrow_constructible_v<_storage_t, ::std::in_place_t, ::std::initializer_list<U> &, Args...>)
    requires ::std::is_constructible_v<_storage_t, ::std::in_place_t, ::std::initializer_list<U> &, Args...>
      : storage_(::std::in_place, il, FWD(a)...), set_(true)
  {
  }
  template <class... Args>
  constexpr explicit _expected_base(unexpect_t /*ignored*/, Args &&...a) //
      noexcept(::std::is_nothrow_constructible_v<E, Args...>)
    requires ::std::is_constructible_v<E, Args...>
      : storage_(unexpect, FWD(a)...), set_(false)
  {
  }
  template <class U, class... Args>
  constexpr explicit _expected_base(unexpect_t /*ignored*/, ::std::initializer_list<U> il, Args &&...a) //
      noexcept(::std::is_nothrow_constructible_v<E, ::std::initializer_list<U> &, Args...>)
    requires ::std::is_constructible_v<E, ::std::initializer_list<U> &, Args...>
      : storage_(unexpect, il, FWD(a)...), set_(false)
  {
  }
  template <typename Tag, typename Fn, typename... Args>
  constexpr explicit _expected_base(_expected_from_invoke_t tag, Tag which, Fn &&fn, Args &&...args) //
      noexcept(::std::is_nothrow_constructible_v<_storage_t, _expected_from_invoke_t, Tag, Fn, Args...>)
      : storage_(tag, which, FWD(fn), FWD(args)...), set_(::std::is_same_v<Tag, ::std::in_place_t>)
  {
  }

  // `add_lvalue_reference_t<add_const_t<U>>` keeps the explicit-specifier
  // and noexcept substitution well-formed when U=void (yields `void const`).
  template <class U, class G>
  constexpr explicit(not ::std::is_convertible_v<::std::add_lvalue_reference_t<::std::add_const_t<U>>, T>
                     || not ::std::is_convertible_v<G const &, E>)
      _expected_base(typename Policy::template type<U, G> const &s) //
      noexcept((::std::is_void_v<T>
                || ::std::is_nothrow_constructible_v<_value_t, ::std::add_lvalue_reference_t<::std::add_const_t<U>>>)
               && ::std::is_nothrow_constructible_v<E, G const &>) // extension
    requires(_can_copy_convert<U, G>::value)
      : _expected_base(static_cast<_expected_base<U, G, Policy> const &>(s).set_,
                       static_cast<_expected_base<U, G, Policy> const &>(s).storage_)
  {
  }
  template <class U, class G>
  constexpr explicit(not ::std::is_convertible_v<U, T> || not ::std::is_convertible_v<G, E>)
      _expected_base(typename Policy::template type<U, G> &&s)                         //
      noexcept((::std::is_void_v<T> || ::std::is_nothrow_constructible_v<_value_t, U>) //
               &&::std::is_nothrow_constructible_v<E, G>)                              // extension
    requires(_can_move_convert<U, G>::value)
      : _expected_base(static_cast<_expected_base<U, G, Policy> &&>(s).set_,
                       ::std::move(static_cast<_expected_base<U, G, Policy> &&>(s).storage_))
  {
  }

  // [expected.object.assign] and [expected.void.assign]: the converting `operator=(U&&)` and
  // `operator=(unexpected<G>...)` overloads are implemented directly in the wrappers (which call
  // `_assign_value` / `_assign_unexpected` below), so no dedicated overloads are provided here.
  template <class... Args>
  constexpr _value_t &emplace(Args &&...args) noexcept
    requires(not ::std::is_void_v<T> && ::std::is_nothrow_constructible_v<T, Args...>)
  {
    if (set_) {
      ::std::destroy_at(::std::addressof(storage_.v_));
    } else {
      ::std::destroy_at(::std::addressof(storage_.e_));
      set_ = true;
    }
    return *::std::construct_at(::std::addressof(storage_.v_), ::std::forward<Args>(args)...);
  }

  template <class U, class... Args>
  constexpr _value_t &emplace(::std::initializer_list<U> il, Args &&...args) noexcept
    requires(not ::std::is_void_v<T> && ::std::is_nothrow_constructible_v<T, ::std::initializer_list<U> &, Args...>)
  {
    if (set_) {
      ::std::destroy_at(::std::addressof(storage_.v_));
    } else {
      ::std::destroy_at(::std::addressof(storage_.e_));
      set_ = true;
    }
    return *::std::construct_at(::std::addressof(storage_.v_), il, ::std::forward<Args>(args)...);
  }

  constexpr void emplace() noexcept
    requires(::std::is_void_v<T>)
  {
    if (not set_) {
      ::std::destroy_at(::std::addressof(storage_.e_));
      ::std::construct_at(::std::addressof(storage_.v_));
      set_ = true;
    }
  }

  constexpr _expected_base(_expected_base const &) noexcept = default;
  constexpr _expected_base(_expected_base &&) noexcept = default;
  constexpr _expected_base &operator=(_expected_base const &) noexcept = default;
  constexpr _expected_base &operator=(_expected_base &&) noexcept = default;

  constexpr ~_expected_base() //
    requires(::std::is_trivially_destructible_v<_value_t> && ::std::is_trivially_destructible_v<E>)
  = default;
  constexpr ~_expected_base() //
    requires(::std::is_trivially_destructible_v<_value_t> && not ::std::is_trivially_destructible_v<E>)
  {
    if (not set_)
      ::std::destroy_at(::std::addressof(storage_.e_));
  }
  constexpr ~_expected_base() //
    requires(not ::std::is_trivially_destructible_v<_value_t> && ::std::is_trivially_destructible_v<E>)
  {
    if (set_)
      ::std::destroy_at(::std::addressof(storage_.v_));
  }
  constexpr ~_expected_base() //
    requires(not ::std::is_trivially_destructible_v<_value_t> && not ::std::is_trivially_destructible_v<E>)
  {
    if (set_)
      ::std::destroy_at(::std::addressof(storage_.v_));
    else
      ::std::destroy_at(::std::addressof(storage_.e_));
  }

  // [expected.object.obs], observers
  static constexpr auto &&_value(auto &&s) noexcept
    requires(not ::std::is_void_v<T>)
  {
    ASSERT(s.set_); // LCOV_EXCL_LINE
    return FWD(s).storage_.v_;
  }
  constexpr _value_t const *operator->() const noexcept
    requires(not ::std::is_void_v<T>)
  {
    ASSERT(set_); // LCOV_EXCL_LINE
    return ::std::addressof(storage_.v_);
  }
  constexpr _value_t *operator->() noexcept
    requires(not ::std::is_void_v<T>)
  {
    ASSERT(set_); // LCOV_EXCL_LINE
    return ::std::addressof(storage_.v_);
  }
  constexpr _value_t const &operator*() const & noexcept
    requires(not ::std::is_void_v<T>)
  {
    return *(this->operator->());
  }
  constexpr _value_t &operator*() & noexcept
    requires(not ::std::is_void_v<T>)
  {
    return *(this->operator->());
  }
  constexpr _value_t const &&operator*() const && noexcept
    requires(not ::std::is_void_v<T>)
  {
    return ::std::move(*(this->operator->()));
  }
  constexpr _value_t &&operator*() && noexcept
    requires(not ::std::is_void_v<T>)
  {
    return ::std::move(*(this->operator->()));
  }
  constexpr explicit operator bool() const noexcept { return set_; }
  constexpr bool has_value() const noexcept { return set_; }
  constexpr bool has_error() const noexcept { return !set_; } // P3798
  constexpr _value_t const &value() const &
    requires(not ::std::is_void_v<T>)
  {
    static_assert(::std::is_copy_constructible_v<E>);
    if (not set_)
      throw bad_expected_access<E>(storage_.e_);
    return storage_.v_;
  }
  constexpr _value_t &value() &
    requires(not ::std::is_void_v<T>)
  {
    static_assert(::std::is_copy_constructible_v<E>);
    if (not set_)
      throw bad_expected_access<E>(::std::as_const(storage_.e_));
    return storage_.v_;
  }
  constexpr _value_t const &&value() const &&
    requires(not ::std::is_void_v<T>)
  {
    static_assert(::std::is_copy_constructible_v<E>);
    static_assert(::std::is_constructible_v<E, E const &&>);
    if (not set_)
      throw bad_expected_access<E>(::std::move(storage_.e_));
    return ::std::move(storage_.v_);
  }
  constexpr _value_t &&value() &&
    requires(not ::std::is_void_v<T>)
  {
    static_assert(::std::is_copy_constructible_v<E>);
    static_assert(::std::is_constructible_v<E, E &&>);
    if (not set_)
      throw bad_expected_access<E>(::std::move(storage_.e_));
    return ::std::move(storage_.v_);
  }
  // [expected.void.obs] for void specialization, operator* is a no-op that asserts the expected has a value
  constexpr void operator*() const & noexcept
    requires(::std::is_void_v<T>)
  {
    ASSERT(set_); // LCOV_EXCL_LINE
  }
  constexpr void operator*() & noexcept
    requires(::std::is_void_v<T>)
  {
    ASSERT(set_); // LCOV_EXCL_LINE
  }
  constexpr void operator*() const && noexcept
    requires(::std::is_void_v<T>)
  {
    ASSERT(set_); // LCOV_EXCL_LINE
  }
  constexpr void operator*() && noexcept
    requires(::std::is_void_v<T>)
  {
    ASSERT(set_); // LCOV_EXCL_LINE
  }
  constexpr void value() const &
    requires(::std::is_void_v<T>)
  {
    static_assert(::std::is_copy_constructible_v<E>);
    if (not set_)
      throw bad_expected_access<E>(storage_.e_);
  }
  constexpr void value() &&
    requires(::std::is_void_v<T>)
  {
    static_assert(::std::is_copy_constructible_v<E>);
    static_assert(::std::is_move_constructible_v<E>);
    if (not set_)
      throw bad_expected_access<E>(::std::move(storage_.e_));
  }

  static constexpr auto &&_error(auto &&s) noexcept
  {
    ASSERT(not s.set_); // LCOV_EXCL_LINE
    return FWD(s).storage_.e_;
  }
  constexpr E const &error() const & noexcept { return _error(*this); }
  constexpr E &error() & noexcept { return _error(*this); }
  constexpr E const &&error() const && noexcept { return _error(::std::move(*this)); }
  constexpr E &&error() && noexcept { return _error(::std::move(*this)); }

  template <class U = ::std::remove_cv_t<T>>
  constexpr T value_or(U &&v) const &                                                              //
      noexcept(::std::is_nothrow_copy_constructible_v<T> && ::std::is_nothrow_convertible_v<U, T>) // extension
    requires(not ::std::is_void_v<T>)
  {
    static_assert(::std::is_copy_constructible_v<T>);
    static_assert(::std::is_convertible_v<U, T>);
    return set_ ? storage_.v_ : static_cast<T>(FWD(v));
  }
  template <class U = ::std::remove_cv_t<T>>
  constexpr T value_or(U &&v) &&                                                                   //
      noexcept(::std::is_nothrow_move_constructible_v<T> && ::std::is_nothrow_convertible_v<U, T>) // extension
    requires(not ::std::is_void_v<T>)
  {
    static_assert(::std::is_move_constructible_v<T>);
    static_assert(::std::is_convertible_v<U, T>);
    return set_ ? ::std::move(storage_.v_) : static_cast<T>(FWD(v));
  }

  template <class G = E>
  constexpr E error_or(G &&e) const &                                                              //
      noexcept(::std::is_nothrow_copy_constructible_v<E> && ::std::is_nothrow_convertible_v<G, E>) // extension
  {
    static_assert(::std::is_copy_constructible_v<E>);
    static_assert(::std::is_convertible_v<G, E>);
    if (set_) {
      return FWD(e);
    }
    return storage_.e_;
  }
  template <class G = E>
  constexpr E error_or(G &&e) &&                                                                   //
      noexcept(::std::is_nothrow_move_constructible_v<E> && ::std::is_nothrow_convertible_v<G, E>) // extension
  {
    static_assert(::std::is_move_constructible_v<E>);
    static_assert(::std::is_convertible_v<G, E>);
    if (set_) {
      return FWD(e);
    }
    return ::std::move(storage_.e_);
  }

  template <typename Self, typename Fn>
  static constexpr auto _and_then(Self &&self, Fn &&fn) //
      noexcept(::std::is_nothrow_invocable_v<Fn, decltype(_expected_base::_value(FWD(self)))>
               && ::std::is_nothrow_constructible_v<E, decltype(_expected_base::_error(FWD(self)))>)
    requires(not ::std::is_void_v<T> && ::std::is_invocable_v<Fn, decltype(_expected_base::_value(FWD(self)))>
             && ::std::is_constructible_v<E, decltype(_expected_base::_error(FWD(self)))>)
  {
    using result_t = ::std::remove_cvref_t<::std::invoke_result_t<Fn, decltype(_expected_base::_value(FWD(self)))>>;
    static_assert(Policy::template is_specialization<result_t>);
    static_assert(::std::is_same_v<typename result_t::error_type, typename ::std::remove_cvref_t<Self>::error_type>);
    if (self.has_value()) {
      return ::std::invoke(FWD(fn), _expected_base::_value(FWD(self)));
    }
    return result_t(unexpect, _expected_base::_error(FWD(self)));
  }

  template <typename Self, typename Fn>
  static constexpr auto _and_then(Self &&self, Fn &&fn) //
      noexcept(::std::is_nothrow_invocable_v<Fn>
               && ::std::is_nothrow_constructible_v<E, decltype(_expected_base::_error(FWD(self)))>)
    requires(::std::is_void_v<T> && ::std::is_invocable_v<Fn>
             && ::std::is_constructible_v<E, decltype(_expected_base::_error(FWD(self)))>)
  {
    using result_t = ::std::remove_cvref_t<::std::invoke_result_t<Fn>>;
    static_assert(Policy::template is_specialization<result_t>);
    static_assert(::std::is_same_v<typename result_t::error_type, typename ::std::remove_cvref_t<Self>::error_type>);
    if (self.has_value()) {
      return ::std::invoke(FWD(fn));
    }
    return result_t(unexpect, _expected_base::_error(FWD(self)));
  }

  template <typename Self, typename Fn>
  static constexpr auto _or_else(Self &&self, Fn &&fn) //
      noexcept(::std::is_nothrow_invocable_v<Fn, decltype(_expected_base::_error(FWD(self)))>
               && ::std::is_nothrow_constructible_v<T, decltype(_expected_base::_value(FWD(self)))>)
    requires(not ::std::is_void_v<T> && ::std::is_invocable_v<Fn, decltype(_expected_base::_error(FWD(self)))>
             && ::std::is_constructible_v<T, decltype(_expected_base::_value(FWD(self)))>)
  {
    using result_t = ::std::remove_cvref_t<::std::invoke_result_t<Fn, decltype(_expected_base::_error(FWD(self)))>>;
    static_assert(Policy::template is_specialization<result_t>);
    static_assert(::std::is_same_v<typename result_t::value_type, typename ::std::remove_cvref_t<Self>::value_type>);
    if (self.has_value()) {
      return result_t(::std::in_place, _expected_base::_value(FWD(self)));
    }
    return ::std::invoke(FWD(fn), _expected_base::_error(FWD(self)));
  }

  template <typename Self, typename Fn>
  static constexpr auto _or_else(Self &&self, Fn &&fn) //
      noexcept(::std::is_nothrow_invocable_v<Fn, decltype(_expected_base::_error(FWD(self)))>)
    requires(::std::is_void_v<T> && ::std::is_invocable_v<Fn, decltype(_expected_base::_error(FWD(self)))>)
  {
    using result_t = ::std::remove_cvref_t<::std::invoke_result_t<Fn, decltype(_expected_base::_error(FWD(self)))>>;
    static_assert(Policy::template is_specialization<result_t>);
    static_assert(::std::is_same_v<typename result_t::value_type, typename ::std::remove_cvref_t<Self>::value_type>);
    if (self.has_value()) {
      return result_t(::std::in_place);
    }
    return ::std::invoke(FWD(fn), _expected_base::_error(FWD(self)));
  }

  // In the noexcept specs of the four _transform/_transform_error overloads, only the invoke
  // and copying the untouched side can throw: the new value/error is direct-non-list-
  // initialized from the invoke expression (guaranteed elision, no constructor of it runs).
  template <typename Self, typename Fn>
  static constexpr auto _transform(Self &&self, Fn &&fn) //
      noexcept(::std::is_nothrow_invocable_v<Fn, decltype(_expected_base::_value(FWD(self)))>
               && ::std::is_nothrow_constructible_v<E, decltype(_expected_base::_error(FWD(self)))>) // extension
    requires(not ::std::is_void_v<T> && ::std::is_invocable_v<Fn, decltype(_expected_base::_value(FWD(self)))>
             && ::std::is_constructible_v<E, decltype(_expected_base::_error(FWD(self)))>)
  {
    using value_t = ::std::remove_cv_t<::std::invoke_result_t<Fn, decltype(_expected_base::_value(FWD(self)))>>;
    static_assert(detail::_is_valid_expected<value_t, E>);
    using result_t = typename Policy::template type<value_t, E>;
    if (self.has_value()) {
      if constexpr (not ::std::is_void_v<value_t>) {
        return result_t(_expected_from_invoke, ::std::in_place, FWD(fn), _expected_base::_value(FWD(self)));
      } else {
        ::std::invoke(FWD(fn), _expected_base::_value(FWD(self)));
        return result_t(::std::in_place);
      }
    }
    return result_t(unexpect, _expected_base::_error(FWD(self)));
  }

  template <typename Self, typename Fn>
  static constexpr auto _transform(Self &&self, Fn &&fn) //
      noexcept(::std::is_nothrow_invocable_v<Fn>
               && ::std::is_nothrow_constructible_v<E, decltype(_expected_base::_error(FWD(self)))>) // extension
    requires(::std::is_void_v<T> && ::std::is_invocable_v<Fn>
             && ::std::is_constructible_v<E, decltype(_expected_base::_error(FWD(self)))>)
  {
    using value_t = ::std::remove_cv_t<::std::invoke_result_t<Fn>>;
    static_assert(detail::_is_valid_expected<value_t, E>);
    using result_t = typename Policy::template type<value_t, E>;
    if (self.has_value()) {
      if constexpr (not ::std::is_void_v<value_t>) {
        return result_t(_expected_from_invoke, ::std::in_place, FWD(fn));
      } else {
        ::std::invoke(FWD(fn));
        return result_t(::std::in_place);
      }
    }
    return result_t(unexpect, _expected_base::_error(FWD(self)));
  }

  template <typename Self, typename Fn>
  static constexpr auto _transform_error(Self &&self, Fn &&fn) //
      noexcept(::std::is_nothrow_invocable_v<Fn, decltype(_expected_base::_error(FWD(self)))>
               && ::std::is_nothrow_constructible_v<T, decltype(_expected_base::_value(FWD(self)))>) // extension
    requires(not ::std::is_void_v<T> && ::std::is_invocable_v<Fn, decltype(_expected_base::_error(FWD(self)))>
             && ::std::is_constructible_v<T, decltype(_expected_base::_value(FWD(self)))>)
  {
    using error_t = ::std::remove_cv_t<::std::invoke_result_t<Fn, decltype(_expected_base::_error(FWD(self)))>>;
    static_assert(detail::_is_valid_unexpected<error_t>);
    using result_t = typename Policy::template type<T, error_t>;
    if (not self.has_value()) {
      return result_t(_expected_from_invoke, unexpect, FWD(fn), _expected_base::_error(FWD(self)));
    }
    return result_t(::std::in_place, _expected_base::_value(FWD(self)));
  }

  template <typename Self, typename Fn>
  static constexpr auto _transform_error(Self &&self, Fn &&fn)                                 //
      noexcept(::std::is_nothrow_invocable_v<Fn, decltype(_expected_base::_error(FWD(self)))>) // extension
    requires(::std::is_void_v<T> && ::std::is_invocable_v<Fn, decltype(_expected_base::_error(FWD(self)))>)
  {
    using error_t = ::std::remove_cv_t<::std::invoke_result_t<Fn, decltype(_expected_base::_error(FWD(self)))>>;
    static_assert(detail::_is_valid_unexpected<error_t>);
    using result_t = typename Policy::template type<void, error_t>;
    if (not self.has_value()) {
      return result_t(_expected_from_invoke, unexpect, FWD(fn), _expected_base::_error(FWD(self)));
    }
    return result_t(::std::in_place);
  }

  // Assignment body shared by the public expected operator= overloads,
  // which keep their constraints/noexcept clauses and forward `s` here as
  // lvalue or rvalue. For T=void all `storage_.v_` operations are no-ops
  // at runtime (trivial `_dummy_t`) but still track the active union member.
  constexpr void _assign(auto &&s)
  {
    if (set_ && s.set_) {
      storage_.v_ = FWD(s).storage_.v_;
    } else if (set_) {
      _storage_t::_reinit(::std::addressof(storage_.e_), ::std::addressof(storage_.v_), FWD(s).storage_.e_);
      set_ = false;
    } else if (s.set_) {
      _storage_t::_reinit(::std::addressof(storage_.v_), ::std::addressof(storage_.e_), FWD(s).storage_.v_);
      set_ = true;
    } else {
      storage_.e_ = FWD(s).storage_.e_;
    }
  }
  template <class U> constexpr void _assign_value(U &&s)
  {
    if (set_) {
      storage_.v_ = FWD(s);
    } else {
      _storage_t::_reinit(::std::addressof(storage_.v_), ::std::addressof(storage_.e_), FWD(s));
      set_ = true;
    }
  }
  constexpr void _assign_unexpected(auto &&s)
  {
    if (not set_) {
      storage_.e_ = FWD(s).error();
    } else {
      _storage_t::_reinit(::std::addressof(storage_.e_), ::std::addressof(storage_.v_), FWD(s).error());
      set_ = false;
    }
  }

  // Cross-state swap; lhs holds value, rhs holds error.
  static constexpr void _swap_helper(_expected_base &lhs, _expected_base &rhs) //
      noexcept(::std::is_nothrow_move_constructible_v<T> && ::std::is_nothrow_move_constructible_v<E>)
  {
    if constexpr (::std::is_nothrow_move_constructible_v<E>) {
      E tmp(::std::move(rhs.storage_.e_));
      ::std::destroy_at(::std::addressof(rhs.storage_.e_));
      try {
        ::std::construct_at(::std::addressof(rhs.storage_.v_), ::std::move(lhs.storage_.v_));
        ::std::destroy_at(::std::addressof(lhs.storage_.v_));
        ::std::construct_at(::std::addressof(lhs.storage_.e_), ::std::move(tmp));
      } catch (...) {
        ::std::construct_at(::std::addressof(rhs.storage_.e_), ::std::move(tmp));
        throw;
      }
    } else {
      auto tmp(::std::move(lhs.storage_.v_));
      ::std::destroy_at(::std::addressof(lhs.storage_.v_));
      try {
        ::std::construct_at(::std::addressof(lhs.storage_.e_), ::std::move(rhs.storage_.e_));
        ::std::destroy_at(::std::addressof(rhs.storage_.e_));
        ::std::construct_at(::std::addressof(rhs.storage_.v_), ::std::move(tmp));
      } catch (...) {
        ::std::construct_at(::std::addressof(lhs.storage_.v_), ::std::move(tmp));
        throw;
      }
    }
    lhs.set_ = false;
    rhs.set_ = true;
  }

  constexpr void _swap_with(_expected_base &rhs)
  {
    if (set_ == rhs.set_) {
      if (set_) {
        if constexpr (not ::std::is_void_v<T>) {
          using ::std::swap;
          swap(storage_.v_, rhs.storage_.v_);
        }
      } else {
        using ::std::swap;
        swap(storage_.e_, rhs.storage_.e_);
      }
    } else if constexpr (::std::is_void_v<T>) {
      // [expected.void.swap] mandates a single E move on cross-state.
      // On exception from E's move, restore the `_dummy_t` value so the union
      // always has an active member (required for constant evaluation).
      if (set_) {
        ::std::destroy_at(::std::addressof(storage_.v_));
        try {
          ::std::construct_at(::std::addressof(storage_.e_), ::std::move(rhs.storage_.e_));
        } catch (...) {
          ::std::construct_at(::std::addressof(storage_.v_));
          throw;
        }
        ::std::destroy_at(::std::addressof(rhs.storage_.e_));
        ::std::construct_at(::std::addressof(rhs.storage_.v_));
        set_ = false;
        rhs.set_ = true;
      } else {
        rhs._swap_with(*this);
      }
    } else if (set_) {
      _swap_helper(*this, rhs);
    } else {
      _swap_helper(rhs, *this);
    }
  }

  // [expected.object.eq] and [expected.void.eq], equality operators
  template <class T2, class E2>
    requires(not ::std::is_void_v<T> && not ::std::is_void_v<T2>)
  constexpr friend bool operator==(typename Policy::template type<T, E> const &x,
                                   typename Policy::template type<T2, E2> const &y) //
      noexcept(noexcept(detail::_implicit_to_bool(*x == *y))
               && noexcept(detail::_implicit_to_bool(x.error() == y.error()))) // extension
    requires requires {
      { *x == *y } -> ::std::convertible_to<bool>;
      { x.error() == y.error() } -> ::std::convertible_to<bool>;
    }
  {
    if (x.has_value() != y.has_value())
      return false;
    if (x.has_value())
      return *x == *y;
    return x.error() == y.error();
  }
  template <class T2, class E2>
    requires(::std::is_void_v<T> && ::std::is_void_v<T2>)
  constexpr friend bool operator==(typename Policy::template type<T, E> const &x,
                                   typename Policy::template type<T2, E2> const &y) //
      noexcept(noexcept(detail::_implicit_to_bool(x.error() == y.error())))         // extension
    requires requires {
      { x.error() == y.error() } -> ::std::convertible_to<bool>;
    }
  {
    if (x.has_value() != y.has_value())
      return false;
    if (x.has_value())
      return true;
    return x.error() == y.error();
  }
  // The comparison against a value is NOT here: alone among these, its constraint asks about the
  // other operand, and a hidden friend can only spell its own operand as `Policy::type<T, E>` - a
  // non-deduced context, which leaves deduction unable to reject anything. The constraint would then
  // be evaluated for every left operand there is, and where that operand reaches this same operator
  // by ADL, satisfaction depends on itself. It lives at namespace scope instead, one per carrier, so
  // that its operand is deduced and a left operand which is not that carrier answers first.
  template <class E2>
  constexpr friend bool operator==(typename Policy::template type<T, E> const &x, unexpected<E2> const &e) //
      noexcept(noexcept(detail::_implicit_to_bool(x.error() == e.error())))                                // extension
    requires requires {
      { x.error() == e.error() } -> ::std::convertible_to<bool>;
    }
  {
    if (x.has_value())
      return false;
    return x.error() == e.error();
  }

  // [expected.object.swap] and [expected.void.swap]
  constexpr friend void swap(typename Policy::template type<T, E> &x, //
                             typename Policy::template type<T, E> &y) noexcept(noexcept(x.swap(y)))
    requires requires { x.swap(y); }
  {
    x.swap(y);
  }
};

} // namespace detail

template <class T, class E> class expected;
template <class E> class expected<void, E>;

namespace detail {
template <typename> constexpr bool _is_some_expected = false;
template <typename T, typename E> constexpr bool _is_some_expected<::pfn::expected<T, E>> = true;

struct expected_policy {
  template <class U, class G> using type = ::pfn::expected<U, G>;
  template <class X> static constexpr bool is_specialization = _is_some_expected<X>;
};

} // namespace detail

/**
 * @brief `std::expected` in its C++26 shape: a computation yielding a success `T` or an error `E`
 *
 * A polyfill for C++20 compilers, tracking the C++ working draft: members are as
 * [expected.object] specifies them, including changes accepted beyond C++26 (`has_error`,
 * P3798). Deliberate deviations:
 * - a `noexcept` specification is derived from `T`, `E` and the callable arguments wherever the
 *   standard leaves one unstated; each such clause is marked `// extension` inline;
 * - the draft's hardened preconditions are checked by an assertion, customizable by defining
 *   `LIBFN_ASSERT` before inclusion;
 * - the comparison against a value is declared at namespace scope, not as the specified hidden
 *   friend, keeping its constraint deducible.
 *
 *
 * Its members are the standard's, and specified where
 * the reference page for this entity points.
 * @tparam T Type of the success value; `void` selects the specialization
 * @tparam E Type of the error value
 */
template <class T, class E> class expected : private detail::_expected_base<T, E, detail::expected_policy> {
  static_assert(detail::_is_valid_expected<T, E>);
  using _base = detail::_expected_base<T, E, detail::expected_policy>;

  // Allow sibling `_expected_base` instantiations to downcast into our private base
  // (needed for the lifted converting ctors and friend operators) and to call the
  // private from-invoke ctor below.
  template <class, class, class> friend struct detail::_expected_base;

public:
  using value_type = T;
  using error_type = E;
  using unexpected_type = unexpected<E>;

  template <class U> using rebind = expected<U, error_type>;

  // [expected.object.cons] constructors. Not `using _base::_base;` to avoid a clang-16 bug.
  constexpr expected()                                       //
      noexcept(::std::is_nothrow_default_constructible_v<T>) // extension
    requires ::std::is_default_constructible_v<T>
      : _base(::std::in_place)
  {
  }

  template <class U, class G>
  constexpr explicit(not ::std::is_convertible_v<U const &, T> || not ::std::is_convertible_v<G const &, E>)
      expected(expected<U, G> const &s) //
      noexcept(::std::is_nothrow_constructible_v<T, U const &>
               && ::std::is_nothrow_constructible_v<E, G const &>) // extension
    requires(_base::template _can_copy_convert<U, G>::value)
      : _base(s)
  {
  }
  template <class U, class G>
  constexpr explicit(not ::std::is_convertible_v<U, T> || not ::std::is_convertible_v<G, E>)
      expected(expected<U, G> &&s)                                                                 //
      noexcept(::std::is_nothrow_constructible_v<T, U> && ::std::is_nothrow_constructible_v<E, G>) // extension
    requires(_base::template _can_move_convert<U, G>::value)
      : _base(::std::move(s))
  {
  }
  template <class U = ::std::remove_cv_t<T>>
  constexpr explicit(not ::std::is_convertible_v<U, T>) expected(U &&v) // NOSONAR cpp:S6458 _can_convert excludes self
      noexcept(::std::is_nothrow_constructible_v<T, U>)                 // extension
    requires(_base::template _can_convert<U>::value)
      : _base(::std::in_place, FWD(v))
  {
  }
  template <class G>
  constexpr explicit(!::std::is_convertible_v<G const &, E>) expected(unexpected<G> const &g) //
      noexcept(::std::is_nothrow_constructible_v<E, G const &>)                               // extension
    requires(::std::is_constructible_v<E, G const &>)
      : _base(unexpect, ::std::forward<G const &>(g.error())) // NOSONAR cpp:S6031 forward<GF> per the standard
  {
  }
  template <class G>
  constexpr explicit(!::std::is_convertible_v<G, E>) expected(unexpected<G> &&g) //
      noexcept(::std::is_nothrow_constructible_v<E, G>)                          // extension
    requires(::std::is_constructible_v<E, G>)
      : _base(unexpect, ::std::forward<G>(g.error()))
  {
  }

  template <class... Args>
  constexpr explicit expected(::std::in_place_t, Args &&...a) //
      noexcept(::std::is_nothrow_constructible_v<T, Args...>) // extension
    requires ::std::is_constructible_v<T, Args...>
      : _base(::std::in_place, FWD(a)...)
  {
  }
  template <class U, class... Args>
  constexpr explicit expected(::std::in_place_t, ::std::initializer_list<U> il, Args &&...a) //
      noexcept(::std::is_nothrow_constructible_v<T, ::std::initializer_list<U> &, Args...>)  // extension
    requires ::std::is_constructible_v<T, ::std::initializer_list<U> &, Args...>
      : _base(::std::in_place, il, FWD(a)...)
  {
  }
  template <class... Args>
  constexpr explicit expected(unexpect_t, Args &&...a)        //
      noexcept(::std::is_nothrow_constructible_v<E, Args...>) // extension
    requires ::std::is_constructible_v<E, Args...>
      : _base(unexpect, FWD(a)...)
  {
  }
  template <class U, class... Args>
  constexpr explicit expected(unexpect_t, ::std::initializer_list<U> il, Args &&...a)       //
      noexcept(::std::is_nothrow_constructible_v<E, ::std::initializer_list<U> &, Args...>) // extension
    requires ::std::is_constructible_v<E, ::std::initializer_list<U> &, Args...>
      : _base(unexpect, il, FWD(a)...)
  {
  }

  constexpr expected(expected const &) = delete;
  constexpr expected(expected const &s)                                                                //
      noexcept(::std::is_nothrow_copy_constructible_v<T> && ::std::is_nothrow_copy_constructible_v<E>) // extension
    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;
  constexpr expected(expected const &s)                                                                //
      noexcept(::std::is_nothrow_copy_constructible_v<T> && ::std::is_nothrow_copy_constructible_v<E>) // extension
    requires(::std::is_copy_constructible_v<T> && ::std::is_copy_constructible_v<E>
             && (not ::std::is_trivially_copy_constructible_v<T> || not ::std::is_trivially_copy_constructible_v<E>))
      : _base(s.set_, FWD(s).storage_)
  {
  }
  constexpr expected(expected &&s) noexcept
    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;
  constexpr expected(expected &&s)                                                                     //
      noexcept(::std::is_nothrow_move_constructible_v<T> && ::std::is_nothrow_move_constructible_v<E>) // required
    requires(::std::is_move_constructible_v<T> && ::std::is_move_constructible_v<E>
             && (not ::std::is_trivially_move_constructible_v<T> || not ::std::is_trivially_move_constructible_v<E>))
      : _base(s.set_, FWD(s).storage_)
  {
  }

  // [expected.object.dtor]
  constexpr ~expected() = default;

  // [expected.void.assign], assignment. Not `using _base::operator=;` to avoid an MSVC bug.
  template <class U = ::std::remove_cv_t<T>>
  constexpr expected &operator=(U &&s)                                                            //
      noexcept(::std::is_nothrow_assignable_v<T &, U> && ::std::is_nothrow_constructible_v<T, U>) // extension
    requires(_base::template _can_convert_assign<U>::value)
  {
    this->_assign_value(FWD(s));
    return *this;
  }
  template <class G>
  constexpr expected &operator=(unexpected<G> const &s) //
      noexcept(::std::is_nothrow_assignable_v<E &, G const &>
               && ::std::is_nothrow_constructible_v<E, G const &>) // extension
    requires(::std::is_constructible_v<E, G const &> && ::std::is_assignable_v<E &, G const &>
             && (::std::is_nothrow_constructible_v<E, G const &> || ::std::is_nothrow_move_constructible_v<T>
                 || ::std::is_nothrow_move_constructible_v<E>))
  {
    this->_assign_unexpected(s);
    return *this;
  }
  template <class G>
  constexpr expected &operator=(unexpected<G> &&s)                                                //
      noexcept(::std::is_nothrow_assignable_v<E &, G> && ::std::is_nothrow_constructible_v<E, G>) // extension
    requires(::std::is_constructible_v<E, G> && ::std::is_assignable_v<E &, G>
             && (::std::is_nothrow_constructible_v<E, G> || ::std::is_nothrow_move_constructible_v<T>
                 || ::std::is_nothrow_move_constructible_v<E>))
  {
    this->_assign_unexpected(::std::move(s));
    return *this;
  }

  constexpr expected &operator=(expected const &) = delete;
  constexpr expected &operator=(expected const &) //
      noexcept(::std::is_nothrow_copy_assignable_v<T> && ::std::is_nothrow_copy_constructible_v<T>
               && ::std::is_nothrow_copy_assignable_v<E> && ::std::is_nothrow_copy_constructible_v<E>) // extension
    requires(::std::is_copy_assignable_v<T> && ::std::is_copy_constructible_v<T> && ::std::is_copy_assignable_v<E>
             && ::std::is_copy_constructible_v<E>
             && (::std::is_nothrow_move_constructible_v<T> || ::std::is_nothrow_move_constructible_v<E>)
             && ::std::is_trivially_copy_constructible_v<T> && ::std::is_trivially_copy_assignable_v<T>
             && ::std::is_trivially_destructible_v<T> && ::std::is_trivially_copy_constructible_v<E>
             && ::std::is_trivially_copy_assignable_v<E> && ::std::is_trivially_destructible_v<E>)
  = default;
  constexpr expected &operator=(expected const &s) //
      noexcept(::std::is_nothrow_copy_assignable_v<T> && ::std::is_nothrow_copy_constructible_v<T>
               && ::std::is_nothrow_copy_assignable_v<E> && ::std::is_nothrow_copy_constructible_v<E>) // extension
    requires(::std::is_copy_assignable_v<T> && ::std::is_copy_constructible_v<T> && ::std::is_copy_assignable_v<E>
             && ::std::is_copy_constructible_v<E>
             && (::std::is_nothrow_move_constructible_v<T> || ::std::is_nothrow_move_constructible_v<E>)
             && (not ::std::is_trivially_copy_constructible_v<T> || not ::std::is_trivially_copy_assignable_v<T>
                 || not ::std::is_trivially_destructible_v<T> || not ::std::is_trivially_copy_constructible_v<E>
                 || not ::std::is_trivially_copy_assignable_v<E> || not ::std::is_trivially_destructible_v<E>))
  {
    this->_assign(static_cast<_base const &>(s));
    return *this;
  }

  constexpr expected &operator=(expected &&) // NOSONAR cpp:S5018 standard mandated `noexcept` spec.
      noexcept(::std::is_nothrow_move_assignable_v<T> && ::std::is_nothrow_move_constructible_v<T>
               && ::std::is_nothrow_move_assignable_v<E> && ::std::is_nothrow_move_constructible_v<E>) // required
    requires(::std::is_move_constructible_v<T> && ::std::is_move_assignable_v<T> && ::std::is_move_constructible_v<E>
             && ::std::is_move_assignable_v<E>
             && (::std::is_nothrow_move_constructible_v<T> || ::std::is_nothrow_move_constructible_v<E>)
             && ::std::is_trivially_move_constructible_v<T> && ::std::is_trivially_move_assignable_v<T>
             && ::std::is_trivially_destructible_v<T> && ::std::is_trivially_move_constructible_v<E>
             && ::std::is_trivially_move_assignable_v<E> && ::std::is_trivially_destructible_v<E>)
  = default;
  constexpr expected &operator=(expected &&s) // NOSONAR cpp:S5018 standard mandated `noexcept` spec.
      noexcept(::std::is_nothrow_move_assignable_v<T> && ::std::is_nothrow_move_constructible_v<T>
               && ::std::is_nothrow_move_assignable_v<E> && ::std::is_nothrow_move_constructible_v<E>) // required
    requires(::std::is_move_constructible_v<T> && ::std::is_move_assignable_v<T> && ::std::is_move_constructible_v<E>
             && ::std::is_move_assignable_v<E>
             && (::std::is_nothrow_move_constructible_v<T> || ::std::is_nothrow_move_constructible_v<E>)
             && (not ::std::is_trivially_move_constructible_v<T> || not ::std::is_trivially_move_assignable_v<T>
                 || not ::std::is_trivially_destructible_v<T> || not ::std::is_trivially_move_constructible_v<E>
                 || not ::std::is_trivially_move_assignable_v<E> || not ::std::is_trivially_destructible_v<E>))
  {
    this->_assign(static_cast<_base &&>(s));
    return *this;
  }

  // [expected.object.emplace], emplace inherited from _expected_base
  using _base::emplace;

  // [expected.object.swap], swap; body delegates to _expected_base helper
  constexpr void swap(expected &rhs) // NOSONAR cpp:S5018 standard mandated `noexcept` spec.
      noexcept(::std::is_nothrow_move_constructible_v<T> && ::std::is_nothrow_swappable_v<T>
               && ::std::is_nothrow_move_constructible_v<E> && ::std::is_nothrow_swappable_v<E>)
    requires(::std::is_swappable_v<T> && ::std::is_swappable_v<E> && ::std::is_move_constructible_v<T>
             && ::std::is_move_constructible_v<E>
             && (::std::is_nothrow_move_constructible_v<T> || ::std::is_nothrow_move_constructible_v<E>))
  {
    this->_swap_with(rhs);
  }

  // [expected.object.obs], observers inherited from _expected_base
  using _base::operator*;
  using _base::operator->;
  using _base::operator bool;
  using _base::error;
  using _base::error_or;
  using _base::has_error;
  using _base::has_value;
  using _base::value;
  using _base::value_or;

  // [expected.object.monadic], monadic operations
  template <class F>
  constexpr auto and_then(F &&f) &                        //
      noexcept(noexcept(_base::_and_then(*this, FWD(f)))) // extension
      -> decltype(_base::_and_then(*this, FWD(f)))
  {
    return _base::_and_then(*this, FWD(f));
  }
  template <class F>
  constexpr auto and_then(F &&f) &&                                    //
      noexcept(noexcept(_base::_and_then(::std::move(*this), FWD(f)))) // extension
      -> decltype(_base::_and_then(::std::move(*this), FWD(f)))
  {
    return _base::_and_then(::std::move(*this), FWD(f));
  }
  template <class F>
  constexpr auto and_then(F &&f) const &                  //
      noexcept(noexcept(_base::_and_then(*this, FWD(f)))) // extension
      -> decltype(_base::_and_then(*this, FWD(f)))
  {
    return _base::_and_then(*this, FWD(f));
  }
  template <class F>
  constexpr auto and_then(F &&f) const &&                              //
      noexcept(noexcept(_base::_and_then(::std::move(*this), FWD(f)))) // extension
      -> decltype(_base::_and_then(::std::move(*this), FWD(f)))
  {
    return _base::_and_then(::std::move(*this), FWD(f));
  }

  template <class F>
  constexpr auto or_else(F &&f) &                        //
      noexcept(noexcept(_base::_or_else(*this, FWD(f)))) // extension
      -> decltype(_base::_or_else(*this, FWD(f)))
  {
    return _base::_or_else(*this, FWD(f));
  }
  template <class F>
  constexpr auto or_else(F &&f) &&                                    //
      noexcept(noexcept(_base::_or_else(::std::move(*this), FWD(f)))) // extension
      -> decltype(_base::_or_else(::std::move(*this), FWD(f)))
  {
    return _base::_or_else(::std::move(*this), FWD(f));
  }
  template <class F>
  constexpr auto or_else(F &&f) const &                  //
      noexcept(noexcept(_base::_or_else(*this, FWD(f)))) // extension
      -> decltype(_base::_or_else(*this, FWD(f)))
  {
    return _base::_or_else(*this, FWD(f));
  }
  template <class F>
  constexpr auto or_else(F &&f) const &&                              //
      noexcept(noexcept(_base::_or_else(::std::move(*this), FWD(f)))) // extension
      -> decltype(_base::_or_else(::std::move(*this), FWD(f)))
  {
    return _base::_or_else(::std::move(*this), FWD(f));
  }

  template <class F>
  constexpr auto transform(F &&f) &                        //
      noexcept(noexcept(_base::_transform(*this, FWD(f)))) // extension
      -> decltype(_base::_transform(*this, FWD(f)))
  {
    return _base::_transform(*this, FWD(f));
  }
  template <class F>
  constexpr auto transform(F &&f) &&                                    //
      noexcept(noexcept(_base::_transform(::std::move(*this), FWD(f)))) // extension
      -> decltype(_base::_transform(::std::move(*this), FWD(f)))
  {
    return _base::_transform(::std::move(*this), FWD(f));
  }
  template <class F>
  constexpr auto transform(F &&f) const &                  //
      noexcept(noexcept(_base::_transform(*this, FWD(f)))) // extension
      -> decltype(_base::_transform(*this, FWD(f)))
  {
    return _base::_transform(*this, FWD(f));
  }
  template <class F>
  constexpr auto transform(F &&f) const &&                              //
      noexcept(noexcept(_base::_transform(::std::move(*this), FWD(f)))) // extension
      -> decltype(_base::_transform(::std::move(*this), FWD(f)))
  {
    return _base::_transform(::std::move(*this), FWD(f));
  }

  template <class F>
  constexpr auto transform_error(F &&f) &                        //
      noexcept(noexcept(_base::_transform_error(*this, FWD(f)))) // extension
      -> decltype(_base::_transform_error(*this, FWD(f)))
  {
    return _base::_transform_error(*this, FWD(f));
  }
  template <class F>
  constexpr auto transform_error(F &&f) &&                                    //
      noexcept(noexcept(_base::_transform_error(::std::move(*this), FWD(f)))) // extension
      -> decltype(_base::_transform_error(::std::move(*this), FWD(f)))
  {
    return _base::_transform_error(::std::move(*this), FWD(f));
  }
  template <class F>
  constexpr auto transform_error(F &&f) const &                  //
      noexcept(noexcept(_base::_transform_error(*this, FWD(f)))) // extension
      -> decltype(_base::_transform_error(*this, FWD(f)))
  {
    return _base::_transform_error(*this, FWD(f));
  }
  template <class F>
  constexpr auto transform_error(F &&f) const &&                              //
      noexcept(noexcept(_base::_transform_error(::std::move(*this), FWD(f)))) // extension
      -> decltype(_base::_transform_error(::std::move(*this), FWD(f)))
  {
    return _base::_transform_error(::std::move(*this), FWD(f));
  }

  // [expected.object.eq], equality operators are hidden friends of _expected_base,
  // found via ADL (associated classes include the private base).

private:
  // Direct-non-list-initializes the value (in_place) or error (unexpect) member from the result
  // of std::invoke; used by monadic functions implemented in _expected_base.
  template <class Tag, class Fn, class... Args>
  constexpr explicit expected(detail::_expected_from_invoke_t tag, Tag which, Fn &&fn, Args &&...args) //
      noexcept(::std::is_nothrow_constructible_v<_base, detail::_expected_from_invoke_t, Tag, Fn, Args...>)
      : _base(tag, which, FWD(fn), FWD(args)...)
  {
  }
};

/**
 * @brief The `std::expected` partial specialization for `void` success: a computation yielding
 *        either nothing (success) or an error `E`
 *
 * Members are as [expected.void] specifies them; the `noexcept` and assertion deviations listed
 * on the primary template apply here equally.
 *
 *
 * Its members are the standard's, and specified where
 * the reference page for this entity points.
 * @tparam E Type of the error value
 */
template <class E> class expected<void, E> : private detail::_expected_base<void, E, detail::expected_policy> {
  static_assert(detail::_is_valid_unexpected<E>);
  using _base = detail::_expected_base<void, E, detail::expected_policy>;

  // Allow sibling `_expected_base` instantiations to downcast into our private base
  // (needed for the lifted converting ctors and friend operators) and to call the
  // private from-invoke ctor below.
  template <class, class, class> friend struct detail::_expected_base;

public:
  using value_type = void;
  using error_type = E;
  using unexpected_type = unexpected<E>;

  template <class U> using rebind = expected<U, error_type>;

  // [expected.void.cons], constructors. Not `using _base::_base;` to avoid a clang-16 bug.
  constexpr expected() noexcept : _base(::std::in_place) {}

  template <class U, class G>
  constexpr explicit(not ::std::is_convertible_v<G const &, E>) expected(expected<U, G> const &s) //
      noexcept(::std::is_nothrow_constructible_v<E, G const &>)                                   // extension
    requires(_base::template _can_copy_convert<U, G>::value)
      : _base(s)
  {
  }
  template <class U, class G>
  constexpr explicit(not ::std::is_convertible_v<G, E>) expected(expected<U, G> &&s) //
      noexcept(::std::is_nothrow_constructible_v<E, G>)                              // extension
    requires(_base::template _can_move_convert<U, G>::value)
      : _base(::std::move(s))
  {
  }
  template <class G>
  constexpr explicit(!::std::is_convertible_v<G const &, E>) expected(unexpected<G> const &g) //
      noexcept(::std::is_nothrow_constructible_v<E, G const &>)                               // extension
    requires(::std::is_constructible_v<E, G const &>)
      : _base(unexpect, ::std::forward<G const &>(g.error())) // NOSONAR cpp:S6031 forward<GF> per the standard
  {
  }
  template <class G>
  constexpr explicit(!::std::is_convertible_v<G, E>) expected(unexpected<G> &&g) //
      noexcept(::std::is_nothrow_constructible_v<E, G>)                          // extension
    requires(::std::is_constructible_v<E, G>)
      : _base(unexpect, ::std::forward<G>(g.error()))
  {
  }

  constexpr explicit expected(::std::in_place_t) noexcept : _base(::std::in_place) {}

  template <class... Args>
  constexpr explicit expected(unexpect_t, Args &&...a)        //
      noexcept(::std::is_nothrow_constructible_v<E, Args...>) // extension
    requires ::std::is_constructible_v<E, Args...>
      : _base(unexpect, FWD(a)...)
  {
  }
  template <class U, class... Args>
  constexpr explicit expected(unexpect_t, ::std::initializer_list<U> il, Args &&...a)       //
      noexcept(::std::is_nothrow_constructible_v<E, ::std::initializer_list<U> &, Args...>) // extension
    requires ::std::is_constructible_v<E, ::std::initializer_list<U> &, Args...>
      : _base(unexpect, il, FWD(a)...)
  {
  }

  constexpr expected(expected const &) = delete;
  constexpr expected(expected const &)                                                         //
    requires(::std::is_copy_constructible_v<E> && ::std::is_trivially_copy_constructible_v<E>) //
  = default;
  constexpr expected(expected const &s)                                                            //
      noexcept(::std::is_nothrow_copy_constructible_v<E>)                                          // extension
    requires(::std::is_copy_constructible_v<E> && not ::std::is_trivially_copy_constructible_v<E>) //
      : _base(s.set_, FWD(s).storage_)
  {
  }
  constexpr expected(expected &&s) noexcept                                                    //
    requires(::std::is_move_constructible_v<E> && ::std::is_trivially_move_constructible_v<E>) //
  = default;
  constexpr expected(expected &&s)                        //
      noexcept(::std::is_nothrow_move_constructible_v<E>) // required
    requires(::std::is_move_constructible_v<E> && not ::std::is_trivially_move_constructible_v<E>)
      : _base(s.set_, FWD(s).storage_)
  {
  }

  // [expected.void.dtor]
  constexpr ~expected() = default;

  // [expected.void.assign], assignment. Not `using _base::operator=;` to avoid an MSVC bug.
  template <class G>
  constexpr expected &operator=(unexpected<G> const &s) //
      noexcept(::std::is_nothrow_assignable_v<E &, G const &>
               && ::std::is_nothrow_constructible_v<E, G const &>) // extension
    requires(::std::is_constructible_v<E, G const &> && ::std::is_assignable_v<E &, G const &>)
  {
    this->_assign_unexpected(s);
    return *this;
  }
  template <class G>
  constexpr expected &operator=(unexpected<G> &&s)                                                //
      noexcept(::std::is_nothrow_assignable_v<E &, G> && ::std::is_nothrow_constructible_v<E, G>) // extension
    requires(::std::is_constructible_v<E, G> && ::std::is_assignable_v<E &, G>)
  {
    this->_assign_unexpected(::std::move(s));
    return *this;
  }

  constexpr expected &operator=(expected const &) = delete;
  constexpr expected &operator=(expected const &)                                                   //
      noexcept(::std::is_nothrow_copy_assignable_v<E> && ::std::is_nothrow_copy_constructible_v<E>) // extension
    requires(::std::is_copy_assignable_v<E> && ::std::is_copy_constructible_v<E>
             && ::std::is_trivially_copy_constructible_v<E> && ::std::is_trivially_copy_assignable_v<E>
             && ::std::is_trivially_destructible_v<E>)
  = default;
  constexpr expected &operator=(expected const &s)                                                  //
      noexcept(::std::is_nothrow_copy_assignable_v<E> && ::std::is_nothrow_copy_constructible_v<E>) // extension
    requires(::std::is_copy_assignable_v<E> && ::std::is_copy_constructible_v<E>
             && (not ::std::is_trivially_copy_constructible_v<E> || not ::std::is_trivially_copy_assignable_v<E>
                 || not ::std::is_trivially_destructible_v<E>))
  {
    this->_assign(static_cast<_base const &>(s));
    return *this;
  }

  constexpr expected &operator=(expected &&) // NOSONAR cpp:S5018 standard mandated `noexcept` spec.
      noexcept(::std::is_nothrow_move_assignable_v<E> && ::std::is_nothrow_move_constructible_v<E>) // required
    requires(::std::is_move_constructible_v<E> && ::std::is_move_assignable_v<E>
             && ::std::is_trivially_move_constructible_v<E> && ::std::is_trivially_move_assignable_v<E>
             && ::std::is_trivially_destructible_v<E>)
  = default;
  constexpr expected &operator=(expected &&s) // NOSONAR cpp:S5018 standard mandated `noexcept` spec.
      noexcept(::std::is_nothrow_move_assignable_v<E> && ::std::is_nothrow_move_constructible_v<E>) // required
    requires(::std::is_move_constructible_v<E> && ::std::is_move_assignable_v<E>
             && (not ::std::is_trivially_move_constructible_v<E> || not ::std::is_trivially_move_assignable_v<E>
                 || not ::std::is_trivially_destructible_v<E>))
  {
    this->_assign(static_cast<_base &&>(s));
    return *this;
  }

  // [expected.void.emplace], emplace inherited from _expected_base
  using _base::emplace;

  // [expected.void.swap], swap; body delegates to _expected_base helper
  constexpr void swap(expected &rhs) // NOSONAR cpp:S5018 standard mandated `noexcept` spec.
      noexcept(::std::is_nothrow_move_constructible_v<E> && ::std::is_nothrow_swappable_v<E>)
    requires(::std::is_swappable_v<E> && ::std::is_move_constructible_v<E>)
  {
    this->_swap_with(rhs);
  }

  // [expected.void.obs], observers inherited from _expected_base
  using _base::operator*;
  using _base::operator bool;
  using _base::error;
  using _base::error_or;
  using _base::has_error;
  using _base::has_value;
  using _base::value;

  // [expected.void.monadic], monadic operations
  template <class F>
  constexpr auto and_then(F &&f) &                        //
      noexcept(noexcept(_base::_and_then(*this, FWD(f)))) // extension
      -> decltype(_base::_and_then(*this, FWD(f)))
  {
    return _base::_and_then(*this, FWD(f));
  }
  template <class F>
  constexpr auto and_then(F &&f) &&                                    //
      noexcept(noexcept(_base::_and_then(::std::move(*this), FWD(f)))) // extension
      -> decltype(_base::_and_then(::std::move(*this), FWD(f)))
  {
    return _base::_and_then(::std::move(*this), FWD(f));
  }
  template <class F>
  constexpr auto and_then(F &&f) const &                  //
      noexcept(noexcept(_base::_and_then(*this, FWD(f)))) // extension
      -> decltype(_base::_and_then(*this, FWD(f)))
  {
    return _base::_and_then(*this, FWD(f));
  }
  template <class F>
  constexpr auto and_then(F &&f) const &&                              //
      noexcept(noexcept(_base::_and_then(::std::move(*this), FWD(f)))) // extension
      -> decltype(_base::_and_then(::std::move(*this), FWD(f)))
  {
    return _base::_and_then(::std::move(*this), FWD(f));
  }

  template <class F>
  constexpr auto or_else(F &&f) &                        //
      noexcept(noexcept(_base::_or_else(*this, FWD(f)))) // extension
      -> decltype(_base::_or_else(*this, FWD(f)))
  {
    return _base::_or_else(*this, FWD(f));
  }
  template <class F>
  constexpr auto or_else(F &&f) &&                                    //
      noexcept(noexcept(_base::_or_else(::std::move(*this), FWD(f)))) // extension
      -> decltype(_base::_or_else(::std::move(*this), FWD(f)))
  {
    return _base::_or_else(::std::move(*this), FWD(f));
  }
  template <class F>
  constexpr auto or_else(F &&f) const &                  //
      noexcept(noexcept(_base::_or_else(*this, FWD(f)))) // extension
      -> decltype(_base::_or_else(*this, FWD(f)))
  {
    return _base::_or_else(*this, FWD(f));
  }
  template <class F>
  constexpr auto or_else(F &&f) const &&                              //
      noexcept(noexcept(_base::_or_else(::std::move(*this), FWD(f)))) // extension
      -> decltype(_base::_or_else(::std::move(*this), FWD(f)))
  {
    return _base::_or_else(::std::move(*this), FWD(f));
  }

  template <class F>
  constexpr auto transform(F &&f) &                        //
      noexcept(noexcept(_base::_transform(*this, FWD(f)))) // extension
      -> decltype(_base::_transform(*this, FWD(f)))
  {
    return _base::_transform(*this, FWD(f));
  }
  template <class F>
  constexpr auto transform(F &&f) &&                                    //
      noexcept(noexcept(_base::_transform(::std::move(*this), FWD(f)))) // extension
      -> decltype(_base::_transform(::std::move(*this), FWD(f)))
  {
    return _base::_transform(::std::move(*this), FWD(f));
  }
  template <class F>
  constexpr auto transform(F &&f) const &                  //
      noexcept(noexcept(_base::_transform(*this, FWD(f)))) // extension
      -> decltype(_base::_transform(*this, FWD(f)))
  {
    return _base::_transform(*this, FWD(f));
  }
  template <class F>
  constexpr auto transform(F &&f) const &&                              //
      noexcept(noexcept(_base::_transform(::std::move(*this), FWD(f)))) // extension
      -> decltype(_base::_transform(::std::move(*this), FWD(f)))
  {
    return _base::_transform(::std::move(*this), FWD(f));
  }

  template <class F>
  constexpr auto transform_error(F &&f) &                        //
      noexcept(noexcept(_base::_transform_error(*this, FWD(f)))) // extension
      -> decltype(_base::_transform_error(*this, FWD(f)))
  {
    return _base::_transform_error(*this, FWD(f));
  }
  template <class F>
  constexpr auto transform_error(F &&f) &&                                    //
      noexcept(noexcept(_base::_transform_error(::std::move(*this), FWD(f)))) // extension
      -> decltype(_base::_transform_error(::std::move(*this), FWD(f)))
  {
    return _base::_transform_error(::std::move(*this), FWD(f));
  }
  template <class F>
  constexpr auto transform_error(F &&f) const &                  //
      noexcept(noexcept(_base::_transform_error(*this, FWD(f)))) // extension
      -> decltype(_base::_transform_error(*this, FWD(f)))
  {
    return _base::_transform_error(*this, FWD(f));
  }
  template <class F>
  constexpr auto transform_error(F &&f) const &&                              //
      noexcept(noexcept(_base::_transform_error(::std::move(*this), FWD(f)))) // extension
      -> decltype(_base::_transform_error(::std::move(*this), FWD(f)))
  {
    return _base::_transform_error(::std::move(*this), FWD(f));
  }

  // [expected.void.eq], equality operators are hidden friends of _expected_base,
  // found via ADL (associated classes include the private base).

private:
  // Direct-non-list-initializes the error member from the result of std::invoke; used by
  // transform_error implemented in _expected_base.
  template <class Tag, class Fn, class... Args>
  constexpr explicit expected(detail::_expected_from_invoke_t tag, Tag which, Fn &&fn, Args &&...args) //
      noexcept(::std::is_nothrow_constructible_v<_base, detail::_expected_from_invoke_t, Tag, Fn, Args...>)
      : _base(tag, which, FWD(fn), FWD(args)...)
  {
  }
};

/**
 * @brief Compares an `expected` against a value ([expected.object.eq]): true when `x` holds a
 *        value equal to `v`
 *
 * Deviation: declared at namespace scope, where the standard specifies a hidden friend - the
 * spelling that keeps its constraint on the other operand deducible and non-self-referential.
 */
// [expected.object.eq], the comparison against a value. Alone among the equality operators this one
// constrains itself on the OTHER operand, which is safe only where its own operand is deduced - so
// it cannot be a hidden friend of `_expected_base`, whose only spelling for that operand is
// `Policy::type<T, E>`, a non-deduced context. Deduction would then reject nothing, the constraint
// would be evaluated for every left operand there is, and where that operand reaches this operator
// by ADL - a function pointer returning this expected, or a class template over one - satisfaction
// would depend on itself, which is a hard error rather than an answer.
template <class T, class E, class T2>
  requires(not ::std::is_void_v<T> && not detail::_is_some_expected<T2>)
constexpr bool operator==(expected<T, E> const &x, T2 const &v) //
    noexcept(noexcept(detail::_implicit_to_bool(*x == v)))      // extension
  requires requires {
    { *x == v } -> ::std::convertible_to<bool>;
  }
{
  if (!x.has_value())
    return false;
  return *x == v;
}

} // namespace LIBFN_VERSION_BASE
} // namespace pfn

#undef ASSERT

#ifdef INCLUDE_PFN_EXPECTED__POP_ASSERT
#pragma pop_macro("ASSERT")
#endif

#undef FWD

#ifdef INCLUDE_PFN_EXPECTED__POP_FWD
#pragma pop_macro("FWD")
#endif

#endif // INCLUDE_PFN_EXPECTED
// ---------- END pfn/expected.hpp ----------

// ---------- RESUME fn/expected.hpp ----------

// ---------- RESUME fn/expected.hpp ----------

// ---------- RESUME fn/expected.hpp ----------

// ---------- RESUME fn/expected.hpp ----------

// ---------- RESUME fn/expected.hpp ----------

// ---------- RESUME fn/expected.hpp ----------

// ---------- BEGIN fn/detail/macro_begin.hpp ----------
// Deliberately no include guard: this header and fn/detail/macro_end.hpp bracket the section of a
// header that uses the macros below; push_macro/pop_macro make the bracketing safe under nesting
// and preserve any prior user definition.

#pragma push_macro("FWD")
#undef FWD // NOSONAR cpp:S959 saved by push_macro above

// This FWD macro is a functional equivalent to std::forward<decltype(v)>(v),
// but it saves compilation time (and typing) when used frequently.
#define FWD(...) static_cast<decltype(__VA_ARGS__) &&>(__VA_ARGS__)

#pragma push_macro("DEDUCED_RETURN")
#undef DEDUCED_RETURN // NOSONAR cpp:S959 saved by push_macro above

// Spell a function's deduced return type explicitly on MSVC only. MSVC mis-resolves a deduced
// (`auto`/`decltype(auto)`) return whose type derives from a body-local alias, leaking it as an
// opaque dependent type; an explicit trailing return type is the fix. Every other compiler keeps
// `decltype(auto)` — the natural spelling — which by construction deduces `decltype(EXPR)` on
// `return EXPR;`, so the two are the same type and this is a no-op off MSVC.
//
// Confining `decltype(EXPR)` to MSVC also keeps it off clang <= 20, which in C++23 substitutes a
// non-viable constrained overload's trailing return type BEFORE its requires-clause rejects it
// (fixed clang 21), so the explicit form would fail to compile instead of removing the non-viable
// function from the overload set.
#ifndef _MSC_VER
#define DEDUCED_RETURN(...) decltype(auto)
#else
#define DEDUCED_RETURN(...) decltype(__VA_ARGS__)
#endif
// ---------- END fn/detail/macro_begin.hpp ----------

// ---------- RESUME fn/expected.hpp ----------

namespace fn {
inline namespace LIBFN_VERSION {

// Bring the C++23 polyfill primitives into `fn` namespace, for consistent type naming.
using ::pfn::bad_expected_access;
using ::pfn::unexpect;
using ::pfn::unexpect_t;
using ::pfn::unexpected;

/**
 * @brief Checks if a type is an `fn::expected` (with any sides)
 *
 * @tparam T Type to check, possibly cv-ref qualified
 */
template <typename T>
concept some_expected = detail::_some_expected<T>;

/**
 * @brief Checks if a type is an `fn::expected` with a non-void value type
 *
 * @tparam T Type to check, possibly cv-ref qualified
 */
template <typename T>
concept some_expected_non_void = //
    some_expected<T>             //
    && !::std::is_same_v<void, typename ::std::remove_cvref_t<T>::value_type>;

/**
 * @brief Checks if a type is an `fn::expected` over `void`
 *
 * @tparam T Type to check, possibly cv-ref qualified
 */
template <typename T>
concept some_expected_void = //
    some_expected<T>         //
    && ::std::is_same_v<void, typename ::std::remove_cvref_t<T>::value_type>;

namespace detail {

struct expected_policy {
  template <class U, class G> using type = ::fn::expected<U, G>;
  template <class X> static constexpr bool is_specialization = _is_some_expected<X &>;
};

// Exposition-only probes for the noexcept specs below: the value/error type of an
// fn::expected, or a never-matching incomplete tag when X is not one.
struct _never_t;
template <typename X> struct _expected_types {
  using value_type = _never_t;
  using error_type = _never_t;
};
template <typename U, typename G> struct _expected_types<::fn::expected<U, G>> {
  using value_type = U;
  using error_type = G;
};

// A copack<> side is unconstructible, so an expected carrying one can never hold it: every arm that
// relocates such a side - self's or a callback result's, value or error - is unreachable, and what
// cannot run cannot throw. Keyed on the relocated side's type; the sibling arms still weigh.
template <typename From, typename Type, typename... Args>
constexpr inline bool _nothrow_arm = _nothrow_initializable<Type, Args...>;
template <typename From, typename Type, typename... Args>
  requires empty_copack<From>
constexpr inline bool _nothrow_arm<From, Type, Args...> = true;

// Carrying the callback's value across into a widened result. An expected<void, ...> has no value to
// carry, and `declval<void>()` is not a thing to ask about; an empty-copack value can never exist to be
// carried, so that arm is unreachable (as in _nothrow_arm).
template <typename Type, typename Src>
constexpr inline bool _nothrow_carry_value
    = _nothrow_initializable<Type, ::std::in_place_t, decltype(::std::declval<Src>().value())>;
template <typename Type, typename Src>
  requires ::std::is_void_v<typename ::std::remove_cvref_t<Src>::value_type>
constexpr inline bool _nothrow_carry_value<Type, Src> = _nothrow_initializable<Type, ::std::in_place_t>;
template <typename Type, typename Src>
  requires empty_copack<typename ::std::remove_cvref_t<Src>::value_type>
constexpr inline bool _nothrow_carry_value<Type, Src> = true;

// `and_then` and `or_else` each have two arms - the callback's own expected is returned, or the two
// error (value) types are widened into a copack - and `if constexpr` picks between them. A
// noexcept-specifier is an ordinary constant expression and cannot pick: the untaken arm's spelling
// would have to be well-formed too. Hence a trait, whose constrained specializations mirror the
// body's arms. Both lead with `_is_some_expected`, so a callback returning something else leaves the
// unconstrained primary to answer, and the body's static_assert to diagnose - a specification must
// not pre-empt that with a hard error.
// The dispatch result of a graded bind: a plain side answers through _apply_result as always; a
// copack side goes through the graded join - select for a convergent set (today's behaviour and
// diagnostics verbatim), the joined expected for a heterogeneous all-expected one, absent for an
// invalid one - so the members and the traits below key on ONE answer and never instantiate the
// select assert for a shape the join owns.
template <typename E, typename Fn, typename... V> struct _and_then_dispatch : _apply_result<Fn, V...> {};
template <typename E, typename Fn, typename V>
  requires _some_copack<::std::remove_cvref_t<V>>
struct _and_then_dispatch<E, Fn, V> : _copack_apply_result<_joining_expected_tag<::fn::expected, E>, Fn, V> {};

template <typename T, typename Fn, typename ErrArg> struct _or_else_dispatch : _apply_result<Fn, ErrArg> {};
template <typename T, typename Fn, typename ErrArg>
  requires _some_copack<::std::remove_cvref_t<ErrArg>>
struct _or_else_dispatch<T, Fn, ErrArg> : _copack_apply_result<_joining_recovery_tag<::fn::expected, T>, Fn, ErrArg> {};

template <typename E, typename Fn, typename ErrArg, typename... ValArg> struct _nothrow_and_then : ::std::false_type {};

template <typename E, typename Fn, typename ErrArg, typename... ValArg>
  requires(not _is_hetero_join<_and_then_dispatch<E, Fn, ValArg...>>)
          && _is_some_expected<::std::remove_cvref_t<typename _and_then_dispatch<E, Fn, ValArg...>::type> &>
          && ::std::is_same_v<typename _expected_types<::std::remove_cvref_t<
                                  typename _and_then_dispatch<E, Fn, ValArg...>::type>>::error_type,
                              E>
struct _nothrow_and_then<E, Fn, ErrArg, ValArg...>
    : ::std::bool_constant<_is_nothrow_applicable<Fn, ValArg...>::value // the callback
                               && ::std::is_nothrow_constructible_v<
                                   ::std::remove_cvref_t<typename _and_then_dispatch<E, Fn, ValArg...>::type>,
                                   ::fn::unexpect_t, ErrArg>> {}; // lifting self's error

template <typename E, typename Fn, typename ErrArg, typename... ValArg>
  requires(not _is_hetero_join<_and_then_dispatch<E, Fn, ValArg...>>)
          && _is_some_expected<::std::remove_cvref_t<typename _and_then_dispatch<E, Fn, ValArg...>::type> &>
          && (not ::std::is_same_v<typename _expected_types<::std::remove_cvref_t<
                                       typename _and_then_dispatch<E, Fn, ValArg...>::type>>::error_type,
                                   E>)
struct _nothrow_and_then<E, Fn, ErrArg, ValArg...> {
  using type = ::std::remove_cvref_t<typename _and_then_dispatch<E, Fn, ValArg...>::type>;
  using new_type = ::fn::expected<typename type::value_type, copack_for<E, typename type::error_type>>;

  static constexpr bool value                        //
      = _is_nothrow_applicable<Fn, ValArg...>::value // the callback
        && _nothrow_carry_value<new_type, type>      // carrying its value across
        && _nothrow_arm<typename type::error_type, new_type, ::fn::unexpect_t,
                        decltype(::std::declval<type>().error())> // widening its error
        && _nothrow_arm<E, new_type, ::fn::unexpect_t, ErrArg>;   // widening self's error
};

// the heterogeneous join: each branch and its conversion into the announced result are weighed by
// the rts trait; widening self's error is the one other reachable construction, dead for copack<>
template <typename E, typename Fn, typename ErrArg, typename... ValArg>
  requires _is_hetero_join<_and_then_dispatch<E, Fn, ValArg...>>
struct _nothrow_and_then<E, Fn, ErrArg, ValArg...> {
  using type = typename _and_then_dispatch<E, Fn, ValArg...>::type;

  static constexpr bool value
      = _is_nothrow_rts_applicable<type, Fn, ValArg...>
        && (empty_copack<E> || ::std::is_nothrow_constructible_v<type, ::fn::unexpect_t, ErrArg>);
};

// or_else's arms, mirrored the same way. ValArg is the type of self's value as the body relocates it
// (spelled through apply_const_lvalue_t by the caller, since for a void T there is no value to name).
template <typename T, typename Fn, typename ErrArg, typename ValArg> struct _nothrow_or_else : ::std::false_type {};

template <typename T, typename Fn, typename ErrArg, typename ValArg>
  requires(not _is_hetero_join<_or_else_dispatch<T, Fn, ErrArg>>)
          && _is_some_expected<::std::remove_cvref_t<typename _or_else_dispatch<T, Fn, ErrArg>::type> &>
          && ::std::is_same_v<typename _expected_types<
                                  ::std::remove_cvref_t<typename _or_else_dispatch<T, Fn, ErrArg>::type>>::value_type,
                              T>
struct _nothrow_or_else<T, Fn, ErrArg, ValArg>
    : ::std::bool_constant<
          _is_nothrow_applicable<Fn, ErrArg>::value // the callback
          && (::std::is_void_v<T>
              || _nothrow_initializable<::std::remove_cvref_t<typename _or_else_dispatch<T, Fn, ErrArg>::type>,
                                        ::std::in_place_t, ValArg>)> {}; // carrying self's value

template <typename T, typename Fn, typename ErrArg, typename ValArg>
  requires(not _is_hetero_join<_or_else_dispatch<T, Fn, ErrArg>>)
          && _is_some_expected<::std::remove_cvref_t<typename _or_else_dispatch<T, Fn, ErrArg>::type> &>
          && (not ::std::is_same_v<typename _expected_types<::std::remove_cvref_t<
                                       typename _or_else_dispatch<T, Fn, ErrArg>::type>>::value_type,
                                   T>)
struct _nothrow_or_else<T, Fn, ErrArg, ValArg> {
  using type = ::std::remove_cvref_t<typename _or_else_dispatch<T, Fn, ErrArg>::type>;
  using new_type = ::fn::expected<copack_for<T, typename type::value_type>, typename type::error_type>;

  static constexpr bool value                                   //
      = _is_nothrow_applicable<Fn, ErrArg>::value               // the callback
        && _nothrow_arm<T, new_type, ::std::in_place_t, ValArg> // widening self's value
        && _nothrow_carry_value<new_type, type>                 // widening its value
        && _nothrow_initializable<new_type, ::fn::unexpect_t,
                                  decltype(::std::declval<type>().error())>; // carrying its error
};

// the heterogeneous join, mirrored: the branches and their conversions through the rts trait;
// carrying self's value into the announced result is the other reachable construction
template <typename T, typename Fn, typename ErrArg, typename ValArg>
  requires _is_hetero_join<_or_else_dispatch<T, Fn, ErrArg>>
struct _nothrow_or_else<T, Fn, ErrArg, ValArg> {
  using type = typename _or_else_dispatch<T, Fn, ErrArg>::type;

  static constexpr bool value
      = _is_nothrow_rts_applicable<type, Fn, ErrArg>
        && (::std::is_void_v<T> || empty_copack<T> || _nothrow_initializable<type, ::std::in_place_t, ValArg>);
};

// Storage layer for ::fn::expected. Inherits the standard-conformant base from
// pfn, then hides the four monadic static helpers with copack-widening variants
// that materialise their result via `expected_policy::template type<U, G>`.
// The transform/transform_error helpers hand pfn's _expected_from_invoke constructors a
// zero-argument thunk, so the result's member is direct-non-list-initialized from fn's own
// _apply (or copack::transform) result: no extra move, and immovable result types work.
// The statics carry the same extension noexcept as pfn's, computed through fn's own machinery: the
// callback of a copack/pack dispatch is invoked through `_apply`, not called directly, so it is
// `_is_nothrow_applicable` - not the std trait, which is false for a callable that is not directly
// applicable on a copack or a pack - that answers for it, and the widening arms are weighed by the
// traits above.
template <typename T, typename E> struct _expected_base : ::pfn::detail::_expected_base<T, E, expected_policy> {
  using _pfn_base = ::pfn::detail::_expected_base<T, E, expected_policy>;
  using _pfn_base::_pfn_base;

  // and_then, non-void value type
  template <typename Self, typename Fn>
  static constexpr auto _and_then(Self &&self, Fn &&fn) //
      noexcept(::fn::detail::_nothrow_and_then<E, Fn, decltype(_pfn_base::_error(FWD(self))),
                                               decltype(_pfn_base::_value(FWD(self)))>::value) // extension
    requires(not ::std::is_void_v<T>) && (not empty_copack<T>)
            && ::fn::detail::_bind_applicable<Fn, decltype(_pfn_base::_value(FWD(self)))>
            && ::std::is_constructible_v<E, decltype(_pfn_base::_error(FWD(self)))> && requires {
                 typename ::fn::detail::_and_then_dispatch<E, Fn, decltype(_pfn_base::_value(FWD(self)))>::type;
               }
  {
    using dispatch = ::fn::detail::_and_then_dispatch<E, Fn, decltype(_pfn_base::_value(FWD(self)))>;
    using type = typename dispatch::type;
    if constexpr (::fn::detail::_is_hetero_join<dispatch>) {
      // heterogeneous expected branches: the join announced `type`, every branch converts into it
      // as it returns, and the error path widens self's grade the same way
      if (self.has_value())
        return ::fn::detail::_tagged_join_apply<::fn::detail::_joining_expected_tag<::fn::expected, E>>(
            _pfn_base::_value(FWD(self)), FWD(fn));
      else {
        if constexpr (not empty_copack<E>)
          return type(::fn::unexpect, _pfn_base::_error(FWD(self)));
        else
          ::pfn::unreachable(); // LCOV_EXCL_LINE
      }
    } else {
      static_assert(_is_some_expected<type &>);
      static_assert(::std::is_same_v<typename type::error_type, E> || some_copack<E>
                    || ::std::is_same_v<typename type::error_type, ::fn::copack<E>>);
      if constexpr (::std::is_same_v<typename type::error_type, E>) {
        if (self.has_value())
          return ::fn::detail::_apply(FWD(fn), _pfn_base::_value(FWD(self)));
        else
          return type(::fn::unexpect, _pfn_base::_error(FWD(self)));
      } else {
        using new_error_type = copack_for<E, typename type::error_type>;
        using new_type = ::fn::expected<typename type::value_type, new_error_type>;
        if (self.has_value()) {
          auto t = ::fn::detail::_apply(FWD(fn), _pfn_base::_value(FWD(self)));
          if (t.has_value())
            if constexpr (not ::std::is_void_v<typename new_type::value_type>)
              return new_type{::std::in_place, ::std::move(t).value()};
            else
              return new_type{::std::in_place};
          else {
            if constexpr (not empty_copack<typename type::error_type>)
              return new_type{::fn::unexpect, ::std::move(t).error()};
            else
              ::pfn::unreachable(); // LCOV_EXCL_LINE
          }
        } else {
          if constexpr (not empty_copack<E>)
            return new_type(::fn::unexpect, _pfn_base::_error(FWD(self)));
          else
            ::pfn::unreachable(); // LCOV_EXCL_LINE
        }
      }
    }
  }

  // and_then, void value type
  template <typename Self, typename Fn>
  static constexpr auto _and_then(Self &&self, Fn &&fn)                                               //
      noexcept(::fn::detail::_nothrow_and_then<E, Fn, decltype(_pfn_base::_error(FWD(self)))>::value) // extension
    requires(::std::is_void_v<T>) && ::fn::detail::_is_applicable<Fn>::value
            && ::std::is_constructible_v<E, decltype(_pfn_base::_error(FWD(self)))>
  {
    using type = typename ::fn::detail::_apply_result<Fn>::type;
    static_assert(_is_some_expected<type &>);
    static_assert(::std::is_same_v<typename type::error_type, E> || some_copack<E>
                  || ::std::is_same_v<typename type::error_type, ::fn::copack<E>>);
    if constexpr (::std::is_same_v<typename type::error_type, E>) {
      if (self.has_value())
        return ::fn::detail::_apply(FWD(fn));
      else
        return type(::fn::unexpect, _pfn_base::_error(FWD(self)));
    } else {
      using new_error_type = copack_for<E, typename type::error_type>;
      using new_type = ::fn::expected<typename type::value_type, new_error_type>;
      if (self.has_value()) {
        auto t = ::fn::detail::_apply(FWD(fn));
        if (t.has_value())
          if constexpr (not ::std::is_void_v<typename new_type::value_type>)
            return new_type{::std::in_place, ::std::move(t).value()};
          else
            return new_type{::std::in_place};
        else {
          if constexpr (not empty_copack<typename type::error_type>)
            return new_type{::fn::unexpect, ::std::move(t).error()};
          else
            ::pfn::unreachable(); // LCOV_EXCL_LINE
        }
      } else {
        if constexpr (not empty_copack<E>)
          return new_type(::fn::unexpect, _pfn_base::_error(FWD(self)));
        else
          ::pfn::unreachable(); // LCOV_EXCL_LINE
      }
    }
  }

  // and_then, value type is the empty copack: a value can never be constructed, so the callback can
  // never be presented one - it is left alone, not invoked and not even instantiated, and the
  // result is *this unchanged.
  template <typename Self, typename Fn>
  static constexpr auto _and_then(Self &&self, Fn &&)                         //
      noexcept(::std::is_nothrow_constructible_v<::fn::expected<T, E>, Self>) // extension
      -> ::fn::expected<T, E>
    requires empty_copack<T> && ::std::is_constructible_v<::fn::expected<T, E>, Self>
  {
    return FWD(self);
  }

  // or_else, covers both void and non-void value type. The value-copy conjunct spells the
  // _value(FWD(self)) category via apply_const_lvalue_t: unlike the requires clause below, a
  // noexcept operand is not constraint-checked, so the `is_void_v<T> ||` guard could not save
  // an ill-formed _value call (constrained away for void) from being a hard error.
  template <typename Self, typename Fn>
  static constexpr auto _or_else(Self &&self, Fn &&fn) //
      noexcept(::fn::detail::_nothrow_or_else<T, Fn, decltype(_pfn_base::_error(FWD(self))),
                                              ::fn::apply_const_lvalue_t<Self, typename _pfn_base::_value_t &&>>::value)
    requires(not empty_copack<E>) && ::fn::detail::_bind_applicable<Fn, decltype(_pfn_base::_error(FWD(self)))>
            && (::std::is_void_v<T> || ::std::is_constructible_v<T, decltype(_pfn_base::_value(FWD(self)))>)
            && requires {
                 typename ::fn::detail::_or_else_dispatch<T, Fn, decltype(_pfn_base::_error(FWD(self)))>::type;
               }
  {
    using dispatch = ::fn::detail::_or_else_dispatch<T, Fn, decltype(_pfn_base::_error(FWD(self)))>;
    using type = typename dispatch::type;
    if constexpr (::fn::detail::_is_hetero_join<dispatch>) {
      // heterogeneous expected branches: the join announced `type`; self's value widens into it on
      // the value path, and each branch converts into it as it returns on the error path
      if (self.has_value()) {
        if constexpr (::std::is_void_v<T>)
          return type{::std::in_place};
        else if constexpr (not empty_copack<T>)
          return type{::std::in_place, _pfn_base::_value(FWD(self))};
        else
          ::pfn::unreachable(); // LCOV_EXCL_LINE
      } else
        return ::fn::detail::_tagged_join_apply<::fn::detail::_joining_recovery_tag<::fn::expected, T>>(
            _pfn_base::_error(FWD(self)), FWD(fn));
    } else {
      static_assert(_is_some_expected<type &>);
      static_assert(::std::is_same_v<typename type::value_type, T> || some_copack<T>
                    || ::std::is_same_v<typename type::value_type, ::fn::copack<T>>);
      if constexpr (::std::is_same_v<typename type::value_type, T>) {
        if (self.has_value())
          if constexpr (not ::std::is_void_v<T>)
            return type(::std::in_place, _pfn_base::_value(FWD(self)));
          else {
            static_assert(::std::is_void_v<typename type::value_type>);
#if defined(__clang__) && __clang_major__ <= 18
            // clang 15-18 miscompile the prvalue return below for three of the four Self ref-qualifier
            // instantiations (&, const &, const &&) at -O1/-O2: the value-state result is observed with
            // set_ == false (storage-poison). The workaround dodges the buggy mandatory copy-elision,
            // at the cost of a move -- an immovable error type must keep the prvalue (the workaround
            // would not compile; the miscompile is not observed in that shape).
            if constexpr (::std::is_move_constructible_v<type>)
              return ::std::move(type{::std::in_place});
            else
              return type{::std::in_place};
#else
            return type{::std::in_place};
#endif
          }
        else
          return ::fn::detail::_apply(FWD(fn), _pfn_base::_error(FWD(self)));
      } else {
        static_assert(not ::std::is_void_v<typename type::value_type>);
        using new_value_type = copack_for<T, typename type::value_type>;
        using new_type = ::fn::expected<new_value_type, typename type::error_type>;
        if (self.has_value()) {
          if constexpr (not empty_copack<T>)
            return new_type{::std::in_place, _pfn_base::_value(FWD(self))};
          else
            ::pfn::unreachable(); // LCOV_EXCL_LINE
        } else {
          auto t = ::fn::detail::_apply(FWD(fn), _pfn_base::_error(FWD(self)));
          if (t.has_value()) {
            if constexpr (not empty_copack<typename type::value_type>)
              return new_type{::std::in_place, ::std::move(t).value()};
            else
              ::pfn::unreachable(); // LCOV_EXCL_LINE
          } else
            return new_type{::fn::unexpect, ::std::move(t).error()};
        }
      }
    }
  }

  // or_else, error type is the empty copack: an error can never be constructed, so the callback can
  // never be presented one - it is left alone, not invoked and not even instantiated, and the
  // result is *this unchanged.
  template <typename Self, typename Fn>
  static constexpr auto _or_else(Self &&self, Fn &&)                          //
      noexcept(::std::is_nothrow_constructible_v<::fn::expected<T, E>, Self>) // extension
      -> ::fn::expected<T, E>
    requires empty_copack<E> && ::std::is_constructible_v<::fn::expected<T, E>, Self>
  {
    return FWD(self);
  }

  // transform, non-void value type, not a copack. In the noexcept specs of the transform and
  // transform_error overloads, only the apply and copying the untouched side can throw: the
  // new value/error is direct-non-list-initialized from the thunk's result (guaranteed elision).
  template <typename Self, typename Fn>
  static constexpr auto _transform(Self &&self, Fn &&fn) //
      noexcept(::fn::detail::_is_nothrow_applicable<Fn, decltype(_pfn_base::_value(FWD(self)))>::value
               && ::std::is_nothrow_constructible_v<E, decltype(_pfn_base::_error(FWD(self)))>) // extension
    requires(not ::std::is_void_v<T>) && (not some_copack<T>)
            && ::fn::detail::_is_applicable_if<not some_copack<T>, Fn, decltype(_pfn_base::_value(FWD(self)))>::value
            && ::std::is_constructible_v<E, decltype(_pfn_base::_error(FWD(self)))>
  {
    using new_value_type = typename ::fn::detail::_apply_result<Fn, decltype(_pfn_base::_value(FWD(self)))>::type;
    using type = ::fn::expected<new_value_type, E>;
    if (self.has_value())
      if constexpr (::std::is_void_v<new_value_type>) {
        ::fn::detail::_apply(FWD(fn), _pfn_base::_value(FWD(self)));
        return type();
      } else
        return type(::pfn::detail::_expected_from_invoke, ::std::in_place, [&fn, &self]() -> decltype(auto) {
          return ::fn::detail::_apply(FWD(fn), _pfn_base::_value(FWD(self)));
        });
    else
      return type(::fn::unexpect, _pfn_base::_error(FWD(self)));
  }

  // transform, value type is a copack (delegates to copack::transform). The callback is constrained here,
  // in the immediate context, for the reason given on optional's copack-case _transform.
  template <typename Self, typename Fn>
  static constexpr auto _transform(Self &&self, Fn &&fn) //
      noexcept(noexcept(_pfn_base::_value(FWD(self)).transform(FWD(fn)))
               && ::std::is_nothrow_constructible_v<E, decltype(_pfn_base::_error(FWD(self)))>) // extension
    requires some_copack<T> && (not empty_copack<T>)
             && ::fn::detail::_typelist_applicable<Fn, decltype(_pfn_base::_value(FWD(self)))>
             && ::std::is_constructible_v<E, decltype(_pfn_base::_error(FWD(self)))>
  {
    using new_value_type = decltype(_pfn_base::_value(FWD(self)).transform(FWD(fn)));
    using type = ::fn::expected<new_value_type, E>;
    if (self.has_value())
      if constexpr (::std::is_void_v<new_value_type>) {
        _pfn_base::_value(FWD(self)).transform(FWD(fn));
        return type();
      } else
        return type(::pfn::detail::_expected_from_invoke, ::std::in_place,
                    [&fn, &self]() -> decltype(auto) { return _pfn_base::_value(FWD(self)).transform(FWD(fn)); });
    else
      return type(::fn::unexpect, _pfn_base::_error(FWD(self)));
  }

  // transform, value type is the empty copack: a value can never be constructed, so the callback can
  // never be presented one - it is left alone, not invoked and not even instantiated, the mapping
  // is the identity and the result is *this unchanged.
  template <typename Self, typename Fn>
  static constexpr auto _transform(Self &&self, Fn &&)                        //
      noexcept(::std::is_nothrow_constructible_v<::fn::expected<T, E>, Self>) // extension
      -> ::fn::expected<T, E>
    requires empty_copack<T> && ::std::is_constructible_v<::fn::expected<T, E>, Self>
  {
    return FWD(self);
  }

  // transform, void value type
  template <typename Self, typename Fn>
  static constexpr auto _transform(Self &&self, Fn &&fn) //
      noexcept(::fn::detail::_is_nothrow_applicable<Fn>::value
               && ::std::is_nothrow_constructible_v<E, decltype(_pfn_base::_error(FWD(self)))>) // extension
    requires(::std::is_void_v<T>) && ::fn::detail::_is_applicable<Fn>::value
            && ::std::is_constructible_v<E, decltype(_pfn_base::_error(FWD(self)))>
  {
    using new_value_type = typename ::fn::detail::_apply_result<Fn>::type;
    using type = ::fn::expected<new_value_type, E>;
    if (self.has_value())
      if constexpr (::std::is_void_v<new_value_type>) {
        ::fn::detail::_apply(FWD(fn));
        return type();
      } else
        return type(::pfn::detail::_expected_from_invoke, ::std::in_place,
                    [&fn]() -> decltype(auto) { return ::fn::detail::_apply(FWD(fn)); });
    else
      return type(::fn::unexpect, _pfn_base::_error(FWD(self)));
  }

  // transform_error, error type is not a copack (the value-copy conjunct is spelled via
  // apply_const_lvalue_t for the same reason as _or_else's above)
  template <typename Self, typename Fn>
  static constexpr auto _transform_error(Self &&self, Fn &&fn) //
      noexcept(::fn::detail::_is_nothrow_applicable<Fn, decltype(_pfn_base::_error(FWD(self)))>::value
               && (::std::is_void_v<T>
                   || ::std::is_nothrow_constructible_v<
                       T, ::fn::apply_const_lvalue_t<Self, typename _pfn_base::_value_t &&>>)) // extension
    requires(not some_copack<E>)
            && ::fn::detail::_is_applicable_if<not some_copack<E>, Fn, decltype(_pfn_base::_error(FWD(self)))>::value
            && (::std::is_void_v<T> || ::std::is_constructible_v<T, decltype(_pfn_base::_value(FWD(self)))>)
  {
    using new_error_type = typename ::fn::detail::_apply_result<Fn, decltype(_pfn_base::_error(FWD(self)))>::type;
    using type = ::fn::expected<T, new_error_type>;
    if (self.has_value())
      if constexpr (not ::std::is_void_v<T>)
        return type(::std::in_place, _pfn_base::_value(FWD(self)));
      else
        return type();
    else
      return type(::pfn::detail::_expected_from_invoke, ::fn::unexpect, [&fn, &self]() -> decltype(auto) {
        return ::fn::detail::_apply(FWD(fn), _pfn_base::_error(FWD(self)));
      });
  }

  // transform_error, error type is a copack (delegates to copack::transform). The callback is constrained
  // here, in the immediate context, for the reason given on optional's copack-case _transform.
  template <typename Self, typename Fn>
  static constexpr auto _transform_error(Self &&self, Fn &&fn) //
      noexcept(noexcept(_pfn_base::_error(FWD(self)).transform(FWD(fn)))
               && (::std::is_void_v<T>
                   || ::std::is_nothrow_constructible_v<
                       T, ::fn::apply_const_lvalue_t<Self, typename _pfn_base::_value_t &&>>)) // extension
    requires some_copack<E> && (not empty_copack<E>)
             && ::fn::detail::_typelist_applicable<Fn, decltype(_pfn_base::_error(FWD(self)))>
             && (::std::is_void_v<T> || ::std::is_constructible_v<T, decltype(_pfn_base::_value(FWD(self)))>)
  {
    using new_error_type = decltype(_pfn_base::_error(FWD(self)).transform(FWD(fn)));
    using type = ::fn::expected<T, new_error_type>;
    if (self.has_value())
      if constexpr (not ::std::is_void_v<T>)
        return type(::std::in_place, _pfn_base::_value(FWD(self)));
      else
        return type();
    else
      return type(::pfn::detail::_expected_from_invoke, ::fn::unexpect,
                  [&fn, &self]() -> decltype(auto) { return _pfn_base::_error(FWD(self)).transform(FWD(fn)); });
  }

  // apply: elimination over both states, both arms required outright - each arm eliminates its
  // side's value through fn's own _apply (a pack or tuple-like payload by elements, a copack by
  // dispatch); a void value arm is invoked without a value. Over an empty-copack side this overload
  // set needs no gate: copack<> has no apply, so _is_applicable and _apply_tagged answer false for
  // every Fn and the general overloads drop out.
  template <typename Self, typename Fn, typename... Args>
  static constexpr auto _apply(Self &&self, Fn &&fn, Args &&...args) //
      noexcept(::fn::detail::_is_nothrow_applicable<Fn, decltype(_pfn_base::_value(FWD(self))), Args...>::value
               && ::fn::detail::_is_nothrow_applicable<Fn, decltype(_pfn_base::_error(FWD(self))),
                                                       Args...>::value) // extension
      -> decltype(auto)
    requires(not ::std::is_void_v<T>)
            && ::fn::detail::_is_applicable<Fn, decltype(_pfn_base::_value(FWD(self))), Args...>::value
            && ::fn::detail::_is_applicable<Fn, decltype(_pfn_base::_error(FWD(self))), Args...>::value
  {
    // Both arms are viable here, so they must yield the same result type.
    static_assert(::std::is_same_v<
                  typename ::fn::detail::_apply_result<Fn, decltype(_pfn_base::_value(FWD(self))), Args...>::type,
                  typename ::fn::detail::_apply_result<Fn, decltype(_pfn_base::_error(FWD(self))), Args...>::type>);
    if (self.has_value())
      return ::fn::detail::_apply(FWD(fn), _pfn_base::_value(FWD(self)), FWD(args)...);
    else
      return ::fn::detail::_apply(FWD(fn), _pfn_base::_error(FWD(self)), FWD(args)...);
  }

  // apply, void value type
  template <typename Self, typename Fn, typename... Args>
  static constexpr auto _apply(Self &&self, Fn &&fn, Args &&...args) //
      noexcept(::fn::detail::_is_nothrow_applicable<Fn, Args...>::value
               && ::fn::detail::_is_nothrow_applicable<Fn, decltype(_pfn_base::_error(FWD(self))),
                                                       Args...>::value) // extension
      -> decltype(auto)
    requires ::std::is_void_v<T> && ::fn::detail::_is_applicable<Fn, Args...>::value
             && ::fn::detail::_is_applicable<Fn, decltype(_pfn_base::_error(FWD(self))), Args...>::value
  {
    // Both arms are viable here, so they must yield the same result type.
    static_assert(::std::is_same_v<
                  typename ::fn::detail::_apply_result<Fn, Args...>::type,
                  typename ::fn::detail::_apply_result<Fn, decltype(_pfn_base::_error(FWD(self))), Args...>::type>);
    if (self.has_value())
      return ::fn::detail::_apply(FWD(fn), FWD(args)...);
    else
      return ::fn::detail::_apply(FWD(fn), _pfn_base::_error(FWD(self)), FWD(args)...);
  }

  template <typename Ret, typename Self, typename Fn, typename... Args>
  static constexpr auto _apply_r(Self &&self, Fn &&fn, Args &&...args) //
      noexcept(::fn::detail::_is_nothrow_applicable_r<Ret, Fn, decltype(_pfn_base::_value(FWD(self))), Args...>::value
               && ::fn::detail::_is_nothrow_applicable_r<Ret, Fn, decltype(_pfn_base::_error(FWD(self))),
                                                         Args...>::value) // extension
      -> Ret
    requires(not ::std::is_void_v<T>)
            && ::fn::detail::_is_applicable_r<Ret, Fn, decltype(_pfn_base::_value(FWD(self))), Args...>::value
            && ::fn::detail::_is_applicable_r<Ret, Fn, decltype(_pfn_base::_error(FWD(self))), Args...>::value
  {
    if (self.has_value())
      return ::fn::detail::_apply_r<Ret>(FWD(fn), _pfn_base::_value(FWD(self)), FWD(args)...);
    else
      return ::fn::detail::_apply_r<Ret>(FWD(fn), _pfn_base::_error(FWD(self)), FWD(args)...);
  }

  // apply_r, void value type
  template <typename Ret, typename Self, typename Fn, typename... Args>
  static constexpr auto _apply_r(Self &&self, Fn &&fn, Args &&...args) //
      noexcept(::fn::detail::_is_nothrow_applicable_r<Ret, Fn, Args...>::value
               && ::fn::detail::_is_nothrow_applicable_r<Ret, Fn, decltype(_pfn_base::_error(FWD(self))),
                                                         Args...>::value) // extension
      -> Ret
    requires ::std::is_void_v<T> && ::fn::detail::_is_applicable_r<Ret, Fn, Args...>::value
             && ::fn::detail::_is_applicable_r<Ret, Fn, decltype(_pfn_base::_error(FWD(self))), Args...>::value
  {
    if (self.has_value())
      return ::fn::detail::_apply_r<Ret>(FWD(fn), FWD(args)...);
    else
      return ::fn::detail::_apply_r<Ret>(FWD(fn), _pfn_base::_error(FWD(self)), FWD(args)...);
  }

  // apply_type: the tagged form - the value arm receives ::std::in_place followed by the value as
  // _apply_tagged hands it over (the tag alone when T is void; a tuple-like value's elements form
  // is the row's one signature), the error arm ::fn::unexpect followed by the error; the tags
  // never interconvert, so the dispatch stays airtight even where T and E do. Tags are passed as
  // prvalues, the exact shape the traits ask about; trailing arguments follow either arm's content.
  template <typename Self, typename Fn, typename... Args>
  static constexpr auto _apply_type(Self &&self, Fn &&fn, Args &&...args) //
      noexcept(noexcept(::fn::detail::_apply_tagged<::std::in_place_t>(FWD(fn), _pfn_base::_value(FWD(self)),
                                                                       FWD(args)...))
               && noexcept(::fn::detail::_apply_tagged<::fn::unexpect_t>(FWD(fn), _pfn_base::_error(FWD(self)),
                                                                         FWD(args)...))) // extension
      -> decltype(auto)
    requires(not ::std::is_void_v<T>) && requires {
      ::fn::detail::_apply_tagged<::std::in_place_t>(FWD(fn), _pfn_base::_value(FWD(self)), FWD(args)...);
    } && requires {
      ::fn::detail::_apply_tagged<::fn::unexpect_t>(FWD(fn), _pfn_base::_error(FWD(self)), FWD(args)...);
    }
  {
    // Both arms are viable here, so they must yield the same result type.
    static_assert(::std::is_same_v<decltype(::fn::detail::_apply_tagged<::std::in_place_t>(
                                       FWD(fn), _pfn_base::_value(FWD(self)), FWD(args)...)),
                                   decltype(::fn::detail::_apply_tagged<::fn::unexpect_t>(
                                       FWD(fn), _pfn_base::_error(FWD(self)), FWD(args)...))>);
    if (self.has_value())
      return ::fn::detail::_apply_tagged<::std::in_place_t>(FWD(fn), _pfn_base::_value(FWD(self)), FWD(args)...);
    else
      return ::fn::detail::_apply_tagged<::fn::unexpect_t>(FWD(fn), _pfn_base::_error(FWD(self)), FWD(args)...);
  }

  // apply_type, void value type
  template <typename Self, typename Fn, typename... Args>
  static constexpr auto _apply_type(Self &&self, Fn &&fn, Args &&...args) //
      noexcept(::fn::detail::_is_nothrow_applicable<Fn, ::std::in_place_t, Args &&...>::value
               && noexcept(::fn::detail::_apply_tagged<::fn::unexpect_t>(FWD(fn), _pfn_base::_error(FWD(self)),
                                                                         FWD(args)...))) // extension
      -> decltype(auto)
    requires ::std::is_void_v<T> && ::fn::detail::_is_applicable<Fn, ::std::in_place_t, Args &&...>::value && requires {
      ::fn::detail::_apply_tagged<::fn::unexpect_t>(FWD(fn), _pfn_base::_error(FWD(self)), FWD(args)...);
    }
  {
    // Both arms are viable here, so they must yield the same result type.
    static_assert(::std::is_same_v<typename ::fn::detail::_apply_result<Fn, ::std::in_place_t, Args &&...>::type,
                                   decltype(::fn::detail::_apply_tagged<::fn::unexpect_t>(
                                       FWD(fn), _pfn_base::_error(FWD(self)), FWD(args)...))>);
    if (self.has_value())
      return ::fn::detail::_apply(FWD(fn), ::std::in_place_t{}, FWD(args)...);
    else
      return ::fn::detail::_apply_tagged<::fn::unexpect_t>(FWD(fn), _pfn_base::_error(FWD(self)), FWD(args)...);
  }

  template <typename Ret, typename Self, typename Fn, typename... Args>
  static constexpr auto _apply_type_r(Self &&self, Fn &&fn, Args &&...args) //
      noexcept(noexcept(::fn::detail::_apply_tagged_r<Ret, ::std::in_place_t>(FWD(fn), _pfn_base::_value(FWD(self)),
                                                                              FWD(args)...))
               && noexcept(::fn::detail::_apply_tagged_r<Ret, ::fn::unexpect_t>(FWD(fn), _pfn_base::_error(FWD(self)),
                                                                                FWD(args)...))) // extension
      -> Ret
    requires(not ::std::is_void_v<T>) && requires {
      ::fn::detail::_apply_tagged_r<Ret, ::std::in_place_t>(FWD(fn), _pfn_base::_value(FWD(self)), FWD(args)...);
    } && requires {
      ::fn::detail::_apply_tagged_r<Ret, ::fn::unexpect_t>(FWD(fn), _pfn_base::_error(FWD(self)), FWD(args)...);
    }
  {
    if (self.has_value())
      return ::fn::detail::_apply_tagged_r<Ret, ::std::in_place_t>(FWD(fn), _pfn_base::_value(FWD(self)), FWD(args)...);
    else
      return ::fn::detail::_apply_tagged_r<Ret, ::fn::unexpect_t>(FWD(fn), _pfn_base::_error(FWD(self)), FWD(args)...);
  }

  // apply_type_r, void value type
  template <typename Ret, typename Self, typename Fn, typename... Args>
  static constexpr auto _apply_type_r(Self &&self, Fn &&fn, Args &&...args) //
      noexcept(::fn::detail::_is_nothrow_applicable_r<Ret, Fn, ::std::in_place_t, Args &&...>::value
               && noexcept(::fn::detail::_apply_tagged_r<Ret, ::fn::unexpect_t>(FWD(fn), _pfn_base::_error(FWD(self)),
                                                                                FWD(args)...))) // extension
      -> Ret
    requires ::std::is_void_v<T> && ::fn::detail::_is_applicable_r<Ret, Fn, ::std::in_place_t, Args &&...>::value
             && requires {
                  ::fn::detail::_apply_tagged_r<Ret, ::fn::unexpect_t>(FWD(fn), _pfn_base::_error(FWD(self)),
                                                                       FWD(args)...);
                }
  {
    if (self.has_value())
      return ::fn::detail::_apply_r<Ret>(FWD(fn), ::std::in_place_t{}, FWD(args)...);
    else
      return ::fn::detail::_apply_tagged_r<Ret, ::fn::unexpect_t>(FWD(fn), _pfn_base::_error(FWD(self)), FWD(args)...);
  }

  // apply, error type is the empty copack: the error row is uninhabited, so the value arm alone is
  // exhaustive and dispatch needs no branch; nothing names the error row, so an arm set carrying
  // an arm for it never instantiates it.
  template <typename Self, typename Fn, typename... Args>
  static constexpr auto _apply(Self &&self, Fn &&fn, Args &&...args) //
      noexcept(
          ::fn::detail::_is_nothrow_applicable<Fn, decltype(_pfn_base::_value(FWD(self))), Args...>::value) // extension
      -> decltype(auto)
    requires(not ::std::is_void_v<T>) && empty_copack<E>
            && ::fn::detail::_is_applicable<Fn, decltype(_pfn_base::_value(FWD(self))), Args...>::value
  {
    return ::fn::detail::_apply(FWD(fn), _pfn_base::_value(FWD(self)), FWD(args)...);
  }

  // apply, void value type and empty copack error
  template <typename Self, typename Fn, typename... Args>
  static constexpr auto _apply(Self &&, Fn &&fn, Args &&...args)         //
      noexcept(::fn::detail::_is_nothrow_applicable<Fn, Args...>::value) // extension
      -> decltype(auto)
    requires ::std::is_void_v<T> && empty_copack<E> && ::fn::detail::_is_applicable<Fn, Args...>::value
  {
    return ::fn::detail::_apply(FWD(fn), FWD(args)...);
  }

  template <typename Ret, typename Self, typename Fn, typename... Args>
  static constexpr auto _apply_r(Self &&self, Fn &&fn, Args &&...args) //
      noexcept(::fn::detail::_is_nothrow_applicable_r<Ret, Fn, decltype(_pfn_base::_value(FWD(self))),
                                                      Args...>::value) // extension
      -> Ret
    requires(not ::std::is_void_v<T>) && empty_copack<E>
            && ::fn::detail::_is_applicable_r<Ret, Fn, decltype(_pfn_base::_value(FWD(self))), Args...>::value
  {
    return ::fn::detail::_apply_r<Ret>(FWD(fn), _pfn_base::_value(FWD(self)), FWD(args)...);
  }

  // apply_r, void value type and empty copack error
  template <typename Ret, typename Self, typename Fn, typename... Args>
  static constexpr auto _apply_r(Self &&, Fn &&fn, Args &&...args)              //
      noexcept(::fn::detail::_is_nothrow_applicable_r<Ret, Fn, Args...>::value) // extension
      -> Ret
    requires ::std::is_void_v<T> && empty_copack<E> && ::fn::detail::_is_applicable_r<Ret, Fn, Args...>::value
  {
    return ::fn::detail::_apply_r<Ret>(FWD(fn), FWD(args)...);
  }

  // apply_type, error type is the empty copack: the value arm alone is exhaustive
  template <typename Self, typename Fn, typename... Args>
  static constexpr auto _apply_type(Self &&self, Fn &&fn, Args &&...args) //
      noexcept(noexcept(::fn::detail::_apply_tagged<::std::in_place_t>(FWD(fn), _pfn_base::_value(FWD(self)),
                                                                       FWD(args)...))) // extension
      -> decltype(auto)
    requires(not ::std::is_void_v<T>) && empty_copack<E> && requires {
      ::fn::detail::_apply_tagged<::std::in_place_t>(FWD(fn), _pfn_base::_value(FWD(self)), FWD(args)...);
    }
  {
    return ::fn::detail::_apply_tagged<::std::in_place_t>(FWD(fn), _pfn_base::_value(FWD(self)), FWD(args)...);
  }

  // apply_type, void value type and empty copack error
  template <typename Self, typename Fn, typename... Args>
  static constexpr auto _apply_type(Self &&, Fn &&fn, Args &&...args)                          //
      noexcept(::fn::detail::_is_nothrow_applicable<Fn, ::std::in_place_t, Args &&...>::value) // extension
      -> decltype(auto)
    requires ::std::is_void_v<T> && empty_copack<E>
             && ::fn::detail::_is_applicable<Fn, ::std::in_place_t, Args &&...>::value
  {
    return ::fn::detail::_apply(FWD(fn), ::std::in_place_t{}, FWD(args)...);
  }

  template <typename Ret, typename Self, typename Fn, typename... Args>
  static constexpr auto _apply_type_r(Self &&self, Fn &&fn, Args &&...args) //
      noexcept(noexcept(::fn::detail::_apply_tagged_r<Ret, ::std::in_place_t>(FWD(fn), _pfn_base::_value(FWD(self)),
                                                                              FWD(args)...))) // extension
      -> Ret
    requires(not ::std::is_void_v<T>) && empty_copack<E> && requires {
      ::fn::detail::_apply_tagged_r<Ret, ::std::in_place_t>(FWD(fn), _pfn_base::_value(FWD(self)), FWD(args)...);
    }
  {
    return ::fn::detail::_apply_tagged_r<Ret, ::std::in_place_t>(FWD(fn), _pfn_base::_value(FWD(self)), FWD(args)...);
  }

  // apply_type_r, void value type and empty copack error
  template <typename Ret, typename Self, typename Fn, typename... Args>
  static constexpr auto _apply_type_r(Self &&, Fn &&fn, Args &&...args)                               //
      noexcept(::fn::detail::_is_nothrow_applicable_r<Ret, Fn, ::std::in_place_t, Args &&...>::value) // extension
      -> Ret
    requires ::std::is_void_v<T> && empty_copack<E>
             && ::fn::detail::_is_applicable_r<Ret, Fn, ::std::in_place_t, Args &&...>::value
  {
    return ::fn::detail::_apply_r<Ret>(FWD(fn), ::std::in_place_t{}, FWD(args)...);
  }

  // apply, value type is the empty copack: the value row is uninhabited, so the error arm alone is
  // exhaustive and dispatch needs no branch.
  template <typename Self, typename Fn, typename... Args>
  static constexpr auto _apply(Self &&self, Fn &&fn, Args &&...args) //
      noexcept(
          ::fn::detail::_is_nothrow_applicable<Fn, decltype(_pfn_base::_error(FWD(self))), Args...>::value) // extension
      -> decltype(auto)
    requires empty_copack<T> && ::fn::detail::_is_applicable<Fn, decltype(_pfn_base::_error(FWD(self))), Args...>::value
  {
    return ::fn::detail::_apply(FWD(fn), _pfn_base::_error(FWD(self)), FWD(args)...);
  }

  template <typename Ret, typename Self, typename Fn, typename... Args>
  static constexpr auto _apply_r(Self &&self, Fn &&fn, Args &&...args) //
      noexcept(::fn::detail::_is_nothrow_applicable_r<Ret, Fn, decltype(_pfn_base::_error(FWD(self))),
                                                      Args...>::value) // extension
      -> Ret
    requires empty_copack<T>
             && ::fn::detail::_is_applicable_r<Ret, Fn, decltype(_pfn_base::_error(FWD(self))), Args...>::value
  {
    return ::fn::detail::_apply_r<Ret>(FWD(fn), _pfn_base::_error(FWD(self)), FWD(args)...);
  }

  // apply_type, value type is the empty copack: the error arm alone is exhaustive
  template <typename Self, typename Fn, typename... Args>
  static constexpr auto _apply_type(Self &&self, Fn &&fn, Args &&...args) //
      noexcept(noexcept(::fn::detail::_apply_tagged<::fn::unexpect_t>(FWD(fn), _pfn_base::_error(FWD(self)),
                                                                      FWD(args)...))) // extension
      -> decltype(auto)
    requires empty_copack<T> && requires {
      ::fn::detail::_apply_tagged<::fn::unexpect_t>(FWD(fn), _pfn_base::_error(FWD(self)), FWD(args)...);
    }
  {
    return ::fn::detail::_apply_tagged<::fn::unexpect_t>(FWD(fn), _pfn_base::_error(FWD(self)), FWD(args)...);
  }

  template <typename Ret, typename Self, typename Fn, typename... Args>
  static constexpr auto _apply_type_r(Self &&self, Fn &&fn, Args &&...args) //
      noexcept(noexcept(::fn::detail::_apply_tagged_r<Ret, ::fn::unexpect_t>(FWD(fn), _pfn_base::_error(FWD(self)),
                                                                             FWD(args)...))) // extension
      -> Ret
    requires empty_copack<T> && requires {
      ::fn::detail::_apply_tagged_r<Ret, ::fn::unexpect_t>(FWD(fn), _pfn_base::_error(FWD(self)), FWD(args)...);
    }
  {
    return ::fn::detail::_apply_tagged_r<Ret, ::fn::unexpect_t>(FWD(fn), _pfn_base::_error(FWD(self)), FWD(args)...);
  }

  // transform_error, error type is the empty copack: an error can never be constructed, so the
  // callback can never be presented one - it is left alone, not invoked and not even instantiated,
  // the mapping is the identity and the result is *this unchanged.
  template <typename Self, typename Fn>
  static constexpr auto _transform_error(Self &&self, Fn &&)                  //
      noexcept(::std::is_nothrow_constructible_v<::fn::expected<T, E>, Self>) // extension
      -> ::fn::expected<T, E>
    requires empty_copack<E> && ::std::is_constructible_v<::fn::expected<T, E>, Self>
  {
    return FWD(self);
  }
};

} // namespace detail

/**
 * @brief The fallible carrier: a computation yielding success `T` or error `Err`
 *
 * A strict superset of `std::expected` as specified for C++26, provided here by `pfn::expected`:
 * construction, assignment, observers and comparisons are the standard's, and a valid program
 * switching from `pfn` to `fn` changes neither compilation nor behaviour. On top of the standard
 * contract come the extensions: a `copack` error side enrols the carrier in graded error-set
 * unioning, and a `copack` value side in the same arithmetic on values; the `apply` family
 * eliminates over both states; `copack_error` and `copack_value` lift a plain side into its
 * singular copack; `operator&` conjoins and `operator|` disjoins carriers. An error side
 * `copack<>` makes the carrier infallible - the identity `expected` - and a `pack` value spreads
 * into callbacks as separate arguments. This primary template serves a non-void `T`; the
 * specialization over `void` mirrors it.
 *
 * @tparam T Value type; `void` selects the specialization
 * @tparam Err Error type; a `copack` makes the carrier graded
 */
template <typename T, typename Err> class expected : private detail::_expected_base<T, Err> {
  using _base = detail::_expected_base<T, Err>;

  // Allow sibling _expected_base instantiations to downcast into the private base.
  template <class, class, class> friend struct ::pfn::detail::_expected_base;
  template <class, class> friend struct ::fn::detail::_expected_base;

public:
  /**
   * @brief The type of the value side
   */
  using value_type = T;
  /**
   * @brief The type of the error side
   */
  using error_type = Err;
  /**
   * @brief The `unexpected` specialization over the error type
   */
  using unexpected_type = ::fn::unexpected<Err>;

  /**
   * @brief This carrier over another value type
   */
  template <class U> using rebind = expected<U, error_type>;

  // Constructors. Explicit forwarders to the base mirror pfn::expected.
  /**
   * @brief Default constructor
   */
  constexpr expected() noexcept(::std::is_nothrow_default_constructible_v<T>)
    requires ::std::is_default_constructible_v<T>
      : _base(::std::in_place)
  {
  }

  template <class U, class G>
  constexpr explicit(not ::std::is_convertible_v<U const &, T> || not ::std::is_convertible_v<G const &, Err>)
      /**
       * @brief Converting constructor from a compatible carrier
       */
      expected(expected<U, G> const &s) //
      noexcept(::std::is_nothrow_constructible_v<T, U const &> && ::std::is_nothrow_constructible_v<Err, G const &>)
    requires(_base::template _can_copy_convert<U, G>::value)
      : _base(s)
  {
  }
  template <class U, class G>
  constexpr explicit(not ::std::is_convertible_v<U, T> || not ::std::is_convertible_v<G, Err>)
      /**
       * @brief Converting constructor from a compatible carrier
       */
      expected(expected<U, G> &&s) //
      noexcept(::std::is_nothrow_constructible_v<T, U> && ::std::is_nothrow_constructible_v<Err, G>)
    requires(_base::template _can_move_convert<U, G>::value)
      : _base(::std::move(s))
  {
  }
  /**
   * @brief Constructs the value from a value
   */
  template <class U = ::std::remove_cv_t<T>>
  constexpr explicit(not ::std::is_convertible_v<U, T>) expected(U &&v) //
      noexcept(::std::is_nothrow_constructible_v<T, U>)
    requires(_base::template _can_convert<U>::value)
      : _base(::std::in_place, FWD(v))
  {
  }

  /**
   * @brief Constructs the error from an `unexpected`
   */
  template <class G>
  constexpr explicit(not ::std::is_convertible_v<G const &, Err>) expected(::fn::unexpected<G> const &g) //
      noexcept(::std::is_nothrow_constructible_v<Err, G const &>)
    requires(::std::is_constructible_v<Err, G const &>)
      : _base(::fn::unexpect, ::std::forward<G const &>(g.error()))
  {
  }
  /**
   * @brief Constructs the error from an `unexpected`
   */
  template <class G>
  constexpr explicit(not ::std::is_convertible_v<G, Err>) expected(::fn::unexpected<G> &&g) //
      noexcept(::std::is_nothrow_constructible_v<Err, G>)
    requires(::std::is_constructible_v<Err, G>)
      : _base(::fn::unexpect, ::std::forward<G>(g.error()))
  {
  }

  /**
   * @brief Constructs the value in place from the arguments
   */
  template <class... Args>
  constexpr explicit expected(::std::in_place_t, Args &&...a) //
      noexcept(::std::is_nothrow_constructible_v<T, Args...>)
    requires ::std::is_constructible_v<T, Args...>
      : _base(::std::in_place, FWD(a)...)
  {
  }
  /**
   * @brief Constructs the value in place from the arguments
   */
  template <class U, class... Args>
  constexpr explicit expected(::std::in_place_t, ::std::initializer_list<U> il, Args &&...a) //
      noexcept(::std::is_nothrow_constructible_v<T, ::std::initializer_list<U> &, Args...>)
    requires ::std::is_constructible_v<T, ::std::initializer_list<U> &, Args...>
      : _base(::std::in_place, il, FWD(a)...)
  {
  }
  /**
   * @brief Constructs the error in place from the arguments
   */
  template <class... Args>
  constexpr explicit expected(::fn::unexpect_t, Args &&...a)    //
      noexcept(::std::is_nothrow_constructible_v<Err, Args...>) //
    requires ::std::is_constructible_v<Err, Args...>
      : _base(::fn::unexpect, FWD(a)...)
  {
  }
  /**
   * @brief Constructs the error in place from the arguments
   */
  template <class U, class... Args>
  constexpr explicit expected(::fn::unexpect_t, ::std::initializer_list<U> il, Args &&...a) //
      noexcept(::std::is_nothrow_constructible_v<Err, ::std::initializer_list<U> &, Args...>)
    requires ::std::is_constructible_v<Err, ::std::initializer_list<U> &, Args...>
      : _base(::fn::unexpect, il, FWD(a)...)
  {
  }

  /**
   * @brief Copy constructor; not available on this carrier
   */
  constexpr expected(expected const &) = delete;
  constexpr expected(expected const &s) //
      noexcept(::std::is_nothrow_copy_constructible_v<T> && ::std::is_nothrow_copy_constructible_v<Err>)
    requires(::std::is_copy_constructible_v<T> && ::std::is_copy_constructible_v<Err>
             && ::std::is_trivially_copy_constructible_v<T> && ::std::is_trivially_copy_constructible_v<Err>)
  = default;
  constexpr expected(expected const &s) //
      noexcept(::std::is_nothrow_copy_constructible_v<T> && ::std::is_nothrow_copy_constructible_v<Err>)
    requires(::std::is_copy_constructible_v<T> && ::std::is_copy_constructible_v<Err>
             && (not ::std::is_trivially_copy_constructible_v<T> || not ::std::is_trivially_copy_constructible_v<Err>))
      : _base(s.set_, FWD(s).storage_)
  {
  }
  /**
   * @brief Move constructor
   */
  constexpr expected(expected &&s) noexcept
    requires(::std::is_move_constructible_v<T> && ::std::is_move_constructible_v<Err>
             && ::std::is_trivially_move_constructible_v<T> && ::std::is_trivially_move_constructible_v<Err>)
  = default;
  constexpr expected(expected &&s) //
      noexcept(::std::is_nothrow_move_constructible_v<T> && ::std::is_nothrow_move_constructible_v<Err>)
    requires(::std::is_move_constructible_v<T> && ::std::is_move_constructible_v<Err>
             && (not ::std::is_trivially_move_constructible_v<T> || not ::std::is_trivially_move_constructible_v<Err>))
      : _base(s.set_, FWD(s).storage_)
  {
  }

  /**
   * @brief Destructor
   */
  constexpr ~expected() = default;

  // Assignment. Explicit forwarders mirror pfn::expected to avoid an MSVC bug.
  /**
   * @brief Assignment from a value
   */
  template <class U = T>
  constexpr expected &operator=(U &&s) //
      noexcept(::std::is_nothrow_assignable_v<T &, U> && ::std::is_nothrow_constructible_v<T, U>)
    requires(_base::template _can_convert_assign<U>::value)
  {
    this->_assign_value(FWD(s));
    return *this;
  }
  /**
   * @brief Assignment from an `unexpected`
   */
  template <class G>
  constexpr expected &operator=(::fn::unexpected<G> const &s) //
      noexcept(::std::is_nothrow_assignable_v<Err &, G const &> && ::std::is_nothrow_constructible_v<Err, G const &>)
    requires(::std::is_constructible_v<Err, G const &> && ::std::is_assignable_v<Err &, G const &>
             && (::std::is_nothrow_constructible_v<Err, G const &> || ::std::is_nothrow_move_constructible_v<T>
                 || ::std::is_nothrow_move_constructible_v<Err>))
  {
    this->_assign_unexpected(s);
    return *this;
  }
  /**
   * @brief Assignment from an `unexpected`
   */
  template <class G>
  constexpr expected &operator=(::fn::unexpected<G> &&s) //
      noexcept(::std::is_nothrow_assignable_v<Err &, G> && ::std::is_nothrow_constructible_v<Err, G>)
    requires(::std::is_constructible_v<Err, G> && ::std::is_assignable_v<Err &, G>
             && (::std::is_nothrow_constructible_v<Err, G> || ::std::is_nothrow_move_constructible_v<T>
                 || ::std::is_nothrow_move_constructible_v<Err>))
  {
    this->_assign_unexpected(::std::move(s));
    return *this;
  }
  /**
   * @brief Copy assignment; not available on this carrier
   */
  constexpr expected &operator=(expected const &) = delete;
  constexpr expected &operator=(expected const &) //
      noexcept(::std::is_nothrow_copy_assignable_v<T> && ::std::is_nothrow_copy_constructible_v<T>
               && ::std::is_nothrow_copy_assignable_v<Err> && ::std::is_nothrow_copy_constructible_v<Err>)
    requires(::std::is_copy_assignable_v<T> && ::std::is_copy_constructible_v<T> && ::std::is_copy_assignable_v<Err>
             && ::std::is_copy_constructible_v<Err>
             && (::std::is_nothrow_move_constructible_v<T> || ::std::is_nothrow_move_constructible_v<Err>)
             && ::std::is_trivially_copy_constructible_v<T> && ::std::is_trivially_copy_assignable_v<T>
             && ::std::is_trivially_destructible_v<T> && ::std::is_trivially_copy_constructible_v<Err>
             && ::std::is_trivially_copy_assignable_v<Err> && ::std::is_trivially_destructible_v<Err>)
  = default;
  constexpr expected &operator=(expected const &s) //
      noexcept(::std::is_nothrow_copy_assignable_v<T> && ::std::is_nothrow_copy_constructible_v<T>
               && ::std::is_nothrow_copy_assignable_v<Err> && ::std::is_nothrow_copy_constructible_v<Err>)
    requires(::std::is_copy_assignable_v<T> && ::std::is_copy_constructible_v<T> && ::std::is_copy_assignable_v<Err>
             && ::std::is_copy_constructible_v<Err>
             && (::std::is_nothrow_move_constructible_v<T> || ::std::is_nothrow_move_constructible_v<Err>)
             && (not ::std::is_trivially_copy_constructible_v<T> || not ::std::is_trivially_copy_assignable_v<T>
                 || not ::std::is_trivially_destructible_v<T> || not ::std::is_trivially_copy_constructible_v<Err>
                 || not ::std::is_trivially_copy_assignable_v<Err> || not ::std::is_trivially_destructible_v<Err>))
  {
    this->_assign(static_cast<_base const &>(s));
    return *this;
  }
  /**
   * @brief Move assignment
   */
  constexpr expected &operator=(expected &&) //
      noexcept(::std::is_nothrow_move_assignable_v<T> && ::std::is_nothrow_move_constructible_v<T>
               && ::std::is_nothrow_move_assignable_v<Err> && ::std::is_nothrow_move_constructible_v<Err>)
    requires(::std::is_move_constructible_v<T> && ::std::is_move_assignable_v<T> && ::std::is_move_constructible_v<Err>
             && ::std::is_move_assignable_v<Err>
             && (::std::is_nothrow_move_constructible_v<T> || ::std::is_nothrow_move_constructible_v<Err>)
             && ::std::is_trivially_move_constructible_v<T> && ::std::is_trivially_move_assignable_v<T>
             && ::std::is_trivially_destructible_v<T> && ::std::is_trivially_move_constructible_v<Err>
             && ::std::is_trivially_move_assignable_v<Err> && ::std::is_trivially_destructible_v<Err>)
  = default;
  constexpr expected &operator=(expected &&s) //
      noexcept(::std::is_nothrow_move_assignable_v<T> && ::std::is_nothrow_move_constructible_v<T>
               && ::std::is_nothrow_move_assignable_v<Err> && ::std::is_nothrow_move_constructible_v<Err>)
    requires(::std::is_move_constructible_v<T> && ::std::is_move_assignable_v<T> && ::std::is_move_constructible_v<Err>
             && ::std::is_move_assignable_v<Err>
             && (::std::is_nothrow_move_constructible_v<T> || ::std::is_nothrow_move_constructible_v<Err>)
             && (not ::std::is_trivially_move_constructible_v<T> || not ::std::is_trivially_move_assignable_v<T>
                 || not ::std::is_trivially_destructible_v<T> || not ::std::is_trivially_move_constructible_v<Err>
                 || not ::std::is_trivially_move_assignable_v<Err> || not ::std::is_trivially_destructible_v<Err>))
  {
    this->_assign(static_cast<_base &&>(s));
    return *this;
  }

  // Observers inherited from _expected_base
  using _base::operator*;
  using _base::operator->;
  using _base::operator bool;
  using _base::error;
  using _base::error_or;
  using _base::has_error;
  using _base::has_value;
  using _base::value;
  using _base::value_or;

  // Emplace inherited from _expected_base
  using _base::emplace;

  // Swap; body delegates to _expected_base helper
  constexpr void
  /**
   * @brief Swaps the contents with another `expected`
   */
  swap(expected &rhs) noexcept(::std::is_nothrow_move_constructible_v<T> && ::std::is_nothrow_swappable_v<T>
                               && ::std::is_nothrow_move_constructible_v<Err> && ::std::is_nothrow_swappable_v<Err>)
    requires(::std::is_swappable_v<T> && ::std::is_swappable_v<Err> && ::std::is_move_constructible_v<T>
             && ::std::is_move_constructible_v<Err>
             && (::std::is_nothrow_move_constructible_v<T> || ::std::is_nothrow_move_constructible_v<Err>))
  {
    this->_swap_with(rhs);
  }

  // Elimination over both states, mirroring copack's apply family: each arm takes its side's value
  // unpacked as fn::apply would hand it over, keyed (apply_type) by the constructor tag naming
  // the state - ::std::in_place for the value, ::fn::unexpect for the error. Bodies delegate to
  // _expected_base static helpers.
  /**
   * @brief Eliminates over both states: the active side routes into the callable
   *
   * The value arm receives the value as `fn::apply` hands it over - a `pack` or tuple-like value
   * by elements - and the error arm receives the error likewise; the arms must yield one result
   * type. Over an uninhabited side the other arm alone is exhaustive.
   *
   * @param f Callable with arms for both states; `fn::overload` fuses them
   * @param args Additional arguments, appended after the content
   * @return The callable's result
   */
  template <class F, class... Args>
  [[nodiscard]] constexpr auto apply(F &&f, Args &&...args) &        //
      noexcept(noexcept(_base::_apply(*this, FWD(f), FWD(args)...))) // extension
      -> decltype(_base::_apply(*this, FWD(f), FWD(args)...))
  {
    return _base::_apply(*this, FWD(f), FWD(args)...);
  }
  template <class F, class... Args>
  [[nodiscard]] constexpr auto apply(F &&f, Args &&...args) &&                    //
      noexcept(noexcept(_base::_apply(::std::move(*this), FWD(f), FWD(args)...))) // extension
      -> decltype(_base::_apply(::std::move(*this), FWD(f), FWD(args)...))
  {
    return _base::_apply(::std::move(*this), FWD(f), FWD(args)...);
  }
  template <class F, class... Args>
  [[nodiscard]] constexpr auto apply(F &&f, Args &&...args) const &  //
      noexcept(noexcept(_base::_apply(*this, FWD(f), FWD(args)...))) // extension
      -> decltype(_base::_apply(*this, FWD(f), FWD(args)...))
  {
    return _base::_apply(*this, FWD(f), FWD(args)...);
  }
  template <class F, class... Args>
  [[nodiscard]] constexpr auto apply(F &&f, Args &&...args) const &&              //
      noexcept(noexcept(_base::_apply(::std::move(*this), FWD(f), FWD(args)...))) // extension
      -> decltype(_base::_apply(::std::move(*this), FWD(f), FWD(args)...))
  {
    return _base::_apply(::std::move(*this), FWD(f), FWD(args)...);
  }

  /**
   * @brief Eliminates over both states, converting the result to `Ret`
   *
   * @tparam Ret Type the results convert to
   * @param f Callable with arms for both states; `fn::overload` fuses them
   * @param args Additional arguments, appended after the content
   * @return The callable's result, converted to `Ret`
   */
  template <class Ret, class F, class... Args>
  [[nodiscard]] constexpr auto apply_r(F &&f, Args &&...args) &                      //
      noexcept(noexcept(_base::template _apply_r<Ret>(*this, FWD(f), FWD(args)...))) // extension
      -> decltype(_base::template _apply_r<Ret>(*this, FWD(f), FWD(args)...))
  {
    return _base::template _apply_r<Ret>(*this, FWD(f), FWD(args)...);
  }
  template <class Ret, class F, class... Args>
  [[nodiscard]] constexpr auto apply_r(F &&f, Args &&...args) &&                                  //
      noexcept(noexcept(_base::template _apply_r<Ret>(::std::move(*this), FWD(f), FWD(args)...))) // extension
      -> decltype(_base::template _apply_r<Ret>(::std::move(*this), FWD(f), FWD(args)...))
  {
    return _base::template _apply_r<Ret>(::std::move(*this), FWD(f), FWD(args)...);
  }
  template <class Ret, class F, class... Args>
  [[nodiscard]] constexpr auto apply_r(F &&f, Args &&...args) const &                //
      noexcept(noexcept(_base::template _apply_r<Ret>(*this, FWD(f), FWD(args)...))) // extension
      -> decltype(_base::template _apply_r<Ret>(*this, FWD(f), FWD(args)...))
  {
    return _base::template _apply_r<Ret>(*this, FWD(f), FWD(args)...);
  }
  template <class Ret, class F, class... Args>
  [[nodiscard]] constexpr auto apply_r(F &&f, Args &&...args) const &&                            //
      noexcept(noexcept(_base::template _apply_r<Ret>(::std::move(*this), FWD(f), FWD(args)...))) // extension
      -> decltype(_base::template _apply_r<Ret>(::std::move(*this), FWD(f), FWD(args)...))
  {
    return _base::template _apply_r<Ret>(::std::move(*this), FWD(f), FWD(args)...);
  }

  /**
   * @brief Eliminates over both states, keyed by the constructor tag naming the state
   *
   * The value arm receives `std::in_place` followed by the value's content - `std::in_place`
   * alone where the value type is `void` - and the error arm receives `fn::unexpect` followed by
   * the error.
   *
   * @param f Callable with arms for both tagged states
   * @param args Additional arguments, appended after the content
   * @return The callable's result
   */
  template <class F, class... Args>
  [[nodiscard]] constexpr auto apply_type(F &&f, Args &&...args) &        //
      noexcept(noexcept(_base::_apply_type(*this, FWD(f), FWD(args)...))) // extension
      -> decltype(_base::_apply_type(*this, FWD(f), FWD(args)...))
  {
    return _base::_apply_type(*this, FWD(f), FWD(args)...);
  }
  template <class F, class... Args>
  [[nodiscard]] constexpr auto apply_type(F &&f, Args &&...args) &&                    //
      noexcept(noexcept(_base::_apply_type(::std::move(*this), FWD(f), FWD(args)...))) // extension
      -> decltype(_base::_apply_type(::std::move(*this), FWD(f), FWD(args)...))
  {
    return _base::_apply_type(::std::move(*this), FWD(f), FWD(args)...);
  }
  template <class F, class... Args>
  [[nodiscard]] constexpr auto apply_type(F &&f, Args &&...args) const &  //
      noexcept(noexcept(_base::_apply_type(*this, FWD(f), FWD(args)...))) // extension
      -> decltype(_base::_apply_type(*this, FWD(f), FWD(args)...))
  {
    return _base::_apply_type(*this, FWD(f), FWD(args)...);
  }
  template <class F, class... Args>
  [[nodiscard]] constexpr auto apply_type(F &&f, Args &&...args) const &&              //
      noexcept(noexcept(_base::_apply_type(::std::move(*this), FWD(f), FWD(args)...))) // extension
      -> decltype(_base::_apply_type(::std::move(*this), FWD(f), FWD(args)...))
  {
    return _base::_apply_type(::std::move(*this), FWD(f), FWD(args)...);
  }

  /**
   * @brief Eliminates over both states, keyed by the constructor tag, converting the result to
   *        `Ret`
   *
   * @tparam Ret Type the results convert to
   * @param f Callable with arms for both tagged states
   * @param args Additional arguments, appended after the content
   * @return The callable's result, converted to `Ret`
   */
  template <class Ret, class F, class... Args>
  [[nodiscard]] constexpr auto apply_type_r(F &&f, Args &&...args) &                      //
      noexcept(noexcept(_base::template _apply_type_r<Ret>(*this, FWD(f), FWD(args)...))) // extension
      -> decltype(_base::template _apply_type_r<Ret>(*this, FWD(f), FWD(args)...))
  {
    return _base::template _apply_type_r<Ret>(*this, FWD(f), FWD(args)...);
  }
  template <class Ret, class F, class... Args>
  [[nodiscard]] constexpr auto apply_type_r(F &&f, Args &&...args) &&                                  //
      noexcept(noexcept(_base::template _apply_type_r<Ret>(::std::move(*this), FWD(f), FWD(args)...))) // extension
      -> decltype(_base::template _apply_type_r<Ret>(::std::move(*this), FWD(f), FWD(args)...))
  {
    return _base::template _apply_type_r<Ret>(::std::move(*this), FWD(f), FWD(args)...);
  }
  template <class Ret, class F, class... Args>
  [[nodiscard]] constexpr auto apply_type_r(F &&f, Args &&...args) const &                //
      noexcept(noexcept(_base::template _apply_type_r<Ret>(*this, FWD(f), FWD(args)...))) // extension
      -> decltype(_base::template _apply_type_r<Ret>(*this, FWD(f), FWD(args)...))
  {
    return _base::template _apply_type_r<Ret>(*this, FWD(f), FWD(args)...);
  }
  template <class Ret, class F, class... Args>
  [[nodiscard]] constexpr auto apply_type_r(F &&f, Args &&...args) const &&                            //
      noexcept(noexcept(_base::template _apply_type_r<Ret>(::std::move(*this), FWD(f), FWD(args)...))) // extension
      -> decltype(_base::template _apply_type_r<Ret>(::std::move(*this), FWD(f), FWD(args)...))
  {
    return _base::template _apply_type_r<Ret>(::std::move(*this), FWD(f), FWD(args)...);
  }

  // Monadic operations. Bodies delegate to _expected_base static helpers, which perform copack-widening.
  /**
   * @brief Binds the value through the callable, which returns an `expected`
   *
   * As the standard member, extended by grading: a plain error side admits a callback returning
   * the identical error type, or its singular lift `copack<E>` - the opt-in to the graded world -
   * while a graded (copack) error side unions the callback's error set into its own. A
   * copack-valued operand dispatches per alternative, exhaustively, heterogeneous branch values
   * joining into a normalized copack. The one bind that widens an error grade.
   *
   * @param f Callable applied on the value, returning an `expected`
   * @return The callback's `expected`, its error side widened by the operand's grade
   */
  template <class F>
  constexpr auto and_then(F &&f) &                        //
      noexcept(noexcept(_base::_and_then(*this, FWD(f)))) // extension
      -> decltype(_base::_and_then(*this, FWD(f)))
  {
    return _base::_and_then(*this, FWD(f));
  }
  template <class F>
  constexpr auto and_then(F &&f) &&                                    //
      noexcept(noexcept(_base::_and_then(::std::move(*this), FWD(f)))) // extension
      -> decltype(_base::_and_then(::std::move(*this), FWD(f)))
  {
    return _base::_and_then(::std::move(*this), FWD(f));
  }
  template <class F>
  constexpr auto and_then(F &&f) const &                  //
      noexcept(noexcept(_base::_and_then(*this, FWD(f)))) // extension
      -> decltype(_base::_and_then(*this, FWD(f)))
  {
    return _base::_and_then(*this, FWD(f));
  }
  template <class F>
  constexpr auto and_then(F &&f) const &&                              //
      noexcept(noexcept(_base::_and_then(::std::move(*this), FWD(f)))) // extension
      -> decltype(_base::_and_then(::std::move(*this), FWD(f)))
  {
    return _base::_and_then(::std::move(*this), FWD(f));
  }

  /**
   * @brief Binds the error through the callable, which returns an `expected`
   *
   * The recovery bind: a successful operand passes through, and the callback maps the error - per
   * alternative when graded, exhaustively - into a new `expected`. The value sides join under the
   * grading rules, a plain side admitting its singular lift `copack<T>`; an error alternative
   * handled by a branch leaves the grade unless re-returned, and on a plain error side the
   * callback's error type replaces the operand's. On the identity `expected` the operation is
   * vacuous: nothing is asked of the handler, not even that it be callable.
   *
   * @param f Callable applied on the error, returning an `expected`
   * @return The recovery's `expected`, its value side joined with the operand's
   */
  template <class F>
  constexpr auto or_else(F &&f) &                        //
      noexcept(noexcept(_base::_or_else(*this, FWD(f)))) // extension
      -> decltype(_base::_or_else(*this, FWD(f)))
  {
    return _base::_or_else(*this, FWD(f));
  }
  template <class F>
  constexpr auto or_else(F &&f) &&                                    //
      noexcept(noexcept(_base::_or_else(::std::move(*this), FWD(f)))) // extension
      -> decltype(_base::_or_else(::std::move(*this), FWD(f)))
  {
    return _base::_or_else(::std::move(*this), FWD(f));
  }
  template <class F>
  constexpr auto or_else(F &&f) const &                  //
      noexcept(noexcept(_base::_or_else(*this, FWD(f)))) // extension
      -> decltype(_base::_or_else(*this, FWD(f)))
  {
    return _base::_or_else(*this, FWD(f));
  }
  template <class F>
  constexpr auto or_else(F &&f) const &&                              //
      noexcept(noexcept(_base::_or_else(::std::move(*this), FWD(f)))) // extension
      -> decltype(_base::_or_else(::std::move(*this), FWD(f)))
  {
    return _base::_or_else(::std::move(*this), FWD(f));
  }

  /**
   * @brief Maps the value through the callable, staying inside the carrier
   *
   * As the standard member, extended over the algebra: a `pack` value spreads into the callable
   * by elements, and a copack-valued operand dispatches per alternative - heterogeneous branch
   * results joining into a normalized copack. Over an uninhabited value side the mapping is the
   * identity, and the callback is neither invoked nor instantiated.
   *
   * @param f Callable applied on the value
   * @return An `expected` holding the callable's result, with the same error side
   */
  template <class F>
  constexpr auto transform(F &&f) &                        //
      noexcept(noexcept(_base::_transform(*this, FWD(f)))) // extension
      -> decltype(_base::_transform(*this, FWD(f)))
  {
    return _base::_transform(*this, FWD(f));
  }
  template <class F>
  constexpr auto transform(F &&f) &&                                    //
      noexcept(noexcept(_base::_transform(::std::move(*this), FWD(f)))) // extension
      -> decltype(_base::_transform(::std::move(*this), FWD(f)))
  {
    return _base::_transform(::std::move(*this), FWD(f));
  }
  template <class F>
  constexpr auto transform(F &&f) const &                  //
      noexcept(noexcept(_base::_transform(*this, FWD(f)))) // extension
      -> decltype(_base::_transform(*this, FWD(f)))
  {
    return _base::_transform(*this, FWD(f));
  }
  template <class F>
  constexpr auto transform(F &&f) const &&                              //
      noexcept(noexcept(_base::_transform(::std::move(*this), FWD(f)))) // extension
      -> decltype(_base::_transform(::std::move(*this), FWD(f)))
  {
    return _base::_transform(::std::move(*this), FWD(f));
  }

  /**
   * @brief Maps the error through the callable, staying inside the carrier
   *
   * As the standard member, extended by grading: over a graded (copack) error side the matching
   * is exhaustive, and the branches may collapse diverse alternatives into one type - the grade
   * narrows to its singular copack - or into a narrower copack. Over the uninhabited `copack<>`
   * error side the mapping is the identity, and the callback is neither invoked nor instantiated.
   *
   * @param f Callable applied on the error
   * @return An `expected` with the same value side and the mapped error side
   */
  template <class F>
  constexpr auto transform_error(F &&f) &                        //
      noexcept(noexcept(_base::_transform_error(*this, FWD(f)))) // extension
      -> decltype(_base::_transform_error(*this, FWD(f)))
  {
    return _base::_transform_error(*this, FWD(f));
  }
  template <class F>
  constexpr auto transform_error(F &&f) &&                                    //
      noexcept(noexcept(_base::_transform_error(::std::move(*this), FWD(f)))) // extension
      -> decltype(_base::_transform_error(::std::move(*this), FWD(f)))
  {
    return _base::_transform_error(::std::move(*this), FWD(f));
  }
  template <class F>
  constexpr auto transform_error(F &&f) const &                  //
      noexcept(noexcept(_base::_transform_error(*this, FWD(f)))) // extension
      -> decltype(_base::_transform_error(*this, FWD(f)))
  {
    return _base::_transform_error(*this, FWD(f));
  }
  template <class F>
  constexpr auto transform_error(F &&f) const &&                              //
      noexcept(noexcept(_base::_transform_error(::std::move(*this), FWD(f)))) // extension
      -> decltype(_base::_transform_error(::std::move(*this), FWD(f)))
  {
    return _base::_transform_error(::std::move(*this), FWD(f));
  }

  // Convert to graded monad. A lifting overload wraps one side in a copack and relocates the other
  // untouched, so it weighs both; the ones whose side already is a copack only return *this.
  /**
   * @brief Lifts the error side into its singular copack: `expected<T, E>` becomes
   *        `expected<T, copack<E>>`
   *
   * The explicit entry into the graded world; an already-graded error side returns `*this`
   * unchanged.
   *
   * @return The graded `expected`, relocating both sides
   */
  constexpr auto
  copack_error() const & noexcept(::std::is_nothrow_constructible_v<value_type, value_type const &>
                                  && ::std::is_nothrow_constructible_v<copack<error_type>, error_type const &>
                                  && ::std::is_nothrow_move_constructible_v<copack<error_type>>) // extension
      -> expected<value_type, copack<error_type>>
    requires(not some_copack<error_type>)
  {
    using type = expected<value_type, copack<error_type>>;
    if (this->has_value())
      return type{::std::in_place, this->value()};
    else
      return type{::fn::unexpect, copack<error_type>(this->error())};
  }
  constexpr auto copack_error() && noexcept(::std::is_nothrow_constructible_v<value_type, value_type>
                                            && ::std::is_nothrow_constructible_v<copack<error_type>, error_type>
                                            && ::std::is_nothrow_move_constructible_v<copack<error_type>>) // extension
      -> expected<value_type, copack<error_type>>
    requires(not some_copack<error_type>)
  {
    using type = expected<value_type, copack<error_type>>;
    if (this->has_value())
      return type{::std::in_place, ::std::move(*this).value()};
    else
      return type{::fn::unexpect, copack<error_type>(::std::move(*this).error())};
  }
  constexpr auto copack_error() & noexcept -> decltype(auto)
    requires(some_copack<error_type>)
  {
    return *this;
  }
  constexpr auto copack_error() const & noexcept -> decltype(auto)
    requires(some_copack<error_type>)
  {
    return *this;
  }
  constexpr auto copack_error() && noexcept -> decltype(auto)
    requires(some_copack<error_type>)
  {
    return ::std::move(*this);
  }
  constexpr auto copack_error() const && noexcept -> decltype(auto)
    requires(some_copack<error_type>)
  {
    return ::std::move(*this);
  }

  /**
   * @brief Lifts the value side into its singular copack: `expected<T, E>` becomes
   *        `expected<copack<T>, E>`
   *
   * The value-side twin of `copack_error`; an already-copack value side returns `*this`
   * unchanged.
   *
   * @return The graded `expected`, relocating both sides
   */
  constexpr auto
  copack_value() const & noexcept(::std::is_nothrow_constructible_v<copack<value_type>, value_type const &>
                                  && ::std::is_nothrow_move_constructible_v<copack<value_type>>
                                  && ::std::is_nothrow_constructible_v<error_type, error_type const &>) // extension
      -> expected<copack<value_type>, error_type>
    requires(not some_copack<value_type>)
  {
    using type = expected<copack<value_type>, error_type>;
    if (this->has_value())
      return type{::std::in_place, copack<value_type>(this->value())};
    else
      return type{::fn::unexpect, this->error()};
  }
  constexpr auto copack_value() && noexcept(::std::is_nothrow_constructible_v<copack<value_type>, value_type>
                                            && ::std::is_nothrow_move_constructible_v<copack<value_type>>
                                            && ::std::is_nothrow_constructible_v<error_type, error_type>) // extension
      -> expected<copack<value_type>, error_type>
    requires(not some_copack<value_type>)
  {
    using type = expected<copack<value_type>, error_type>;
    if (this->has_value())
      return type{::std::in_place, copack<value_type>(::std::move(*this).value())};
    else
      return type{::fn::unexpect, ::std::move(*this).error()};
  }
  constexpr auto copack_value() & noexcept -> decltype(auto)
    requires(some_copack<value_type>)
  {
    return *this;
  }
  constexpr auto copack_value() const & noexcept -> decltype(auto)
    requires(some_copack<value_type>)
  {
    return *this;
  }
  constexpr auto copack_value() && noexcept -> decltype(auto)
    requires(some_copack<value_type>)
  {
    return ::std::move(*this);
  }
  constexpr auto copack_value() const && noexcept -> decltype(auto)
    requires(some_copack<value_type>)
  {
    return ::std::move(*this);
  }

private:
  // Direct-non-list-initializes the value (in_place) or error (unexpect) member from the
  // result of a callable; used by the monadic functions implemented in _expected_base.
  template <class Tag, class Fn, class... Args>
  constexpr explicit expected(::pfn::detail::_expected_from_invoke_t tag, Tag which, Fn &&fn, Args &&...args) //
      noexcept(::std::is_nothrow_constructible_v<_base, ::pfn::detail::_expected_from_invoke_t, Tag, Fn, Args...>)
      : _base(tag, which, FWD(fn), FWD(args)...)
  {
  }
};

/**
 * @brief The `expected` specialization over `void`: success carries no value
 *
 * As the primary, with the value side the unit: success-path callbacks are invoked with no
 * arguments, the `apply` family's value arm receives the trailing arguments alone, and a
 * conjunction elides the void side from the value product.
 *
 * @tparam Err Error type; a `copack` makes the carrier graded
 */
template <typename Err> class expected<void, Err> : private detail::_expected_base<void, Err> {
  using _base = detail::_expected_base<void, Err>;

  template <class, class, class> friend struct ::pfn::detail::_expected_base;
  template <class, class> friend struct ::fn::detail::_expected_base;

public:
  /**
   * @brief The type of the value side
   */
  using value_type = void;
  /**
   * @brief The type of the error side
   */
  using error_type = Err;
  /**
   * @brief The `unexpected` specialization over the error type
   */
  using unexpected_type = ::fn::unexpected<Err>;

  /**
   * @brief This carrier over another value type
   */
  template <class U> using rebind = expected<U, error_type>;

  /**
   * @brief Default constructor
   */
  constexpr expected() noexcept : _base(::std::in_place) {}

  /**
   * @brief Converting constructor from a compatible carrier
   */
  template <class U, class G>
  constexpr explicit(not ::std::is_convertible_v<G const &, Err>) expected(expected<U, G> const &s) //
      noexcept(::std::is_nothrow_constructible_v<Err, G const &>)
    requires(_base::template _can_copy_convert<U, G>::value)
      : _base(s)
  {
  }
  /**
   * @brief Converting constructor from a compatible carrier
   */
  template <class U, class G>
  constexpr explicit(not ::std::is_convertible_v<G, Err>) expected(expected<U, G> &&s) //
      noexcept(::std::is_nothrow_constructible_v<Err, G>)
    requires(_base::template _can_move_convert<U, G>::value)
      : _base(::std::move(s))
  {
  }
  /**
   * @brief Constructs the error from an `unexpected`
   */
  template <class G>
  constexpr explicit(not ::std::is_convertible_v<G const &, Err>) expected(::fn::unexpected<G> const &g) //
      noexcept(::std::is_nothrow_constructible_v<Err, G const &>)
    requires(::std::is_constructible_v<Err, G const &>)
      : _base(::fn::unexpect, ::std::forward<G const &>(g.error()))
  {
  }
  /**
   * @brief Constructs the error from an `unexpected`
   */
  template <class G>
  constexpr explicit(not ::std::is_convertible_v<G, Err>) expected(::fn::unexpected<G> &&g) //
      noexcept(::std::is_nothrow_constructible_v<Err, G>)
    requires(::std::is_constructible_v<Err, G>)
      : _base(::fn::unexpect, ::std::forward<G>(g.error()))
  {
  }

  /**
   * @brief Constructs the value in place from the arguments
   */
  constexpr explicit expected(::std::in_place_t) noexcept : _base(::std::in_place) {}

  /**
   * @brief Constructs the error in place from the arguments
   */
  template <class... Args>
  constexpr explicit expected(::fn::unexpect_t, Args &&...a)    //
      noexcept(::std::is_nothrow_constructible_v<Err, Args...>) //
    requires ::std::is_constructible_v<Err, Args...>
      : _base(::fn::unexpect, FWD(a)...)
  {
  }
  /**
   * @brief Constructs the error in place from the arguments
   */
  template <class U, class... Args>
  constexpr explicit expected(::fn::unexpect_t, ::std::initializer_list<U> il, Args &&...a) //
      noexcept(::std::is_nothrow_constructible_v<Err, ::std::initializer_list<U> &, Args...>)
    requires ::std::is_constructible_v<Err, ::std::initializer_list<U> &, Args...>
      : _base(::fn::unexpect, il, FWD(a)...)
  {
  }

  /**
   * @brief Copy constructor; not available on this carrier
   */
  constexpr expected(expected const &) = delete;
  constexpr expected(expected const &)
    requires(::std::is_copy_constructible_v<Err> && ::std::is_trivially_copy_constructible_v<Err>)
  = default;
  constexpr expected(expected const &s) //
      noexcept(::std::is_nothrow_copy_constructible_v<Err>)
    requires(::std::is_copy_constructible_v<Err> && not ::std::is_trivially_copy_constructible_v<Err>)
      : _base(s.set_, FWD(s).storage_)
  {
  }
  /**
   * @brief Move constructor
   */
  constexpr expected(expected &&s) noexcept
    requires(::std::is_move_constructible_v<Err> && ::std::is_trivially_move_constructible_v<Err>)
  = default;
  constexpr expected(expected &&s) //
      noexcept(::std::is_nothrow_move_constructible_v<Err>)
    requires(::std::is_move_constructible_v<Err> && not ::std::is_trivially_move_constructible_v<Err>)
      : _base(s.set_, FWD(s).storage_)
  {
  }

  /**
   * @brief Destructor
   */
  constexpr ~expected() = default;

  /**
   * @brief Assignment from an `unexpected`
   */
  template <class G>
  constexpr expected &operator=(::fn::unexpected<G> const &s) //
      noexcept(::std::is_nothrow_assignable_v<Err &, G const &> && ::std::is_nothrow_constructible_v<Err, G const &>)
    requires(::std::is_constructible_v<Err, G const &> && ::std::is_assignable_v<Err &, G const &>)
  {
    this->_assign_unexpected(s);
    return *this;
  }
  /**
   * @brief Assignment from an `unexpected`
   */
  template <class G>
  constexpr expected &operator=(::fn::unexpected<G> &&s) //
      noexcept(::std::is_nothrow_assignable_v<Err &, G> && ::std::is_nothrow_constructible_v<Err, G>)
    requires(::std::is_constructible_v<Err, G> && ::std::is_assignable_v<Err &, G>)
  {
    this->_assign_unexpected(::std::move(s));
    return *this;
  }
  /**
   * @brief Copy assignment; not available on this carrier
   */
  constexpr expected &operator=(expected const &) = delete;
  constexpr expected &operator=(expected const &) //
      noexcept(::std::is_nothrow_copy_assignable_v<Err> && ::std::is_nothrow_copy_constructible_v<Err>)
    requires(::std::is_copy_assignable_v<Err> && ::std::is_copy_constructible_v<Err>
             && ::std::is_trivially_copy_constructible_v<Err> && ::std::is_trivially_copy_assignable_v<Err>
             && ::std::is_trivially_destructible_v<Err>)
  = default;
  constexpr expected &operator=(expected const &s) //
      noexcept(::std::is_nothrow_copy_assignable_v<Err> && ::std::is_nothrow_copy_constructible_v<Err>)
    requires(::std::is_copy_assignable_v<Err> && ::std::is_copy_constructible_v<Err>
             && (not ::std::is_trivially_copy_constructible_v<Err> || not ::std::is_trivially_copy_assignable_v<Err>
                 || not ::std::is_trivially_destructible_v<Err>))
  {
    this->_assign(static_cast<_base const &>(s));
    return *this;
  }
  /**
   * @brief Move assignment
   */
  constexpr expected &operator=(expected &&) //
      noexcept(::std::is_nothrow_move_assignable_v<Err> && ::std::is_nothrow_move_constructible_v<Err>)
    requires(::std::is_move_constructible_v<Err> && ::std::is_move_assignable_v<Err>
             && ::std::is_trivially_move_constructible_v<Err> && ::std::is_trivially_move_assignable_v<Err>
             && ::std::is_trivially_destructible_v<Err>)
  = default;
  constexpr expected &operator=(expected &&s) //
      noexcept(::std::is_nothrow_move_assignable_v<Err> && ::std::is_nothrow_move_constructible_v<Err>)
    requires(::std::is_move_constructible_v<Err> && ::std::is_move_assignable_v<Err>
             && (not ::std::is_trivially_move_constructible_v<Err> || not ::std::is_trivially_move_assignable_v<Err>
                 || not ::std::is_trivially_destructible_v<Err>))
  {
    this->_assign(static_cast<_base &&>(s));
    return *this;
  }

  using _base::emplace;

  /**
   * @brief Swaps the contents with another `expected`
   */
  constexpr void swap(expected &rhs) //
      noexcept(::std::is_nothrow_move_constructible_v<Err> && ::std::is_nothrow_swappable_v<Err>)
    requires(::std::is_swappable_v<Err> && ::std::is_move_constructible_v<Err>)
  {
    this->_swap_with(rhs);
  }

  using _base::operator*;
  using _base::operator bool;
  using _base::error;
  using _base::error_or;
  using _base::has_error;
  using _base::has_value;
  using _base::value;

  /**
   * @brief Eliminates over both states: the active side routes into the callable
   *
   * The value arm receives nothing - success carries no value - so it is invoked with the
   * trailing arguments alone, and the error arm receives the error as `fn::apply` hands it
   * over; the arms must yield one result type. Over an uninhabited error side the value arm
   * alone is exhaustive.
   *
   * @param f Callable with arms for both states; `fn::overload` fuses them
   * @param args Additional arguments, appended after the content
   * @return The callable's result
   */
  template <class F, class... Args>
  [[nodiscard]] constexpr auto apply(F &&f, Args &&...args) &        //
      noexcept(noexcept(_base::_apply(*this, FWD(f), FWD(args)...))) // extension
      -> decltype(_base::_apply(*this, FWD(f), FWD(args)...))
  {
    return _base::_apply(*this, FWD(f), FWD(args)...);
  }
  template <class F, class... Args>
  [[nodiscard]] constexpr auto apply(F &&f, Args &&...args) &&                    //
      noexcept(noexcept(_base::_apply(::std::move(*this), FWD(f), FWD(args)...))) // extension
      -> decltype(_base::_apply(::std::move(*this), FWD(f), FWD(args)...))
  {
    return _base::_apply(::std::move(*this), FWD(f), FWD(args)...);
  }
  template <class F, class... Args>
  [[nodiscard]] constexpr auto apply(F &&f, Args &&...args) const &  //
      noexcept(noexcept(_base::_apply(*this, FWD(f), FWD(args)...))) // extension
      -> decltype(_base::_apply(*this, FWD(f), FWD(args)...))
  {
    return _base::_apply(*this, FWD(f), FWD(args)...);
  }
  template <class F, class... Args>
  [[nodiscard]] constexpr auto apply(F &&f, Args &&...args) const &&              //
      noexcept(noexcept(_base::_apply(::std::move(*this), FWD(f), FWD(args)...))) // extension
      -> decltype(_base::_apply(::std::move(*this), FWD(f), FWD(args)...))
  {
    return _base::_apply(::std::move(*this), FWD(f), FWD(args)...);
  }

  /**
   * @brief Eliminates over both states, converting the result to `Ret`
   *
   * @tparam Ret Type the results convert to
   * @param f Callable with arms for both states; `fn::overload` fuses them
   * @param args Additional arguments, appended after the content
   * @return The callable's result, converted to `Ret`
   */
  template <class Ret, class F, class... Args>
  [[nodiscard]] constexpr auto apply_r(F &&f, Args &&...args) &                      //
      noexcept(noexcept(_base::template _apply_r<Ret>(*this, FWD(f), FWD(args)...))) // extension
      -> decltype(_base::template _apply_r<Ret>(*this, FWD(f), FWD(args)...))
  {
    return _base::template _apply_r<Ret>(*this, FWD(f), FWD(args)...);
  }
  template <class Ret, class F, class... Args>
  [[nodiscard]] constexpr auto apply_r(F &&f, Args &&...args) &&                                  //
      noexcept(noexcept(_base::template _apply_r<Ret>(::std::move(*this), FWD(f), FWD(args)...))) // extension
      -> decltype(_base::template _apply_r<Ret>(::std::move(*this), FWD(f), FWD(args)...))
  {
    return _base::template _apply_r<Ret>(::std::move(*this), FWD(f), FWD(args)...);
  }
  template <class Ret, class F, class... Args>
  [[nodiscard]] constexpr auto apply_r(F &&f, Args &&...args) const &                //
      noexcept(noexcept(_base::template _apply_r<Ret>(*this, FWD(f), FWD(args)...))) // extension
      -> decltype(_base::template _apply_r<Ret>(*this, FWD(f), FWD(args)...))
  {
    return _base::template _apply_r<Ret>(*this, FWD(f), FWD(args)...);
  }
  template <class Ret, class F, class... Args>
  [[nodiscard]] constexpr auto apply_r(F &&f, Args &&...args) const &&                            //
      noexcept(noexcept(_base::template _apply_r<Ret>(::std::move(*this), FWD(f), FWD(args)...))) // extension
      -> decltype(_base::template _apply_r<Ret>(::std::move(*this), FWD(f), FWD(args)...))
  {
    return _base::template _apply_r<Ret>(::std::move(*this), FWD(f), FWD(args)...);
  }

  /**
   * @brief Eliminates over both states, keyed by the constructor tag naming the state
   *
   * The value arm receives `std::in_place` alone, there being no content to follow it, and the
   * error arm receives `fn::unexpect` followed by the error.
   *
   * @param f Callable with arms for both tagged states
   * @param args Additional arguments, appended after the content
   * @return The callable's result
   */
  template <class F, class... Args>
  [[nodiscard]] constexpr auto apply_type(F &&f, Args &&...args) &        //
      noexcept(noexcept(_base::_apply_type(*this, FWD(f), FWD(args)...))) // extension
      -> decltype(_base::_apply_type(*this, FWD(f), FWD(args)...))
  {
    return _base::_apply_type(*this, FWD(f), FWD(args)...);
  }
  template <class F, class... Args>
  [[nodiscard]] constexpr auto apply_type(F &&f, Args &&...args) &&                    //
      noexcept(noexcept(_base::_apply_type(::std::move(*this), FWD(f), FWD(args)...))) // extension
      -> decltype(_base::_apply_type(::std::move(*this), FWD(f), FWD(args)...))
  {
    return _base::_apply_type(::std::move(*this), FWD(f), FWD(args)...);
  }
  template <class F, class... Args>
  [[nodiscard]] constexpr auto apply_type(F &&f, Args &&...args) const &  //
      noexcept(noexcept(_base::_apply_type(*this, FWD(f), FWD(args)...))) // extension
      -> decltype(_base::_apply_type(*this, FWD(f), FWD(args)...))
  {
    return _base::_apply_type(*this, FWD(f), FWD(args)...);
  }
  template <class F, class... Args>
  [[nodiscard]] constexpr auto apply_type(F &&f, Args &&...args) const &&              //
      noexcept(noexcept(_base::_apply_type(::std::move(*this), FWD(f), FWD(args)...))) // extension
      -> decltype(_base::_apply_type(::std::move(*this), FWD(f), FWD(args)...))
  {
    return _base::_apply_type(::std::move(*this), FWD(f), FWD(args)...);
  }

  /**
   * @brief Eliminates over both states, keyed by the constructor tag, converting the result to
   *        `Ret`
   *
   * @tparam Ret Type the results convert to
   * @param f Callable with arms for both tagged states
   * @param args Additional arguments, appended after the content
   * @return The callable's result, converted to `Ret`
   */
  template <class Ret, class F, class... Args>
  [[nodiscard]] constexpr auto apply_type_r(F &&f, Args &&...args) &                      //
      noexcept(noexcept(_base::template _apply_type_r<Ret>(*this, FWD(f), FWD(args)...))) // extension
      -> decltype(_base::template _apply_type_r<Ret>(*this, FWD(f), FWD(args)...))
  {
    return _base::template _apply_type_r<Ret>(*this, FWD(f), FWD(args)...);
  }
  template <class Ret, class F, class... Args>
  [[nodiscard]] constexpr auto apply_type_r(F &&f, Args &&...args) &&                                  //
      noexcept(noexcept(_base::template _apply_type_r<Ret>(::std::move(*this), FWD(f), FWD(args)...))) // extension
      -> decltype(_base::template _apply_type_r<Ret>(::std::move(*this), FWD(f), FWD(args)...))
  {
    return _base::template _apply_type_r<Ret>(::std::move(*this), FWD(f), FWD(args)...);
  }
  template <class Ret, class F, class... Args>
  [[nodiscard]] constexpr auto apply_type_r(F &&f, Args &&...args) const &                //
      noexcept(noexcept(_base::template _apply_type_r<Ret>(*this, FWD(f), FWD(args)...))) // extension
      -> decltype(_base::template _apply_type_r<Ret>(*this, FWD(f), FWD(args)...))
  {
    return _base::template _apply_type_r<Ret>(*this, FWD(f), FWD(args)...);
  }
  template <class Ret, class F, class... Args>
  [[nodiscard]] constexpr auto apply_type_r(F &&f, Args &&...args) const &&                            //
      noexcept(noexcept(_base::template _apply_type_r<Ret>(::std::move(*this), FWD(f), FWD(args)...))) // extension
      -> decltype(_base::template _apply_type_r<Ret>(::std::move(*this), FWD(f), FWD(args)...))
  {
    return _base::template _apply_type_r<Ret>(::std::move(*this), FWD(f), FWD(args)...);
  }

  // Bodies delegate to _expected_base static helpers, which perform copack-widening.

  /**
   * @brief Binds through the callable, invoked with no arguments, which returns an `expected`
   *
   * As the standard member, extended by grading: a plain error side admits a callback returning
   * the identical error type, or its singular lift `copack<E>` - the opt-in to the graded world -
   * while a graded (copack) error side unions the callback's error set into its own. Over the
   * uninhabited `copack<>` error side the operand passes through and the callback is neither
   * invoked nor instantiated.
   *
   * @param f Callable taking no arguments, returning an `expected`
   * @return The callback's `expected`, its error side widened by the operand's grade
   */
  template <class F>
  constexpr auto and_then(F &&f) &                        //
      noexcept(noexcept(_base::_and_then(*this, FWD(f)))) // extension
      -> decltype(_base::_and_then(*this, FWD(f)))
  {
    return _base::_and_then(*this, FWD(f));
  }
  template <class F>
  constexpr auto and_then(F &&f) &&                                    //
      noexcept(noexcept(_base::_and_then(::std::move(*this), FWD(f)))) // extension
      -> decltype(_base::_and_then(::std::move(*this), FWD(f)))
  {
    return _base::_and_then(::std::move(*this), FWD(f));
  }
  template <class F>
  constexpr auto and_then(F &&f) const &                  //
      noexcept(noexcept(_base::_and_then(*this, FWD(f)))) // extension
      -> decltype(_base::_and_then(*this, FWD(f)))
  {
    return _base::_and_then(*this, FWD(f));
  }
  template <class F>
  constexpr auto and_then(F &&f) const &&                              //
      noexcept(noexcept(_base::_and_then(::std::move(*this), FWD(f)))) // extension
      -> decltype(_base::_and_then(::std::move(*this), FWD(f)))
  {
    return _base::_and_then(::std::move(*this), FWD(f));
  }

  /**
   * @brief Binds the error through the callable, which returns an `expected`
   *
   * The recovery bind: a successful operand passes through, and the callback maps the error - per
   * alternative when graded, exhaustively - into a new `expected`. A callback returning a value
   * side leaves this carrier for that one; on a plain error side the callback's error type
   * replaces the operand's. Over the uninhabited `copack<>` error side the operation is vacuous:
   * nothing is asked of the handler, not even that it be callable.
   *
   * @param f Callable applied on the error, returning an `expected`
   * @return The callback's `expected`, or the operand unchanged where it holds success
   */
  template <class F>
  constexpr auto or_else(F &&f) &                        //
      noexcept(noexcept(_base::_or_else(*this, FWD(f)))) // extension
      -> decltype(_base::_or_else(*this, FWD(f)))
  {
    return _base::_or_else(*this, FWD(f));
  }
  template <class F>
  constexpr auto or_else(F &&f) &&                                    //
      noexcept(noexcept(_base::_or_else(::std::move(*this), FWD(f)))) // extension
      -> decltype(_base::_or_else(::std::move(*this), FWD(f)))
  {
    return _base::_or_else(::std::move(*this), FWD(f));
  }
  template <class F>
  constexpr auto or_else(F &&f) const &                  //
      noexcept(noexcept(_base::_or_else(*this, FWD(f)))) // extension
      -> decltype(_base::_or_else(*this, FWD(f)))
  {
    return _base::_or_else(*this, FWD(f));
  }
  template <class F>
  constexpr auto or_else(F &&f) const &&                              //
      noexcept(noexcept(_base::_or_else(::std::move(*this), FWD(f)))) // extension
      -> decltype(_base::_or_else(::std::move(*this), FWD(f)))
  {
    return _base::_or_else(::std::move(*this), FWD(f));
  }

  /**
   * @brief Maps through the callable, invoked with no arguments, staying inside the carrier
   *
   * The callable's result becomes the new value side, so a callback returning `void` leaves the
   * carrier's value side `void` and any other return type gives it one. The error side is
   * untouched, and an operand holding an error passes through uninvoked.
   *
   * @param f Callable taking no arguments
   * @return An `expected` over the callable's result type, with the same error side
   */
  template <class F>
  constexpr auto transform(F &&f) &                        //
      noexcept(noexcept(_base::_transform(*this, FWD(f)))) // extension
      -> decltype(_base::_transform(*this, FWD(f)))
  {
    return _base::_transform(*this, FWD(f));
  }
  template <class F>
  constexpr auto transform(F &&f) &&                                    //
      noexcept(noexcept(_base::_transform(::std::move(*this), FWD(f)))) // extension
      -> decltype(_base::_transform(::std::move(*this), FWD(f)))
  {
    return _base::_transform(::std::move(*this), FWD(f));
  }
  template <class F>
  constexpr auto transform(F &&f) const &                  //
      noexcept(noexcept(_base::_transform(*this, FWD(f)))) // extension
      -> decltype(_base::_transform(*this, FWD(f)))
  {
    return _base::_transform(*this, FWD(f));
  }
  template <class F>
  constexpr auto transform(F &&f) const &&                              //
      noexcept(noexcept(_base::_transform(::std::move(*this), FWD(f)))) // extension
      -> decltype(_base::_transform(::std::move(*this), FWD(f)))
  {
    return _base::_transform(::std::move(*this), FWD(f));
  }

  /**
   * @brief Maps the error through the callable, staying inside the carrier
   *
   * As the standard member, extended by grading: over a graded (copack) error side the matching
   * is exhaustive, and the branches may collapse diverse alternatives into one type - the grade
   * narrows to its singular copack - or into a narrower copack. Over the uninhabited `copack<>`
   * error side the mapping is the identity, and the callback is neither invoked nor instantiated.
   *
   * @param f Callable applied on the error
   * @return An `expected` over `void` with the mapped error side
   */
  template <class F>
  constexpr auto transform_error(F &&f) &                        //
      noexcept(noexcept(_base::_transform_error(*this, FWD(f)))) // extension
      -> decltype(_base::_transform_error(*this, FWD(f)))
  {
    return _base::_transform_error(*this, FWD(f));
  }
  template <class F>
  constexpr auto transform_error(F &&f) &&                                    //
      noexcept(noexcept(_base::_transform_error(::std::move(*this), FWD(f)))) // extension
      -> decltype(_base::_transform_error(::std::move(*this), FWD(f)))
  {
    return _base::_transform_error(::std::move(*this), FWD(f));
  }
  template <class F>
  constexpr auto transform_error(F &&f) const &                  //
      noexcept(noexcept(_base::_transform_error(*this, FWD(f)))) // extension
      -> decltype(_base::_transform_error(*this, FWD(f)))
  {
    return _base::_transform_error(*this, FWD(f));
  }
  template <class F>
  constexpr auto transform_error(F &&f) const &&                              //
      noexcept(noexcept(_base::_transform_error(::std::move(*this), FWD(f)))) // extension
      -> decltype(_base::_transform_error(::std::move(*this), FWD(f)))
  {
    return _base::_transform_error(::std::move(*this), FWD(f));
  }

  /**
   * @brief Lifts the error side into its singular copack: `expected<void, E>` becomes
   *        `expected<void, copack<E>>`
   *
   * The explicit opt-in to the graded world. There is no value to relocate here, so only the
   * error's lift weighs; an already-graded error side returns `*this` unchanged.
   *
   * @return The same carrier with its error side graded
   */
  constexpr auto
  copack_error() const & noexcept(::std::is_nothrow_constructible_v<copack<error_type>, error_type const &>
                                  && ::std::is_nothrow_move_constructible_v<copack<error_type>>) // extension
      -> expected<value_type, copack<error_type>>
    requires(not some_copack<error_type>)
  {
    using type = expected<value_type, copack<error_type>>;
    if (this->has_value())
      return type{::std::in_place};
    else
      return type{::fn::unexpect, copack<error_type>(this->error())};
  }
  constexpr auto copack_error() && noexcept(::std::is_nothrow_constructible_v<copack<error_type>, error_type>
                                            && ::std::is_nothrow_move_constructible_v<copack<error_type>>) // extension
      -> expected<value_type, copack<error_type>>
    requires(not some_copack<error_type>)
  {
    using type = expected<value_type, copack<error_type>>;
    if (this->has_value())
      return type{::std::in_place};
    else
      return type{::fn::unexpect, copack<error_type>(::std::move(*this).error())};
  }
  constexpr auto copack_error() & noexcept -> decltype(auto)
    requires(some_copack<error_type>)
  {
    return *this;
  }
  constexpr auto copack_error() const & noexcept -> decltype(auto)
    requires(some_copack<error_type>)
  {
    return *this;
  }
  constexpr auto copack_error() && noexcept -> decltype(auto)
    requires(some_copack<error_type>)
  {
    return ::std::move(*this);
  }
  constexpr auto copack_error() const && noexcept -> decltype(auto)
    requires(some_copack<error_type>)
  {
    return ::std::move(*this);
  }

private:
  // Direct-non-list-initializes the error member from the result of a callable; used by the
  // monadic functions implemented in _expected_base.
  template <class Tag, class Fn, class... Args>
  constexpr explicit expected(::pfn::detail::_expected_from_invoke_t tag, Tag which, Fn &&fn, Args &&...args) //
      noexcept(::std::is_nothrow_constructible_v<_base, ::pfn::detail::_expected_from_invoke_t, Tag, Fn, Args...>)
      : _base(tag, which, FWD(fn), FWD(args)...)
  {
  }
};

/**
 * @brief The unit of the `expected` family: a carrier over `void` whose error side is uninhabited
 *
 * It always holds its empty value - `copack<>` offers no alternative to fail with - so it belongs to
 * the identity cluster, and `operator&` elides it from a product.
 */
using expected_unit = expected<void, copack<>>;

// The comparison against a value, at namespace scope for the reason given where its siblings are
// declared in pfn: it is the one equality operator constrained on the OTHER operand, and that is
// safe only where this operand is deduced.
/**
 * @brief Compares an `expected` against a value; a failed `expected` equals nothing
 */
template <typename T, typename Err, typename T2>
  requires(not ::std::is_void_v<T> && not detail::_is_some_expected<T2 &>)
constexpr bool operator==(expected<T, Err> const &x, T2 const &v) //
    noexcept(noexcept(::pfn::detail::_implicit_to_bool(*x == v))) // extension
  requires requires {
    { *x == v } -> ::std::convertible_to<bool>;
  }
{
  if (!x.has_value())
    return false;
  return *x == v;
}

/**
 * @brief Free-function form of the member `copack_value` lift
 *
 * @param src The `expected` to lift
 * @return `src.copack_value()`
 */
[[nodiscard]] constexpr auto copack_value(some_expected_non_void auto &&src) noexcept(noexcept(FWD(src).copack_value()))
    -> decltype(auto)
{
  return FWD(src).copack_value();
}

/**
 * @brief Free-function form of the member `copack_error` lift
 *
 * @param src The `expected` to lift
 * @return `src.copack_error()`
 */
[[nodiscard]] constexpr auto copack_error(some_expected auto &&src) noexcept(noexcept(FWD(src).copack_error()))
    -> decltype(auto)
{
  return FWD(src).copack_error();
}

namespace detail {
template <typename E> struct _expected_type {
  template <typename T> using type = ::fn::expected<T, E>;
};

// `error()` throws when the expected holds a value, but every arm below is reached only once
// `has_value()` has answered - so these ask what constructing the result promises, with the accessor
// spelled as a type rather than as a call which would drag its own throw in.
template <typename Type, typename Lh, typename Rh, typename... Vs>
constexpr inline bool _nothrow_join_expected
    = _nothrow_initializable<Type, ::std::in_place_t, Vs...>
      && _nothrow_initializable<Type, ::fn::unexpect_t, decltype(::std::declval<Lh>().error())>
      && _nothrow_initializable<Type, ::fn::unexpect_t, decltype(::std::declval<Rh>().error())>;

// Lifting an operand's error into a widened error type, through the copack<> guard of _nothrow_arm
// (the joins below assert the same unreachability with pfn::unreachable).
template <typename Src, typename Err>
constexpr inline bool _nothrow_error_lift
    = _nothrow_arm<typename ::std::remove_cvref_t<Src>::error_type, Err, decltype(::std::declval<Src>().error())>;

template <typename Type, typename Err, typename Lh, typename Rh, typename... Vs>
constexpr inline bool _nothrow_join_widened = _nothrow_initializable<Type, ::std::in_place_t, Vs...>
                                              && (_nothrow_error_lift<Lh, Err> && _nothrow_error_lift<Rh, Err>)
                                              && _nothrow_initializable<Type, ::fn::unexpect_t, Err>;

// A named type, not a lambda: `operator&` specifies itself in terms of what lifting the error
// promises, and a lambda can be named neither in a noexcept-specifier nor (before clang 17) in any
// unevaluated operand at all.
template <typename E> struct _expected_efn final {
  // Explicit return type: for a copack<> (never-erroring) operand the else branch is the only one
  // instantiated, and without this it would deduce void - poisoning _join's return-type deduction.
  [[nodiscard]] constexpr auto operator()(auto &&v) const noexcept(_nothrow_error_lift<decltype(v), unexpected<E>>)
      -> ::fn::unexpected<E>
  {
    if constexpr (not ::std::is_same_v<typename ::std::remove_cvref_t<decltype(v)>::error_type, copack<>>) {
      return ::fn::unexpected<E>(FWD(v).error());
    } else {
      ::pfn::unreachable(); // LCOV_EXCL_LINE
    }
  }
};
} // namespace detail

// The conjunction of fallible carriers: values multiply into a `pack`, errors sum into a
//        `copack`
//
// `a & b` succeeds only if both operands succeed, the values folding into one `pack` - a `void`
// side elides, and a copack value distributes into a copack of packs - while at runtime the error
// side holds the leftmost failing operand's error. Two identical error types stay as they are;
// any other pair sums into their normalized `copack_for`, grading not required of the operands.
// Both operands are fully constructed before the operator runs: an error-selection rule, not
// short-circuiting. An identity-cluster operand contributes its value and no error term.
// When any of the sides is expected<void, ...>, we do not produce expected<pack<...>, ...>
// Instead just elide void and carry non-void (or elide both voids if that's what we get)
template <typename Lh, typename Rh>
  requires some_expected_void<Lh> && (not some_expected_void<Rh>)
           && ::std::is_same_v<typename ::std::remove_cvref_t<Lh>::error_type,
                               typename ::std::remove_cvref_t<Rh>::error_type>
[[nodiscard]] constexpr auto operator&(Lh &&lh, Rh &&rh) //
    noexcept(detail::_nothrow_join_expected<
             expected<typename ::std::remove_cvref_t<Rh>::value_type, typename ::std::remove_cvref_t<Lh>::error_type>,
             Lh, Rh, decltype(FWD(rh).value())>)
{
  using error_type = ::std::remove_cvref_t<Lh>::error_type;
  using value_type = ::std::remove_cvref_t<Rh>::value_type;
  using type = expected<value_type, error_type>;
  if (lh.has_value() && rh.has_value())
    return type{::std::in_place, FWD(rh).value()};
  else if (not lh.has_value())
    return type{::fn::unexpect, FWD(lh).error()};
  else
    return type{::fn::unexpect, FWD(rh).error()};
}

template <typename Lh, typename Rh>
  requires some_expected_void<Lh> && (not some_expected_void<Rh>)
           && (not ::std::is_same_v<typename ::std::remove_cvref_t<Lh>::error_type,
                                    typename ::std::remove_cvref_t<Rh>::error_type>)
[[nodiscard]] constexpr auto operator&(Lh &&lh, Rh &&rh) //
    noexcept(detail::_nothrow_join_widened<
             expected<typename ::std::remove_cvref_t<Rh>::value_type,
                      copack_for<typename ::std::remove_cvref_t<Lh>::error_type,
                                 typename ::std::remove_cvref_t<Rh>::error_type>>,
             copack_for<typename ::std::remove_cvref_t<Lh>::error_type, typename ::std::remove_cvref_t<Rh>::error_type>,
             Lh, Rh, decltype(FWD(rh).value())>)
{
  using new_error_type
      = copack_for<typename ::std::remove_cvref_t<Lh>::error_type, typename ::std::remove_cvref_t<Rh>::error_type>;
  using value_type = ::std::remove_cvref_t<Rh>::value_type;
  using type = expected<value_type, new_error_type>;
  if (lh.has_value() && rh.has_value())
    return type{::std::in_place, FWD(rh).value()};
  else if (not lh.has_value()) {
    if constexpr (not ::std::is_same_v<typename ::std::remove_cvref_t<Lh>::error_type, copack<>>)
      return type{::fn::unexpect, new_error_type{FWD(lh).error()}};
    else
      ::pfn::unreachable(); // LCOV_EXCL_LINE
  } else {
    if constexpr (not ::std::is_same_v<typename ::std::remove_cvref_t<Rh>::error_type, copack<>>)
      return type{::fn::unexpect, new_error_type{FWD(rh).error()}};
    else
      ::pfn::unreachable(); // LCOV_EXCL_LINE
  }
}

template <typename Lh, typename Rh>
  requires(not some_expected_void<Lh>) && some_expected_void<Rh>
          && ::std::is_same_v<typename ::std::remove_cvref_t<Lh>::error_type,
                              typename ::std::remove_cvref_t<Rh>::error_type>
[[nodiscard]] constexpr auto operator&(Lh &&lh, Rh &&rh) //
    noexcept(detail::_nothrow_join_expected<
             expected<typename ::std::remove_cvref_t<Lh>::value_type, typename ::std::remove_cvref_t<Lh>::error_type>,
             Lh, Rh, decltype(FWD(lh).value())>)
{
  using error_type = ::std::remove_cvref_t<Lh>::error_type;
  using value_type = ::std::remove_cvref_t<Lh>::value_type;
  using type = expected<value_type, error_type>;
  if (lh.has_value() && rh.has_value())
    return type{::std::in_place, FWD(lh).value()};
  else if (not lh.has_value())
    return type{::fn::unexpect, FWD(lh).error()};
  else
    return type{::fn::unexpect, FWD(rh).error()};
}

template <typename Lh, typename Rh>
  requires(not some_expected_void<Lh>) && some_expected_void<Rh>
          && (not ::std::is_same_v<typename ::std::remove_cvref_t<Lh>::error_type,
                                   typename ::std::remove_cvref_t<Rh>::error_type>)
[[nodiscard]] constexpr auto operator&(Lh &&lh, Rh &&rh) //
    noexcept(detail::_nothrow_join_widened<
             expected<typename ::std::remove_cvref_t<Lh>::value_type,
                      copack_for<typename ::std::remove_cvref_t<Lh>::error_type,
                                 typename ::std::remove_cvref_t<Rh>::error_type>>,
             copack_for<typename ::std::remove_cvref_t<Lh>::error_type, typename ::std::remove_cvref_t<Rh>::error_type>,
             Lh, Rh, decltype(FWD(lh).value())>)
{
  using new_error_type
      = copack_for<typename ::std::remove_cvref_t<Lh>::error_type, typename ::std::remove_cvref_t<Rh>::error_type>;
  using value_type = ::std::remove_cvref_t<Lh>::value_type;
  using type = expected<value_type, new_error_type>;
  if (lh.has_value() && rh.has_value())
    return type{::std::in_place, FWD(lh).value()};
  else if (not lh.has_value()) {
    if constexpr (not ::std::is_same_v<typename ::std::remove_cvref_t<Lh>::error_type, copack<>>)
      return type{::fn::unexpect, new_error_type{FWD(lh).error()}};
    else
      ::pfn::unreachable(); // LCOV_EXCL_LINE
  } else {
    if constexpr (not ::std::is_same_v<typename ::std::remove_cvref_t<Rh>::error_type, copack<>>)
      return type{::fn::unexpect, new_error_type{FWD(rh).error()}};
    else
      ::pfn::unreachable(); // LCOV_EXCL_LINE
  }
}

template <typename Lh, typename Rh>
  requires some_expected_void<Lh> && some_expected_void<Rh>
           && ::std::is_same_v<typename ::std::remove_cvref_t<Lh>::error_type,
                               typename ::std::remove_cvref_t<Rh>::error_type>
[[nodiscard]] constexpr auto operator&(Lh &&lh, Rh &&rh) //
    noexcept(detail::_nothrow_join_expected<expected<void, typename ::std::remove_cvref_t<Lh>::error_type>, Lh, Rh>)
{
  using error_type = ::std::remove_cvref_t<Lh>::error_type;
  using type = expected<void, error_type>;
  if (lh.has_value() && rh.has_value())
    return type{::std::in_place};
  else if (not lh.has_value())
    return type{::fn::unexpect, FWD(lh).error()};
  else
    return type{::fn::unexpect, FWD(rh).error()};
}

template <typename Lh, typename Rh>
  requires some_expected_void<Lh> && some_expected_void<Rh>
           && (not ::std::is_same_v<typename ::std::remove_cvref_t<Lh>::error_type,
                                    typename ::std::remove_cvref_t<Rh>::error_type>)
[[nodiscard]] constexpr auto operator&(Lh &&lh, Rh &&rh) //
    noexcept(detail::_nothrow_join_widened<
             expected<void, copack_for<typename ::std::remove_cvref_t<Lh>::error_type,
                                       typename ::std::remove_cvref_t<Rh>::error_type>>,
             copack_for<typename ::std::remove_cvref_t<Lh>::error_type, typename ::std::remove_cvref_t<Rh>::error_type>,
             Lh, Rh>)
{
  using new_error_type
      = copack_for<typename ::std::remove_cvref_t<Lh>::error_type, typename ::std::remove_cvref_t<Rh>::error_type>;
  using type = expected<void, new_error_type>;
  if (lh.has_value() && rh.has_value())
    return type{::std::in_place};
  else if (not lh.has_value()) {
    if constexpr (not ::std::is_same_v<typename ::std::remove_cvref_t<Lh>::error_type, copack<>>)
      return type{::fn::unexpect, new_error_type{FWD(lh).error()}};
    else
      ::pfn::unreachable(); // LCOV_EXCL_LINE
  } else {
    if constexpr (not ::std::is_same_v<typename ::std::remove_cvref_t<Rh>::error_type, copack<>>)
      return type{::fn::unexpect, new_error_type{FWD(rh).error()}};
    else
      ::pfn::unreachable(); // LCOV_EXCL_LINE
  }
}

// Overloads when both sides are non-void, producing either of
// expected<pack<...>, ...> or expected<copack<pack<...>, pack...>, ...>
template <typename Lh, typename Rh>
  requires(not some_expected_void<Lh>) && (not some_expected_void<Rh>)
          && ::std::is_same_v<typename ::std::remove_cvref_t<Lh>::error_type,
                              typename ::std::remove_cvref_t<Rh>::error_type>
[[nodiscard]] constexpr auto operator&(Lh &&lh, Rh &&rh) //
    noexcept(noexcept(::fn::detail::_join<
                      detail::template _expected_type<typename ::std::remove_cvref_t<Lh>::error_type>::template type>(
        FWD(lh), FWD(rh), detail::_expected_efn<typename ::std::remove_cvref_t<Lh>::error_type>{})))
{
  using error_type = ::std::remove_cvref_t<Lh>::error_type;
  return ::fn::detail::_join<detail::template _expected_type<error_type>::template type>(
      FWD(lh), FWD(rh), detail::_expected_efn<error_type>{});
}

template <typename Lh, typename Rh>
  requires(not some_expected_void<Lh>) && (not some_expected_void<Rh>)
          && (not ::std::is_same_v<typename ::std::remove_cvref_t<Lh>::error_type,
                                   typename ::std::remove_cvref_t<Rh>::error_type>)
[[nodiscard]] constexpr auto operator&(Lh &&lh, Rh &&rh) //
    noexcept(noexcept(
        ::fn::detail::_join<
            detail::template _expected_type<copack_for<typename ::std::remove_cvref_t<Lh>::error_type,
                                                       typename ::std::remove_cvref_t<Rh>::error_type>>::template type>(
            FWD(lh), FWD(rh),
            detail::_expected_efn<copack_for<typename ::std::remove_cvref_t<Lh>::error_type,
                                             typename ::std::remove_cvref_t<Rh>::error_type>>{})))
{
  using new_error_type
      = copack_for<typename ::std::remove_cvref_t<Lh>::error_type, typename ::std::remove_cvref_t<Rh>::error_type>;
  return ::fn::detail::_join<detail::template _expected_type<new_error_type>::template type>(
      FWD(lh), FWD(rh), detail::_expected_efn<new_error_type>{});
}

namespace detail {
// The cluster conjunction's specification: the cluster operand always contributes its value, so
// only the expected operand's channels weigh - its error relocating unchanged into the result.
template <bool Uninhabited, typename Type, typename Lh, typename Rh, typename Err> struct _nothrow_amp_cluster {
  static constexpr bool value = _nothrow_initializable<Type, ::fn::unexpect_t, Err>;
};
template <typename Type, typename Lh, typename Rh, typename Err> struct _nothrow_amp_cluster<false, Type, Lh, Rh, Err> {
  static constexpr bool value
      = noexcept(::fn::detail::_fold_detail::fold<typename ::std::remove_cvref_t<Lh>::value_type,
                                                  typename ::std::remove_cvref_t<Rh>::value_type>(
            ::std::declval<::fn::detail::_value_of_t<Lh>>(), ::std::declval<::fn::detail::_value_of_t<Rh>>()))
        && _nothrow_initializable<Type, ::std::in_place_t, ::fn::detail::_joined_t<Lh, Rh>>
        && _nothrow_initializable<Type, ::fn::unexpect_t, Err>;
};
} // namespace detail

// The identity cluster in the conjunction: a just or choice operand always contributes its value
// to the product and adds no term to the error sum - the expected operand's error passes through
// unchanged, plain or graded, and its state alone decides. just<void> is the product's unit and
// elides.
template <typename Lh, some_expected Rh>
  requires(::fn::detail::_some_just<Lh> || ::fn::detail::_some_choice<Lh>)
          && (not ::std::is_void_v<typename ::std::remove_cvref_t<Lh>::value_type>) && (not some_expected_void<Rh>)
[[nodiscard]] constexpr auto operator&(Lh &&lh, Rh &&rh) //
    noexcept(detail::_nothrow_amp_cluster<
             ::fn::detail::_uninhabited_join<Lh, Rh>,
             expected<::fn::detail::_joined_t<Lh, Rh>, typename ::std::remove_cvref_t<Rh>::error_type>, Lh, Rh,
             decltype(FWD(rh).error())>::value)
{
  using type = expected<::fn::detail::_joined_t<Lh, Rh>, typename ::std::remove_cvref_t<Rh>::error_type>;
  if constexpr (::fn::detail::_uninhabited_join<Lh, Rh>) {
    return type{::fn::unexpect, FWD(rh).error()};
  } else {
    using VL = ::std::remove_cvref_t<Lh>::value_type;
    using VR = ::std::remove_cvref_t<Rh>::value_type;
    if (rh.has_value())
      return type{::std::in_place, ::fn::detail::_fold_detail::fold<VL, VR>(FWD(lh).value(), FWD(rh).value())};
    return type{::fn::unexpect, FWD(rh).error()};
  }
}

template <some_expected Lh, typename Rh>
  requires(::fn::detail::_some_just<Rh> || ::fn::detail::_some_choice<Rh>)
          && (not ::std::is_void_v<typename ::std::remove_cvref_t<Rh>::value_type>) && (not some_expected_void<Lh>)
[[nodiscard]] constexpr auto operator&(Lh &&lh, Rh &&rh) //
    noexcept(detail::_nothrow_amp_cluster<
             ::fn::detail::_uninhabited_join<Lh, Rh>,
             expected<::fn::detail::_joined_t<Lh, Rh>, typename ::std::remove_cvref_t<Lh>::error_type>, Lh, Rh,
             decltype(FWD(lh).error())>::value)
{
  using type = expected<::fn::detail::_joined_t<Lh, Rh>, typename ::std::remove_cvref_t<Lh>::error_type>;
  if constexpr (::fn::detail::_uninhabited_join<Lh, Rh>) {
    return type{::fn::unexpect, FWD(lh).error()};
  } else {
    using VL = ::std::remove_cvref_t<Lh>::value_type;
    using VR = ::std::remove_cvref_t<Rh>::value_type;
    if (lh.has_value())
      return type{::std::in_place, ::fn::detail::_fold_detail::fold<VL, VR>(FWD(lh).value(), FWD(rh).value())};
    return type{::fn::unexpect, FWD(lh).error()};
  }
}

template <typename Lh, some_expected_void Rh>
  requires(::fn::detail::_some_just<Lh> || ::fn::detail::_some_choice<Lh>)
          && (not ::std::is_void_v<typename ::std::remove_cvref_t<Lh>::value_type>)
[[nodiscard]] constexpr auto operator&(Lh &&lh, Rh &&rh) //
    noexcept(
        ::fn::detail::_nothrow_initializable<
            expected<typename ::std::remove_cvref_t<Lh>::value_type, typename ::std::remove_cvref_t<Rh>::error_type>,
            ::std::in_place_t, decltype(FWD(lh).value())>
        && ::fn::detail::_nothrow_initializable<
            expected<typename ::std::remove_cvref_t<Lh>::value_type, typename ::std::remove_cvref_t<Rh>::error_type>,
            ::fn::unexpect_t, decltype(FWD(rh).error())>)
        -> expected<typename ::std::remove_cvref_t<Lh>::value_type, typename ::std::remove_cvref_t<Rh>::error_type>
{
  using type = expected<typename ::std::remove_cvref_t<Lh>::value_type, typename ::std::remove_cvref_t<Rh>::error_type>;
  if (rh.has_value())
    return type{::std::in_place, FWD(lh).value()};
  return type{::fn::unexpect, FWD(rh).error()};
}

template <some_expected_void Lh, typename Rh>
  requires(::fn::detail::_some_just<Rh> || ::fn::detail::_some_choice<Rh>)
          && (not ::std::is_void_v<typename ::std::remove_cvref_t<Rh>::value_type>)
[[nodiscard]] constexpr auto operator&(Lh &&lh, Rh &&rh) //
    noexcept(
        ::fn::detail::_nothrow_initializable<
            expected<typename ::std::remove_cvref_t<Rh>::value_type, typename ::std::remove_cvref_t<Lh>::error_type>,
            ::std::in_place_t, decltype(FWD(rh).value())>
        && ::fn::detail::_nothrow_initializable<
            expected<typename ::std::remove_cvref_t<Rh>::value_type, typename ::std::remove_cvref_t<Lh>::error_type>,
            ::fn::unexpect_t, decltype(FWD(lh).error())>)
        -> expected<typename ::std::remove_cvref_t<Rh>::value_type, typename ::std::remove_cvref_t<Lh>::error_type>
{
  using type = expected<typename ::std::remove_cvref_t<Rh>::value_type, typename ::std::remove_cvref_t<Lh>::error_type>;
  if (lh.has_value())
    return type{::std::in_place, FWD(rh).value()};
  return type{::fn::unexpect, FWD(lh).error()};
}

template <typename Lh, some_expected Rh>
  requires ::fn::detail::_some_just<Lh> && ::std::is_void_v<typename ::std::remove_cvref_t<Lh>::value_type>
[[nodiscard]] constexpr auto operator&(Lh &&, Rh &&rh) //
    noexcept(::fn::detail::_nothrow_initializable<::std::remove_cvref_t<Rh>, Rh>) -> ::std::remove_cvref_t<Rh>
{
  return ::std::remove_cvref_t<Rh>{FWD(rh)};
}

template <some_expected Lh, typename Rh>
  requires ::fn::detail::_some_just<Rh> && ::std::is_void_v<typename ::std::remove_cvref_t<Rh>::value_type>
[[nodiscard]] constexpr auto operator&(Lh &&lh, Rh &&) //
    noexcept(::fn::detail::_nothrow_initializable<::std::remove_cvref_t<Lh>, Lh>) -> ::std::remove_cvref_t<Lh>
{
  return ::std::remove_cvref_t<Lh>{FWD(lh)};
}

namespace detail {
// The disjunction's error channel: the product of both operands' errors - the same fold as the
// conjunction's value product, on the other channel, distributing graded errors the same way.
template <typename Lh, typename Rh>
using _error_product_t = decltype(::fn::detail::_fold_detail::fold<typename ::std::remove_cvref_t<Lh>::error_type,
                                                                   typename ::std::remove_cvref_t<Rh>::error_type>(
    ::std::declval<Lh>().error(), ::std::declval<Rh>().error()));

template <typename Type, typename Lh, typename Rh>
constexpr inline bool _nothrow_disj_error
    = noexcept(::fn::detail::_fold_detail::fold<typename ::std::remove_cvref_t<Lh>::error_type,
                                                typename ::std::remove_cvref_t<Rh>::error_type>(
          ::std::declval<Lh>().error(), ::std::declval<Rh>().error()))
      && _nothrow_initializable<Type, ::fn::unexpect_t, _error_product_t<Lh, Rh>>;

} // namespace detail

// The disjunction of fallible carriers: values sum into a `copack`, errors multiply into a
//        `pack`
//
// `a | b` fails only if both operands fail: the leftmost engaged operand's value wins, injected
// into the sum of the value types - a same-type pair stays bare, and a `void` side enters a
// genuine sum as `pack<>` - while the error side is the product of both errors, present only when
// every operand failed, all evidence kept positionally. Both operands are fully constructed
// before the operator runs: a value-selection rule, not a lazy fallback. An identity-cluster
// operand makes the disjunction total, collapsing the result into `just` or `choice`.
// The disjunction: the value channel is the sum of the value types - a same-type pair stays bare,
// as the conjunction's same-error sum does - and the error channel is the product of both errors,
// present only when every operand failed, all evidence kept positionally. The leftmost engaged
// operand wins and injects by type; void enters a genuine sum as pack<>.
template <typename Lh, typename Rh>
  requires some_expected<Lh> && some_expected<Rh> && (not some_expected_void<Lh>) && (not some_expected_void<Rh>)
           && (not empty_copack<typename ::std::remove_cvref_t<Lh>::error_type>)
           && (not empty_copack<typename ::std::remove_cvref_t<Rh>::error_type>)
           && ::std::is_same_v<typename ::std::remove_cvref_t<Lh>::value_type,
                               typename ::std::remove_cvref_t<Rh>::value_type>
[[nodiscard]] constexpr auto operator|(Lh &&lh, Rh &&rh) //
    noexcept(::fn::detail::_nothrow_disj_inject<
                 ::fn::detail::_dead_value<Lh>,
                 expected<typename ::std::remove_cvref_t<Lh>::value_type, detail::_error_product_t<Lh, Rh>>, Lh>::value
             && detail::_nothrow_disj_error<
                 expected<typename ::std::remove_cvref_t<Lh>::value_type, detail::_error_product_t<Lh, Rh>>, Lh, Rh>)
{
  using value_type = ::std::remove_cvref_t<Lh>::value_type;
  using type = expected<value_type, detail::_error_product_t<Lh, Rh>>;
  using El = ::std::remove_cvref_t<Lh>::error_type;
  using Er = ::std::remove_cvref_t<Rh>::error_type;
  if constexpr (not ::fn::detail::_dead_value<Lh>) {
    if (lh.has_value())
      return type{::std::in_place, FWD(lh).value()};
    if (rh.has_value())
      return type{::std::in_place, FWD(rh).value()};
  }
  return type{::fn::unexpect, ::fn::detail::_fold_detail::fold<El, Er>(FWD(lh).error(), FWD(rh).error())};
}

template <some_expected_void Lh, some_expected_void Rh>
  requires(not empty_copack<typename ::std::remove_cvref_t<Lh>::error_type>)
          && (not empty_copack<typename ::std::remove_cvref_t<Rh>::error_type>)
[[nodiscard]] constexpr auto operator|(Lh &&lh, Rh &&rh) //
    noexcept(detail::_nothrow_disj_error<expected<void, detail::_error_product_t<Lh, Rh>>, Lh, Rh>)
{
  using type = expected<void, detail::_error_product_t<Lh, Rh>>;
  using El = ::std::remove_cvref_t<Lh>::error_type;
  using Er = ::std::remove_cvref_t<Rh>::error_type;
  if (lh.has_value() || rh.has_value())
    return type{};
  return type{::fn::unexpect, ::fn::detail::_fold_detail::fold<El, Er>(FWD(lh).error(), FWD(rh).error())};
}

template <typename Lh, typename Rh>
  requires some_expected<Lh> && some_expected<Rh> && (not some_expected_void<Lh>) && (not some_expected_void<Rh>)
           && (not empty_copack<typename ::std::remove_cvref_t<Lh>::error_type>)
           && (not empty_copack<typename ::std::remove_cvref_t<Rh>::error_type>)
           && (not ::std::is_same_v<typename ::std::remove_cvref_t<Lh>::value_type,
                                    typename ::std::remove_cvref_t<Rh>::value_type>)
[[nodiscard]] constexpr auto operator|(Lh &&lh, Rh &&rh) //
    noexcept(::fn::detail::_nothrow_disj_inject<
                 ::fn::detail::_dead_value<Lh>,
                 expected<::fn::detail::_disjoined_t<Lh, Rh>, detail::_error_product_t<Lh, Rh>>, Lh>::value
             && ::fn::detail::_nothrow_disj_inject<
                 ::fn::detail::_dead_value<Rh>,
                 expected<::fn::detail::_disjoined_t<Lh, Rh>, detail::_error_product_t<Lh, Rh>>, Rh>::value
             && detail::_nothrow_disj_error<
                 expected<::fn::detail::_disjoined_t<Lh, Rh>, detail::_error_product_t<Lh, Rh>>, Lh, Rh>)
{
  using type = expected<::fn::detail::_disjoined_t<Lh, Rh>, detail::_error_product_t<Lh, Rh>>;
  using El = ::std::remove_cvref_t<Lh>::error_type;
  using Er = ::std::remove_cvref_t<Rh>::error_type;
  if constexpr (not ::fn::detail::_dead_value<Lh>) {
    if (lh.has_value())
      return type{::std::in_place, FWD(lh).value()};
  }
  if constexpr (not ::fn::detail::_dead_value<Rh>) {
    if (rh.has_value())
      return type{::std::in_place, FWD(rh).value()};
  }
  return type{::fn::unexpect, ::fn::detail::_fold_detail::fold<El, Er>(FWD(lh).error(), FWD(rh).error())};
}

template <some_expected_void Lh, typename Rh>
  requires some_expected<Rh> && (not some_expected_void<Rh>)
           && (not empty_copack<typename ::std::remove_cvref_t<Lh>::error_type>)
           && (not empty_copack<typename ::std::remove_cvref_t<Rh>::error_type>)
[[nodiscard]] constexpr auto operator|(Lh &&lh, Rh &&rh) //
    noexcept(
        ::fn::detail::_nothrow_initializable<
            expected<::fn::detail::_disjoined_t<Lh, Rh>, detail::_error_product_t<Lh, Rh>>, ::std::in_place_t, pack<>>
        && ::fn::detail::_nothrow_disj_inject<
            ::fn::detail::_dead_value<Rh>,
            expected<::fn::detail::_disjoined_t<Lh, Rh>, detail::_error_product_t<Lh, Rh>>, Rh>::value
        && detail::_nothrow_disj_error<expected<::fn::detail::_disjoined_t<Lh, Rh>, detail::_error_product_t<Lh, Rh>>,
                                       Lh, Rh>)
{
  using type = expected<::fn::detail::_disjoined_t<Lh, Rh>, detail::_error_product_t<Lh, Rh>>;
  using El = ::std::remove_cvref_t<Lh>::error_type;
  using Er = ::std::remove_cvref_t<Rh>::error_type;
  if (lh.has_value())
    return type{::std::in_place, pack<>{}};
  if constexpr (not ::fn::detail::_dead_value<Rh>) {
    if (rh.has_value())
      return type{::std::in_place, FWD(rh).value()};
  }
  return type{::fn::unexpect, ::fn::detail::_fold_detail::fold<El, Er>(FWD(lh).error(), FWD(rh).error())};
}

template <typename Lh, some_expected_void Rh>
  requires some_expected<Lh> && (not some_expected_void<Lh>)
           && (not empty_copack<typename ::std::remove_cvref_t<Lh>::error_type>)
           && (not empty_copack<typename ::std::remove_cvref_t<Rh>::error_type>)
[[nodiscard]] constexpr auto operator|(Lh &&lh, Rh &&rh) //
    noexcept(
        ::fn::detail::_nothrow_disj_inject<
            ::fn::detail::_dead_value<Lh>,
            expected<::fn::detail::_disjoined_t<Lh, Rh>, detail::_error_product_t<Lh, Rh>>, Lh>::value
        && ::fn::detail::_nothrow_initializable<
            expected<::fn::detail::_disjoined_t<Lh, Rh>, detail::_error_product_t<Lh, Rh>>, ::std::in_place_t, pack<>>
        && detail::_nothrow_disj_error<expected<::fn::detail::_disjoined_t<Lh, Rh>, detail::_error_product_t<Lh, Rh>>,
                                       Lh, Rh>)
{
  using type = expected<::fn::detail::_disjoined_t<Lh, Rh>, detail::_error_product_t<Lh, Rh>>;
  using El = ::std::remove_cvref_t<Lh>::error_type;
  using Er = ::std::remove_cvref_t<Rh>::error_type;
  if constexpr (not ::fn::detail::_dead_value<Lh>) {
    if (lh.has_value())
      return type{::std::in_place, FWD(lh).value()};
  }
  if (rh.has_value())
    return type{::std::in_place, pack<>{}};
  return type{::fn::unexpect, ::fn::detail::_fold_detail::fold<El, Er>(FWD(lh).error(), FWD(rh).error())};
}

} // namespace LIBFN_VERSION
} // namespace fn

// ---------- BEGIN fn/detail/macro_end.hpp ----------
// Deliberately no include guard: see fn/detail/macro_begin.hpp.

#undef FWD // NOSONAR cpp:S959 paired with the define in macro_begin.hpp
#pragma pop_macro("FWD")

#undef DEDUCED_RETURN // NOSONAR cpp:S959 paired with the define in macro_begin.hpp
#pragma pop_macro("DEDUCED_RETURN")
// ---------- END fn/detail/macro_end.hpp ----------

// ---------- RESUME fn/expected.hpp ----------

#endif // INCLUDE_FN_EXPECTED
// ---------- END fn/expected.hpp ----------

// ---------- RESUME fn/concepts.hpp ----------

// ---------- RESUME fn/concepts.hpp ----------

// ---------- RESUME fn/concepts.hpp ----------

// ---------- BEGIN fn/optional.hpp ----------
#ifndef INCLUDE_FN_OPTIONAL
#define INCLUDE_FN_OPTIONAL

// ---------- RESUME fn/optional.hpp ----------

// ---------- BEGIN pfn/optional.hpp ----------
#ifndef INCLUDE_PFN_OPTIONAL
#define INCLUDE_PFN_OPTIONAL

// ---------- RESUME pfn/optional.hpp ----------
#include <optional> // For anything that is not std::optional or std::make_optional
#include <ranges>   // For std::ranges::enable_view

#if defined(__cpp_lib_format_ranges)
#include <format> // For std::format_kind
#endif

#ifdef FWD
#pragma push_macro("FWD")
#define INCLUDE_PFN_OPTIONAL__POP_FWD
#undef FWD // NOSONAR cpp:S959 saved by push_macro above
#endif

// Also defined in fn/detail/macro_begin.hpp but pfn headers are standalone
#define FWD(...) static_cast<decltype(__VA_ARGS__) &&>(__VA_ARGS__)

#ifdef ASSERT
#pragma push_macro("ASSERT")
#define INCLUDE_PFN_OPTIONAL__POP_ASSERT
#undef ASSERT
#endif

// LIBFN_ASSERT is a customization point for the user
#ifdef LIBFN_ASSERT
#define ASSERT(...) LIBFN_ASSERT(__VA_ARGS__)
#else
#define ASSERT(...) assert((__VA_ARGS__) == true)
#endif

namespace pfn {
inline namespace LIBFN_VERSION_BASE {

// [optional.optional], class template optional
template <class T> class optional; // partially freestanding

// [optional.optional.ref], partial specialization of optional for lvalue reference types
template <class T> class optional<T &>; // partially freestanding

namespace detail {
// Deduction probe: deliberately declared without a definition (it is only named in an unevaluated
// context), and called qualified so that ADL cannot pull unrelated overloads into the probe.
template <class U> void _derived_from_optional(optional<U> const &);

template <class T>
concept _is_derived_from_optional = requires(T const &t) { // exposition only
  detail::_derived_from_optional(t);
};

// Helper used as noexcept(...) operand where we want to evaluate both:
// * noexcept of an expression itself (e.g. operator==) AND
// * noexcept of the expression's implicit conversion to bool
// May only be used in unevaluated contexts; any ODR-use will trigger a link error.
// Also declared in pfn/expected.hpp (a benign redeclaration; pfn headers are standalone).
constexpr bool _implicit_to_bool(bool) noexcept;

template <typename> constexpr bool _is_some_optional = false;
template <typename T> constexpr bool _is_some_optional<::pfn::optional<T>> = true;

// [optional.relops] and [optional.comp.with.t] Constraints: the comparison expression is
// well-formed and its result is convertible to bool. Operands are probed as const lvalues,
// matching both *x on a const optional (L const& collapses to plain V& when L is V&, i.e.
// for optional<V&>) and the value operand of [optional.comp.with.t].
template <class L, class R>
concept _eq_bool = requires(L const &l, R const &r) {
  { l == r } -> ::std::convertible_to<bool>;
};
template <class L, class R>
concept _ne_bool = requires(L const &l, R const &r) {
  { l != r } -> ::std::convertible_to<bool>;
};
template <class L, class R>
concept _lt_bool = requires(L const &l, R const &r) {
  { l < r } -> ::std::convertible_to<bool>;
};
template <class L, class R>
concept _gt_bool = requires(L const &l, R const &r) {
  { l > r } -> ::std::convertible_to<bool>;
};
template <class L, class R>
concept _le_bool = requires(L const &l, R const &r) {
  { l <= r } -> ::std::convertible_to<bool>;
};
template <class L, class R>
concept _ge_bool = requires(L const &l, R const &r) {
  { l >= r } -> ::std::convertible_to<bool>;
};

// Conditional noexcept of the same comparison expressions, for the comparison operators'
// extension noexcept clauses (probing the implicit conversion too, hence _implicit_to_bool).
template <class L, class R>
constexpr bool _eq_bool_noexcept
    = noexcept(_implicit_to_bool(::std::declval<L const &>() == ::std::declval<R const &>()));
template <class L, class R>
constexpr bool _ne_bool_noexcept
    = noexcept(_implicit_to_bool(::std::declval<L const &>() != ::std::declval<R const &>()));
template <class L, class R>
constexpr bool _lt_bool_noexcept
    = noexcept(_implicit_to_bool(::std::declval<L const &>() < ::std::declval<R const &>()));
template <class L, class R>
constexpr bool _gt_bool_noexcept
    = noexcept(_implicit_to_bool(::std::declval<L const &>() > ::std::declval<R const &>()));
template <class L, class R>
constexpr bool _le_bool_noexcept
    = noexcept(_implicit_to_bool(::std::declval<L const &>() <= ::std::declval<R const &>()));
template <class L, class R>
constexpr bool _ge_bool_noexcept
    = noexcept(_implicit_to_bool(::std::declval<L const &>() >= ::std::declval<R const &>()));

} // namespace detail

// [optional.relops], relational operators
template <class T, class U>
constexpr bool operator==(optional<T> const &, optional<U> const &) //
    noexcept(detail::_eq_bool_noexcept<T, U>)                       // extension
  requires detail::_eq_bool<T, U>;
template <class T, class U>
constexpr bool operator!=(optional<T> const &, optional<U> const &) //
    noexcept(detail::_ne_bool_noexcept<T, U>)                       // extension
  requires detail::_ne_bool<T, U>;
template <class T, class U>
constexpr bool operator<(optional<T> const &, optional<U> const &) //
    noexcept(detail::_lt_bool_noexcept<T, U>)                      // extension
  requires detail::_lt_bool<T, U>;
template <class T, class U>
constexpr bool operator>(optional<T> const &, optional<U> const &) //
    noexcept(detail::_gt_bool_noexcept<T, U>)                      // extension
  requires detail::_gt_bool<T, U>;
template <class T, class U>
constexpr bool operator<=(optional<T> const &, optional<U> const &) //
    noexcept(detail::_le_bool_noexcept<T, U>)                       // extension
  requires detail::_le_bool<T, U>;
template <class T, class U>
constexpr bool operator>=(optional<T> const &, optional<U> const &) //
    noexcept(detail::_ge_bool_noexcept<T, U>)                       // extension
  requires detail::_ge_bool<T, U>;
template <class T, ::std::three_way_comparable_with<T> U>
constexpr ::std::compare_three_way_result_t<T, U> operator<=>(optional<T> const &, optional<U> const &);

// [optional.nullops], comparison with nullopt
template <class T> constexpr bool operator==(optional<T> const &, ::std::nullopt_t) noexcept;
template <class T> constexpr ::std::strong_ordering operator<=>(optional<T> const &, ::std::nullopt_t) noexcept;

// [optional.comp.with.t], comparison with T
template <class T, class U>
constexpr bool operator==(optional<T> const &, U const &) //
    noexcept(detail::_eq_bool_noexcept<T, U>)             // extension
  requires(not detail::_is_some_optional<U>) && detail::_eq_bool<T, U>;
template <class T, class U>
constexpr bool operator==(T const &, optional<U> const &) //
    noexcept(detail::_eq_bool_noexcept<T, U>)             // extension
  requires(not detail::_is_some_optional<T>) && detail::_eq_bool<T, U>;
template <class T, class U>
constexpr bool operator!=(optional<T> const &, U const &) //
    noexcept(detail::_ne_bool_noexcept<T, U>)             // extension
  requires(not detail::_is_some_optional<U>) && detail::_ne_bool<T, U>;
template <class T, class U>
constexpr bool operator!=(T const &, optional<U> const &) //
    noexcept(detail::_ne_bool_noexcept<T, U>)             // extension
  requires(not detail::_is_some_optional<T>) && detail::_ne_bool<T, U>;
template <class T, class U>
constexpr bool operator<(optional<T> const &, U const &) //
    noexcept(detail::_lt_bool_noexcept<T, U>)            // extension
  requires(not detail::_is_some_optional<U>) && detail::_lt_bool<T, U>;
template <class T, class U>
constexpr bool operator<(T const &, optional<U> const &) //
    noexcept(detail::_lt_bool_noexcept<T, U>)            // extension
  requires(not detail::_is_some_optional<T>) && detail::_lt_bool<T, U>;
template <class T, class U>
constexpr bool operator>(optional<T> const &, U const &) //
    noexcept(detail::_gt_bool_noexcept<T, U>)            // extension
  requires(not detail::_is_some_optional<U>) && detail::_gt_bool<T, U>;
template <class T, class U>
constexpr bool operator>(T const &, optional<U> const &) //
    noexcept(detail::_gt_bool_noexcept<T, U>)            // extension
  requires(not detail::_is_some_optional<T>) && detail::_gt_bool<T, U>;
template <class T, class U>
constexpr bool operator<=(optional<T> const &, U const &) //
    noexcept(detail::_le_bool_noexcept<T, U>)             // extension
  requires(not detail::_is_some_optional<U>) && detail::_le_bool<T, U>;
template <class T, class U>
constexpr bool operator<=(T const &, optional<U> const &) //
    noexcept(detail::_le_bool_noexcept<T, U>)             // extension
  requires(not detail::_is_some_optional<T>) && detail::_le_bool<T, U>;
template <class T, class U>
constexpr bool operator>=(optional<T> const &, U const &) //
    noexcept(detail::_ge_bool_noexcept<T, U>)             // extension
  requires(not detail::_is_some_optional<U>) && detail::_ge_bool<T, U>;
template <class T, class U>
constexpr bool operator>=(T const &, optional<U> const &) //
    noexcept(detail::_ge_bool_noexcept<T, U>)             // extension
  requires(not detail::_is_some_optional<T>) && detail::_ge_bool<T, U>;
template <class T, class U>
  requires(not detail::_is_derived_from_optional<U>) && ::std::three_way_comparable_with<T, U>
constexpr ::std::compare_three_way_result_t<T, U> operator<=>(optional<T> const &, U const &);

// [optional.specalg], specialized algorithms
template <class T>
constexpr void swap(optional<T> &x, optional<T> &y) noexcept(noexcept(x.swap(y)))
  requires(::std::is_reference_v<T> || (::std::is_move_constructible_v<T> && ::std::is_swappable_v<T>));

// The leading defaulted non-type parameter implements this overload's [optional.specalg]
// Constraints: "the call to make_optional does not use an explicit template-argument-list
// that begins with a type template-argument" -- so make_optional<U>(...) always selects an
// in_place overload below (for U = X& there is nothing this overload could do: decay_t
// strips the reference and would silently copy the referent).
template <int = 0, class T>
constexpr optional<::std::decay_t<T>> make_optional(T &&v)                       //
    noexcept(::std::is_nothrow_constructible_v<optional<::std::decay_t<T>>, T>); // extension
template <class T, class... Args>
constexpr optional<T> make_optional(Args &&...args)          //
    noexcept(::std::is_nothrow_constructible_v<T, Args...>); // extension
template <class T, class U, class... Args>
constexpr optional<T> make_optional(::std::initializer_list<U> il, Args &&...args)         //
    noexcept(::std::is_nothrow_constructible_v<T, ::std::initializer_list<U> &, Args...>); // extension

namespace detail {

// Internal union wrapper for optional's value / no-value storage. This mirrors the
// strategy of `pfn::detail::_expected_union_t<void, E>` with the value and "empty"
// roles reversed: the engaged value lives in `v_`, and `e_` is a trivial placeholder
// for the disengaged state, so the union always has an active member (required for
// constexpr use). Copy/move ctors are defaulted iff `T` is trivially copy/move
// constructible, assignments iff `T` is trivially copy/move assignable; the
// destructor is defaulted iff `T` is trivially destructible.
// Tag selecting _optional_union_t's/_optional_base's "construct from any source exposing
// has_value()/operator*()" constructor, disambiguating it from the (bool, S&&) one below
// (which instead reads another union's raw v_ member directly).
constexpr inline struct _from_optional_t {
  explicit _from_optional_t() = default;
} _from_optional{};

// Tag selecting the "direct-non-list-initialize the contained value from the result of
// std::invoke" constructors, required by transform ([optional.monadic]/[optional.ref.monadic]):
// the specified initialization is exactly `U u(invoke(...))` -- guaranteed elision, so no
// extra move and an immovable U works -- which means the invoke expression itself must reach
// the contained value's initializer.
constexpr inline struct _optional_from_invoke_t {
  explicit _optional_from_invoke_t() = default;
} _optional_from_invoke{};

template <class T> union _optional_union_t {
  // _dummy_t placeholder, so the union always has an active member
  struct _dummy_t final {
    constexpr _dummy_t() noexcept = default;
  };

  using _value_t = T;
  T v_;
  _dummy_t e_; // disengaged-state placeholder

  template <typename S>
  constexpr explicit _optional_union_t(bool s, S &&src) //
      noexcept(::std::is_nothrow_constructible_v<T, decltype((FWD(src).v_))>)
  {
    if (s)
      ::std::construct_at(::std::addressof(v_), FWD(src).v_);
    else
      ::std::construct_at(::std::addressof(e_));
  }

  // Constructs from any source exposing has_value()/operator*() (e.g. a differently-typed
  // optional, value or reference) -- mirrors the (bool, S&&) ctor above but reads engagement
  // and the value through that public API instead of another union's raw v_ member, so it
  // works uniformly for optional<U&> sources too (a completely different internal
  // representation: a bare pointer, no union or set_ at all).
  template <typename S>
  constexpr explicit _optional_union_t(_from_optional_t /*ignored*/, S &&src) //
      noexcept(::std::is_nothrow_constructible_v<T, decltype(*FWD(src))>)
  {
    if (src.has_value())
      ::std::construct_at(::std::addressof(v_), *FWD(src));
    else
      ::std::construct_at(::std::addressof(e_));
  }

  // In the noexcept spec, a same-type (modulo cv) invoke result means guaranteed elision: the
  // invoke expression initializes v_ directly and no constructor of T runs, so probing
  // is_nothrow_constructible (false e.g. for an immovable T) would be wrongly pessimistic.
  template <typename Fn, typename... Args>
  constexpr explicit _optional_union_t(_optional_from_invoke_t /*ignored*/, Fn &&fn, Args &&...args) //
      noexcept(::std::is_nothrow_invocable_v<Fn, Args...>
               && (::std::is_same_v<::std::remove_cv_t<::std::invoke_result_t<Fn, Args...>>, ::std::remove_cv_t<T>>
                   || ::std::is_nothrow_constructible_v<T, ::std::invoke_result_t<Fn, Args...>>))
      : v_(::std::invoke(FWD(fn), FWD(args)...))
  {
  }

  constexpr _optional_union_t(_optional_union_t const &) = delete;
  constexpr _optional_union_t(_optional_union_t const &) noexcept //
    requires(::std::is_trivially_copy_constructible_v<T>)
  = default;
  constexpr _optional_union_t(_optional_union_t &&) = delete;
  constexpr _optional_union_t(_optional_union_t &&) noexcept //
    requires(::std::is_trivially_move_constructible_v<T>)
  = default;
  constexpr _optional_union_t &operator=(_optional_union_t const &) = delete;
  constexpr _optional_union_t &operator=(_optional_union_t const &) noexcept //
    requires(::std::is_trivially_copy_assignable_v<T>)
  = default;
  constexpr _optional_union_t &operator=(_optional_union_t &&) = delete;
  constexpr _optional_union_t &operator=(_optional_union_t &&) noexcept //
    requires(::std::is_trivially_move_assignable_v<T>)
  = default;

  template <class... Args>
  constexpr explicit _optional_union_t(::std::in_place_t /*ignored*/, Args &&...a) //
      noexcept(::std::is_nothrow_constructible_v<T, Args...>)
    requires ::std::is_constructible_v<T, Args...>
      : v_(FWD(a)...)
  {
  }
  constexpr explicit _optional_union_t(::std::nullopt_t /*ignored*/) noexcept
      : e_{} // NOSONAR cpp:S3230 activates the member
  {
  }

  constexpr ~_optional_union_t() noexcept
    requires(::std::is_trivially_destructible_v<T>)
  = default;
  constexpr ~_optional_union_t() noexcept {} // NOSONAR cpp:S3490 non-trivial arm of the conditionally-trivial pair

  // reinit, mirroring [expected.void.assign]'s direct construction: one of New/Old is
  // always the trivial `_dummy_t` (value <-> empty transition), so no strong-exception
  // snapshot of the old member is needed.
  template <typename New, typename Old, typename... Args>
  static constexpr void _reinit(New *newp, Old *oldp, Args &&...args) //
      noexcept(::std::is_nothrow_constructible_v<New, Args...>)
  {
    if constexpr (::std::is_same_v<New, _dummy_t>) {
      ::std::destroy_at(oldp);
      ::std::construct_at(newp); // Never throws, since New is _dummy_t
    } else if constexpr (::std::is_nothrow_constructible_v<New, Args...>) {
      ::std::destroy_at(oldp);
      ::std::construct_at(newp, ::std::forward<Args>(args)...); // Never throws
    } else {
      ::std::destroy_at(oldp);
      try {
        ::std::construct_at(newp, ::std::forward<Args>(args)...);
      } catch (...) {
        ::std::construct_at(oldp); // Never throws, since Old is _dummy_t
        throw;
      }
    }
  }
};

template <typename> constexpr bool _is_optional_union = false;
template <typename T> constexpr bool _is_optional_union<_optional_union_t<T>> = true;

// [optional.optional.general]: only lvalue references and complete non-array object types are
// valid contained types; also the Mandates of transform's result type ([optional.monadic]).
template <typename T>
constexpr bool _is_valid_optional =                                                         //
    (::std::is_lvalue_reference_v<T>                                                        //
     || (::std::is_object_v<T> && ::std::is_destructible_v<T> && not ::std::is_array_v<T>)) //
    && not ::std::is_same_v<::std::remove_cv_t<T>, ::std::in_place_t>                       //
    && not ::std::is_same_v<::std::remove_cv_t<T>, ::std::nullopt_t>;

// Shared implementation base class for ::pfn::optional. Members are public since inheritance is
// private. Not used by ::pfn::optional<T&> which models a pointer and does not need `bool set_`.
template <class T, class Policy> struct _optional_base {
  using _storage_t = _optional_union_t<T>;
  using _value_t = _storage_t::_value_t; // == T
  _storage_t storage_;
  bool set_;

  template <class U>
  using _can_convert = ::std::bool_constant<                                               //
      ::std::is_constructible_v<T, U>                                                      //
      && not ::std::is_same_v<::std::remove_cvref_t<U>, ::std::in_place_t>                 //
      && not ::std::is_same_v<::std::remove_cvref_t<U>, typename Policy::template type<T>> //
      && (not ::std::is_same_v<bool, ::std::remove_cv_t<T>>                                //
          || not Policy::template is_specialization<::std::remove_cvref_t<U>>)>;

  template <class U>
  using _can_assign = ::std::bool_constant<                                                  //
      ::std::is_constructible_v<T, U>                                                        //
          && ::std::is_assignable_v<T &, U>                                                  //
      && not ::std::conjunction_v<::std::is_scalar<T>, ::std::is_same<T, ::std::decay_t<U>>> //
      && not ::std::is_same_v<::std::remove_cvref_t<U>, typename Policy::template type<T>>>;

  // [optional.ctor], implementation of converts-from-any-cvref
  template <class W>
  using _converts_from_an_cvrev = ::std::bool_constant<::std::disjunction_v<      //
      ::std::is_constructible<T, W &>, ::std::is_convertible<W &, T>,             //
      ::std::is_constructible<T, W>, ::std::is_convertible<W, T>,                 //
      ::std::is_constructible<T, W const &>, ::std::is_convertible<W const &, T>, //
      ::std::is_constructible<T, W const>, ::std::is_convertible<W const, T>>>;

  template <typename U>
  using _can_copy_convert = ::std::bool_constant<       //
      ::std::is_constructible_v<T, U const &>           //
      && (::std::is_same_v<bool, ::std::remove_cv_t<T>> //
          || not _converts_from_an_cvrev<typename Policy::template type<U>>::value)>;

  template <typename U>
  using _can_move_convert = ::std::bool_constant<       //
      ::std::is_constructible_v<T, U>                   //
      && (::std::is_same_v<bool, ::std::remove_cv_t<T>> //
          || not _converts_from_an_cvrev<typename Policy::template type<U>>::value)>;

  template <typename U, typename UF>
  using _can_copy_assign_detail = ::std::bool_constant< //
      ::std::is_constructible_v<T, UF>                  //
          && ::std::is_assignable_v<T &, UF>
      && not _converts_from_an_cvrev<typename Policy::template type<U>>::value      //
      && not ::std::is_assignable_v<T &, typename Policy::template type<U> &>       //
      && not ::std::is_assignable_v<T &, typename Policy::template type<U> &&>      //
      && not ::std::is_assignable_v<T &, typename Policy::template type<U> const &> //
      && not ::std::is_assignable_v<T &, typename Policy::template type<U> const &&>>;

  template <typename U> using _can_copy_assign = _can_copy_assign_detail<U, U const &>;
  template <typename U> using _can_move_assign = _can_copy_assign_detail<U, U>;

  // Shared construction helper: selects the union's active member from `s`. Used by
  // the wrapper's copy/move and (later) the converting constructors.
  template <typename S>
  constexpr explicit _optional_base(bool s, S &&src)
    requires(_is_optional_union<::std::remove_cvref_t<S>>)
      : storage_(s, FWD(src)), set_(s)
  {
  }

  template <class... Args>
  constexpr explicit _optional_base(::std::in_place_t /*ignored*/, Args &&...a) //
      noexcept(::std::is_nothrow_constructible_v<_storage_t, ::std::in_place_t, Args...>)
    requires ::std::is_constructible_v<_storage_t, ::std::in_place_t, Args...>
      : storage_(::std::in_place, FWD(a)...), set_(true)
  {
  }
  template <class U, class... Args>
  constexpr explicit _optional_base(::std::in_place_t /*ignored*/, ::std::initializer_list<U> il, Args &&...a) //
      noexcept(::std::is_nothrow_constructible_v<_storage_t, ::std::in_place_t, ::std::initializer_list<U> &, Args...>)
    requires ::std::is_constructible_v<_storage_t, ::std::in_place_t, ::std::initializer_list<U> &, Args...>
      : storage_(::std::in_place, il, FWD(a)...), set_(true)
  {
  }
  template <typename Fn, typename... Args>
  constexpr explicit _optional_base(_optional_from_invoke_t tag, Fn &&fn, Args &&...args) //
      noexcept(::std::is_nothrow_constructible_v<_storage_t, _optional_from_invoke_t, Fn, Args...>)
      : storage_(tag, FWD(fn), FWD(args)...), set_(true)
  {
  }
  constexpr explicit _optional_base(::std::nullopt_t /*ignored*/) noexcept //
      : storage_(::std::nullopt), set_(false)
  {
  }

  // Shared construction helper for any source exposing has_value()/operator*() -- i.e.
  // another optional, same or differently typed, value or reference. Delegates to the
  // union's own _from_optional_t ctor, which reads that public observer API directly rather
  // than reaching into the source's storage, so it works uniformly for both optional<U> (a
  // discriminated union) and optional<U&> (a bare pointer, no union or `set_` at all)
  // sources alike. Used by the converting ctors below; _assign_from applies the same
  // public-API reads in its own body (via _reinit), without going through this ctor.
  template <typename S>
  constexpr explicit _optional_base(_from_optional_t tag, S &&s) //
      noexcept(::std::is_nothrow_constructible_v<_storage_t, _from_optional_t, S>)
      : storage_(tag, FWD(s)), set_(s.has_value())
  {
  }

  // [optional.ctor], converting constructors from a differently-typed optional<U>.
  template <class U>
  constexpr explicit(not ::std::is_convertible_v<U const &, T>)
      _optional_base(typename Policy::template type<U> const &s) //
      noexcept(::std::is_nothrow_constructible_v<T, U const &>)  // extension
    requires(_can_copy_convert<U>::value)
      : _optional_base(_from_optional, s)
  {
  }
  template <class U>
  constexpr explicit(not ::std::is_convertible_v<U, T>) _optional_base(typename Policy::template type<U> &&s) //
      noexcept(::std::is_nothrow_constructible_v<T, U>) // extension
    requires(_can_move_convert<U>::value)
      : _optional_base(_from_optional, ::std::move(s))
  {
  }

  constexpr _optional_base(_optional_base const &) noexcept = default;
  constexpr _optional_base(_optional_base &&) noexcept = default;
  constexpr _optional_base &operator=(_optional_base const &) noexcept = default;
  constexpr _optional_base &operator=(_optional_base &&) noexcept = default;

  constexpr ~_optional_base() //
    requires(::std::is_trivially_destructible_v<_value_t>)
  = default;
  constexpr ~_optional_base() //
    requires(not ::std::is_trivially_destructible_v<_value_t>)
  {
    if (set_)
      ::std::destroy_at(::std::addressof(storage_.v_));
  }

  // [optional.mod] reset; also the disengage step of operator=(nullopt_t) and emplace
  constexpr void reset() noexcept
  {
    if (set_) {
      _storage_t::_reinit(::std::addressof(storage_.e_), ::std::addressof(storage_.v_));
      set_ = false;
    }
  }

  // Assignment body shared by the public optional operator= overloads, which keep their
  // constraints/noexcept clauses and forward `s` here as an lvalue or rvalue.
  constexpr void _assign(auto &&s)
  {
    if (set_ && s.set_) {
      storage_.v_ = FWD(s).storage_.v_;
    } else if (set_) {
      _storage_t::_reinit(::std::addressof(storage_.e_), ::std::addressof(storage_.v_), FWD(s).storage_.e_);
      set_ = false;
    } else if (s.set_) {
      _storage_t::_reinit(::std::addressof(storage_.v_), ::std::addressof(storage_.e_), FWD(s).storage_.v_);
      set_ = true;
    } else {
      // no effect: both are disengaged, so the trivial `_dummy_t` is already active
    }
  }

  template <class U> constexpr void _assign_value(U &&s)
  {
    if (set_) {
      storage_.v_ = FWD(s);
    } else {
      _storage_t::_reinit(::std::addressof(storage_.v_), ::std::addressof(storage_.e_), FWD(s));
      set_ = true;
    }
  }

  // Converting-assignment body shared by the public optional operator= overloads. Reads `s`
  // through its public has_value()/operator*() (same reasoning as the converting ctors'
  // shared helper above: works uniformly for optional<U> and optional<U&> sources alike),
  // and reuses _reinit for *this's own storage exactly like _assign above.
  template <typename S> constexpr void _assign_from(S &&s)
  {
    if (set_ && s.has_value()) {
      storage_.v_ = *FWD(s);
    } else if (set_) {
      _storage_t::_reinit(::std::addressof(storage_.e_), ::std::addressof(storage_.v_));
      set_ = false;
    } else if (s.has_value()) {
      _storage_t::_reinit(::std::addressof(storage_.v_), ::std::addressof(storage_.e_), *FWD(s));
      set_ = true;
    }
    // else: both disengaged, no effect
  }

  // Swap body shared by the public optional swap. Same-state mirrors _expected_base::_swap_with;
  // cross-state reuses _reinit: the empty side gains the value first (and _reinit restores its
  // dummy if that move throws), the donor is destroyed only afterwards -- [optional.swap]'s
  // construct-then-destroy order and its unchanged-engagement-on-exception guarantee.
  constexpr void _swap_with(_optional_base &rhs)
  {
    if (set_ == rhs.set_) {
      if (set_) {
        using ::std::swap;
        swap(storage_.v_, rhs.storage_.v_);
      }
      // both disengaged: no effect
    } else if (set_) {
      _storage_t::_reinit(::std::addressof(rhs.storage_.v_), ::std::addressof(rhs.storage_.e_),
                          ::std::move(storage_.v_));
      rhs.set_ = true;
      _storage_t::_reinit(::std::addressof(storage_.e_), ::std::addressof(storage_.v_));
      set_ = false;
    } else {
      rhs._swap_with(*this);
    }
  }

  template <class... Args>
  constexpr T &emplace(Args &&...args) //
    requires ::std::is_constructible_v<T, Args...>
  {
    reset();
    _storage_t::_reinit(::std::addressof(storage_.v_), ::std::addressof(storage_.e_), FWD(args)...);
    set_ = true;
    return storage_.v_;
  }
  template <class U, class... Args>
  constexpr T &emplace(::std::initializer_list<U> il, Args &&...args) //
    requires ::std::is_constructible_v<T, ::std::initializer_list<U> &, Args...>
  {
    reset();
    _storage_t::_reinit(::std::addressof(storage_.v_), ::std::addressof(storage_.e_), il, FWD(args)...);
    set_ = true;
    return storage_.v_;
  }

  // [optional.iterators], iterator support. The Policy picks which library's iterator
  // wrapper is minted here, so fn::optional never exposes a pfn type. A disengaged
  // optional hands out the empty range (nullptr, nullptr).
  using iterator = typename Policy::template iterator<T>;
  using const_iterator = typename Policy::template iterator<T const>;
  [[nodiscard]] constexpr iterator begin() noexcept { return iterator(set_ ? ::std::addressof(storage_.v_) : nullptr); }
  [[nodiscard]] constexpr const_iterator begin() const noexcept
  {
    return const_iterator(set_ ? ::std::addressof(storage_.v_) : nullptr);
  }
  [[nodiscard]] constexpr iterator end() noexcept { return begin() + has_value(); }
  [[nodiscard]] constexpr const_iterator end() const noexcept { return begin() + has_value(); }

  // [optional.observe], observers
  constexpr T const *operator->() const noexcept
  {
    ASSERT(set_); // LCOV_EXCL_LINE
    return ::std::addressof(storage_.v_);
  }
  constexpr T *operator->() noexcept
  {
    ASSERT(set_); // LCOV_EXCL_LINE
    return ::std::addressof(storage_.v_);
  }
  constexpr T const &operator*() const & noexcept { return *(this->operator->()); }
  constexpr T &operator*() & noexcept { return *(this->operator->()); }
  constexpr T const &&operator*() const && noexcept { return ::std::move(*(this->operator->())); }
  constexpr T &&operator*() && noexcept { return ::std::move(*(this->operator->())); }
  constexpr explicit operator bool() const noexcept { return set_; }
  constexpr bool has_value() const noexcept { return set_; }

  constexpr T const &value() const &
  {
    if (not set_)
      throw ::std::bad_optional_access();
    return storage_.v_;
  }
  constexpr T &value() &
  {
    if (not set_)
      throw ::std::bad_optional_access();
    return storage_.v_;
  }
  constexpr T const &&value() const &&
  {
    if (not set_)
      throw ::std::bad_optional_access();
    return ::std::move(storage_.v_);
  }
  constexpr T &&value() &&
  {
    if (not set_)
      throw ::std::bad_optional_access();
    return ::std::move(storage_.v_);
  }

  template <class U = ::std::remove_cv_t<T>> constexpr T value_or(U &&v) const &
  {
    static_assert(::std::is_copy_constructible_v<T> && ::std::is_convertible_v<U &&, T>);
    return set_ ? storage_.v_ : static_cast<T>(::std::forward<U>(v));
  }
  template <class U = ::std::remove_cv_t<T>> constexpr T value_or(U &&v) &&
  {
    static_assert(::std::is_move_constructible_v<T> && ::std::is_convertible_v<U &&, T>);
    return set_ ? ::std::move(storage_.v_) : static_cast<T>(::std::forward<U>(v));
  }

  // [optional.monadic] bodies, shared by the public optional's ref-qualified overload sets.
  // Self is the public optional (not this base), so `*FWD(self)` spells the draft's exact
  // decltype((val)) / decltype(std::move(val)) value category and everything is reached
  // through public API -- same reasoning as the _from_optional_t constructors above.
  template <typename Self, typename Fn>
  static constexpr auto _and_then(Self &&self, Fn &&fn) //
      noexcept(::std::is_nothrow_invocable_v<Fn, decltype(*FWD(self))>)
    requires ::std::is_invocable_v<Fn, decltype(*FWD(self))>
  {
    using result_t = ::std::remove_cvref_t<::std::invoke_result_t<Fn, decltype(*FWD(self))>>;
    static_assert(Policy::template is_specialization<result_t>); // [optional.monadic] Mandates
    if (self.has_value()) {
      return ::std::invoke(FWD(fn), *FWD(self));
    }
    return result_t();
  }

  // In the noexcept spec, only the invoke can throw: the contained value is direct-non-list-
  // initialized from the invoke expression -- guaranteed elision for an object result (no
  // constructor of value_t runs), an identity reference binding for a reference result.
  template <typename Self, typename Fn>
  static constexpr auto _transform(Self &&self, Fn &&fn)                //
      noexcept(::std::is_nothrow_invocable_v<Fn, decltype(*FWD(self))>) // extension
    requires ::std::is_invocable_v<Fn, decltype(*FWD(self))>
  {
    using value_t = ::std::remove_cv_t<::std::invoke_result_t<Fn, decltype(*FWD(self))>>;
    static_assert(_is_valid_optional<value_t>); // [optional.monadic] Mandates
    using result_t = typename Policy::template type<value_t>;
    if (self.has_value()) {
      return result_t(_optional_from_invoke, FWD(fn), *FWD(self));
    }
    return result_t();
  }

  template <typename Self, typename Fn>
  static constexpr auto _or_else(Self &&self, Fn &&fn) //
      noexcept(::std::is_nothrow_invocable_v<Fn>
               && ::std::is_nothrow_constructible_v<typename Policy::template type<T>, Self>)
    requires(::std::is_invocable_v<Fn> && ::std::is_constructible_v<typename Policy::template type<T>, Self>)
  {
    using result_t = typename Policy::template type<T>;
    static_assert(::std::is_same_v<::std::remove_cvref_t<::std::invoke_result_t<Fn>>, result_t>); // Mandates
    if (self.has_value()) {
      return result_t(FWD(self)); // the draft's `return *this;` / `return std::move(*this);`
    }
    return ::std::invoke(FWD(fn));
  }
};

// optional<T&> needs its own base: the referent is held directly as a pointer (nullptr
// encodes the disengaged state), so there is no value union, no discriminant flag, and
// every special member is implicitly trivial.
//
// TODO reference_constructs_from_temporary_v is a C++23 trait with no portable C++20
// fallback, so the dangling-reference guards of [optional.ref.ctor] (constraints and
// deleted overloads for binding a temporary) and of [optional.ref.assign]'s emplace are
// deferred; until then such constructions compile and dangle.
template <class T, class Policy> struct _optional_base<T &, Policy> {
  using _value_t = T &;
  T *v_ = nullptr;

  // [optional.ref.expos], exposition only helper. Binds a reference to `u` (through whatever conversion T&
  // requires -- possibly a throwing user conversion operator) and stores its address.
  template <class U> constexpr void _convert_ref_init_val(U &&u) noexcept(::std::is_nothrow_constructible_v<T &, U>)
  {
    // Workaround for MSVC error C2440, same semantics as the specified `T &r(FWD(u));` ([expr.static.cast]/4)
    v_ = ::std::addressof(static_cast<T &>(FWD(u)));
  }

  template <class U>
  using _can_convert = ::std::bool_constant<                                              //
      not ::std::is_same_v<::std::remove_cvref_t<U>, typename Policy::template type<T &>> //
      && not ::std::is_same_v<::std::remove_cvref_t<U>, ::std::in_place_t>                //
      && ::std::is_constructible_v<T &, U>>;

  // [optional.ref.ctor], shared constraint of the converting constructors from optional<U>;
  // UF is the U flavor the overload binds from (U&, U const&, U, U const).
  template <class U, class UF>
  using _can_convert_from = ::std::bool_constant<                                    //
      not ::std::is_same_v<::std::remove_cv_t<T>, typename Policy::template type<U>> //
      && not ::std::is_same_v<T &, U>                                                //
      && ::std::is_constructible_v<T &, UF>>;

  constexpr _optional_base() noexcept = default;
  constexpr explicit _optional_base(::std::nullopt_t /*ignored*/) noexcept {}

  template <class Arg>
  constexpr explicit _optional_base(::std::in_place_t /*ignored*/, Arg &&arg) //
      noexcept(::std::is_nothrow_constructible_v<T &, Arg>)                   // extension
    requires ::std::is_constructible_v<T &, Arg>
  {
    _convert_ref_init_val(FWD(arg));
  }

  template <typename Fn, typename... Args>
  constexpr explicit _optional_base(_optional_from_invoke_t /*ignored*/, Fn &&fn, Args &&...args) //
      noexcept(::std::is_nothrow_invocable_v<Fn, Args...>
               && ::std::is_nothrow_constructible_v<T &, ::std::invoke_result_t<Fn, Args...>>)
  {
    _convert_ref_init_val(::std::invoke(FWD(fn), FWD(args)...));
  }

  // [optional.ref.ctor], converting constructors from a differently-typed optional<U>: four
  // overloads (unlike optional<T>'s two), since both the constness and the value category of
  // the source select which U flavor T& must bind.
  template <class U>
  constexpr explicit(not ::std::is_convertible_v<U &, T &>) _optional_base(typename Policy::template type<U> &rhs) //
      noexcept(::std::is_nothrow_constructible_v<T &, U &>)
    requires(_can_convert_from<U, U &>::value)
  {
    if (rhs.has_value())
      _convert_ref_init_val(*rhs);
  }
  template <class U>
  constexpr explicit(not ::std::is_convertible_v<U const &, T &>)
      _optional_base(typename Policy::template type<U> const &rhs) //
      noexcept(::std::is_nothrow_constructible_v<T &, U const &>)
    requires(_can_convert_from<U, U const &>::value)
  {
    if (rhs.has_value())
      _convert_ref_init_val(*rhs);
  }
  template <class U>
  constexpr explicit(not ::std::is_convertible_v<U, T &>) _optional_base(typename Policy::template type<U> &&rhs) //
      noexcept(::std::is_nothrow_constructible_v<T &, U>)
    requires(_can_convert_from<U, U>::value)
  {
    if (rhs.has_value())
      _convert_ref_init_val(*::std::move(rhs));
  }
  template <class U>
  constexpr explicit(not ::std::is_convertible_v<U const, T &>)
      _optional_base(typename Policy::template type<U> const &&rhs) //
      noexcept(::std::is_nothrow_constructible_v<T &, U const>)
    requires(_can_convert_from<U, U const>::value)
  {
    if (rhs.has_value())
      _convert_ref_init_val(*::std::move(rhs));
  }

  // [optional.ref.assign]
  template <class U>
  constexpr T &emplace(U &&u) noexcept(::std::is_nothrow_constructible_v<T &, U>)
    requires ::std::is_constructible_v<T &, U>
  {
    _convert_ref_init_val(FWD(u));
    return *v_;
  }

  // [optional.ref.swap] and [optional.ref.mod]: the pointer representation makes both trivial
  constexpr void _swap_with(_optional_base &rhs) noexcept { ::std::swap(v_, rhs.v_); }
  constexpr void reset() noexcept { v_ = nullptr; }

  // [optional.ref.iterators], iterator support; const-only like the observers below. The
  // draft's "present only if T is an object type other than an array of unknown bound" is
  // vacuously satisfied: _is_valid_optional already rejects any other referent.
  using iterator = typename Policy::template iterator<T>;
  [[nodiscard]] constexpr iterator begin() const noexcept { return iterator(v_); }
  [[nodiscard]] constexpr iterator end() const noexcept { return begin() + has_value(); }

  // [optional.ref.observe], observers. Unlike optional<T>, const does not propagate to the
  // referent: *this being const only means the stored pointer can't be rebound, not that T
  // becomes T const -- so these all return plain T&/T*, and there is only ever one overload
  // (no ref-qualifier/const overload set like optional<T>'s).
  constexpr T *operator->() const noexcept
  {
    ASSERT(v_ != nullptr); // LCOV_EXCL_LINE
    return v_;
  }
  constexpr T &operator*() const noexcept { return *(this->operator->()); }
  constexpr explicit operator bool() const noexcept { return v_ != nullptr; }
  constexpr bool has_value() const noexcept { return v_ != nullptr; }

  constexpr T &value() const
  {
    if (v_ == nullptr)
      throw ::std::bad_optional_access();
    return *v_;
  }

  template <class U = ::std::remove_cv_t<T>> constexpr ::std::remove_cv_t<T> value_or(U &&u) const
  {
    static_assert(::std::is_constructible_v<::std::remove_cv_t<T>, T &> //
                  && ::std::is_convertible_v<U, ::std::remove_cv_t<T>>);
    return v_ != nullptr ? *v_ : static_cast<::std::remove_cv_t<T>>(::std::forward<U>(u));
  }

  // [optional.ref.monadic] bodies; unlike optional<T>'s, the callable always receives plain
  // T& (const on the optional does not propagate to the referent), so Self only says which
  // public overload delegated here.
  template <typename Self, typename Fn>
  static constexpr auto _and_then(Self &&self, Fn &&fn) noexcept(::std::is_nothrow_invocable_v<Fn, T &>)
    requires ::std::is_invocable_v<Fn, T &>
  {
    using result_t = ::std::remove_cvref_t<::std::invoke_result_t<Fn, T &>>;
    static_assert(Policy::template is_specialization<result_t>); // [optional.ref.monadic] Mandates
    if (self.has_value()) {
      return ::std::invoke(FWD(fn), *self);
    }
    return result_t();
  }

  // In the noexcept spec, only the invoke can throw -- same reasoning as the primary
  // _transform's.
  template <typename Self, typename Fn>
  static constexpr auto _transform(Self &&self, Fn &&fn) //
      noexcept(::std::is_nothrow_invocable_v<Fn, T &>)   // extension
    requires ::std::is_invocable_v<Fn, T &>
  {
    using value_t = ::std::remove_cv_t<::std::invoke_result_t<Fn, T &>>;
    static_assert(_is_valid_optional<value_t>); // [optional.ref.monadic] Mandates
    using result_t = typename Policy::template type<value_t>;
    if (self.has_value()) {
      return result_t(_optional_from_invoke, FWD(fn), *self);
    }
    return result_t();
  }

  template <typename Self, typename Fn>
  static constexpr auto _or_else(Self &&self, Fn &&fn) noexcept(::std::is_nothrow_invocable_v<Fn>)
    requires ::std::is_invocable_v<Fn>
  {
    using result_t = typename Policy::template type<T &>;
    static_assert(::std::is_same_v<::std::remove_cvref_t<::std::invoke_result_t<Fn>>, result_t>); // Mandates
    if (self.has_value()) {
      return result_t(*self); // the draft's `return *val;` -- rebinds the same referent
    }
    return ::std::invoke(FWD(fn));
  }
};

// [optional.iterators]: the implementation-defined iterator types for pfn::optional. A minimal
// wrapper over T* whose job is to keep pointer-ness out of optional interface. Only what mandated
// by contiguous_iterator, Cpp17RandomAccessIterator and the container iterator requirements.
template <class T> class _optional_iterator {
  static_assert(::std::is_object_v<T>);

  T *p_ = nullptr;

  // Only an optional's base mints iterators from storage pointers; the sibling friendship
  // lets the iterator -> const_iterator converting constructor read p_.
  template <class, class> friend struct _optional_base;
  template <class> friend class _optional_iterator;

  constexpr explicit _optional_iterator(T *p) noexcept : p_(p) {}

public:
  using iterator_concept = ::std::contiguous_iterator_tag;
  using iterator_category = ::std::random_access_iterator_tag;
  using value_type = ::std::remove_cv_t<T>;
  using difference_type = ::std::ptrdiff_t;
  using pointer = T *;
  using reference = T &;

  constexpr _optional_iterator() noexcept = default;

  // iterator -> const_iterator, required by the container iterator requirements
  template <class U>
    requires ::std::is_same_v<U const, T>
  constexpr _optional_iterator(_optional_iterator<U> const &other) noexcept // NOSONAR cpp:S1709 implicit per spec
      : p_(other.p_)
  {
  }

  [[nodiscard]] constexpr T &operator*() const noexcept { return *p_; }
  [[nodiscard]] constexpr T *operator->() const noexcept { return p_; } // std::to_address requires this
  [[nodiscard]] constexpr T &operator[](difference_type n) const noexcept { return p_[n]; }

  constexpr _optional_iterator &operator++() noexcept
  {
    ++p_;
    return *this;
  }
  constexpr _optional_iterator operator++(int) noexcept
  {
    auto r = *this;
    ++p_;
    return r;
  }
  constexpr _optional_iterator &operator--() noexcept
  {
    --p_;
    return *this;
  }
  constexpr _optional_iterator operator--(int) noexcept
  {
    auto r = *this;
    --p_;
    return r;
  }
  constexpr _optional_iterator &operator+=(difference_type n) noexcept
  {
    p_ += n;
    return *this;
  }
  constexpr _optional_iterator &operator-=(difference_type n) noexcept
  {
    p_ -= n;
    return *this;
  }

  [[nodiscard]] constexpr friend _optional_iterator operator+(_optional_iterator i, difference_type n) noexcept
  {
    return i += n;
  }
  [[nodiscard]] constexpr friend _optional_iterator operator+(difference_type n, _optional_iterator i) noexcept
  {
    return i += n;
  }
  [[nodiscard]] constexpr friend _optional_iterator operator-(_optional_iterator i, difference_type n) noexcept
  {
    return i -= n;
  }
  [[nodiscard]] constexpr friend difference_type operator-(_optional_iterator const &x,
                                                           _optional_iterator const &y) noexcept
  {
    return x.p_ - y.p_;
  }

  [[nodiscard]] constexpr friend bool operator==(_optional_iterator const &, _optional_iterator const &) noexcept
      = default;
  [[nodiscard]] constexpr friend ::std::strong_ordering operator<=>(_optional_iterator const &x,
                                                                    _optional_iterator const &y) noexcept
  {
    return x.p_ <=> y.p_;
  }
};

struct optional_policy {
  template <class T> using type = ::pfn::optional<T>;
  template <class T> using iterator = _optional_iterator<T>;
  template <class X> static constexpr bool is_specialization = _is_some_optional<X>;
};

// [optional.hash]: hash<optional<T>> is enabled iff hash<remove_const_t<T>> is enabled --
// detected through the disabled-specialization criteria of [unord.hash] (an unspecialized
// std::hash is a complete but disabled type on all mainstream implementations). Never true
// for T = U& (no std::hash specialization for reference types is ever enabled), so
// hash<optional<U&>> is disabled.
template <class X>
concept _hash_enabled_for = ::std::is_default_constructible_v<::std::hash<X>> //
                            && requires(::std::hash<X> const &h, X const &x) {
                                 { h(x) } -> ::std::same_as<::std::size_t>;
                               };

// Opt is the optional type whose std::hash specialization derives this base; a parameter so
// that a derived library's optional (e.g. fn::optional) can reuse the same machinery.
template <class Opt, class T, bool = _hash_enabled_for<::std::remove_const_t<T>>> struct _optional_hash_base {
  ::std::size_t operator()(Opt const &o) const                        //
      noexcept(noexcept(::std::hash<::std::remove_const_t<T>>{}(*o))) // extension
  {
    if (o.has_value())
      return ::std::hash<::std::remove_const_t<T>>{}(*o);
    return static_cast<::std::size_t>(-7919); // [optional.hash] disengaged: an unspecified value
  }
};
// Disabled case: per [unord.hash] a disabled hash specialization is not a function object
// (no call operator) and is neither constructible nor assignable.
template <class Opt, class T> struct _optional_hash_base<Opt, T, false> {
  _optional_hash_base() = delete;
  _optional_hash_base(_optional_hash_base const &) = delete;
  _optional_hash_base(_optional_hash_base &&) = delete;
  _optional_hash_base &operator=(_optional_hash_base const &) = delete;
  _optional_hash_base &operator=(_optional_hash_base &&) = delete;
};

} // namespace detail

/**
 * @brief `std::optional` in its C++26 shape: a computation yielding a value `T` or empty
 *
 * A polyfill for C++20 compilers, tracking the C++ working draft: members are as
 * [optional.optional] specifies them, including the monadic operations, iterator support (an
 * engaged optional is a contiguous range of one element) and hashing; lvalue reference payloads
 * are served by the `optional<T&>` partial specialization. Deliberate deviations:
 * - a `noexcept` specification is derived from `T` and the callable arguments wherever the
 *   standard leaves one unstated; each such clause is marked `// extension` inline;
 * - the draft's hardened preconditions are checked by an assertion, customizable by defining
 *   `LIBFN_ASSERT` before inclusion.
 *
 *
 * Its members are the standard's, and specified where
 * the reference page for this entity points.
 * @tparam T Type of the contained value; an lvalue reference selects the specialization
 */
template <class T> class optional : private detail::_optional_base<T, detail::optional_policy> {
  static_assert(detail::_is_valid_optional<T>);
  using _base = detail::_optional_base<T, detail::optional_policy>;

  // Allow sibling `_optional_base` instantiations to call the private from-invoke ctor
  // below (its caller is another optional's base).
  template <class, class> friend struct detail::_optional_base;

public:
  using value_type = T;
  // [optional.iterators]: the iterator types are implementation-defined
  using iterator = detail::_optional_iterator<T>;
  using const_iterator = detail::_optional_iterator<T const>;

  // [optional.ctor], constructors
  constexpr optional() noexcept : _base(::std::nullopt) {}
  constexpr optional(::std::nullopt_t) noexcept : _base(::std::nullopt) {} // NOSONAR cpp:S1709 implicit per spec

  constexpr optional(optional const &) = delete;
  constexpr optional(optional const &s)                   //
      noexcept(::std::is_nothrow_copy_constructible_v<T>) // extension
    requires(::std::is_copy_constructible_v<T> && ::std::is_trivially_copy_constructible_v<T>)
  = default;
  constexpr optional(optional const &s)                   //
      noexcept(::std::is_nothrow_copy_constructible_v<T>) // extension
    requires(::std::is_copy_constructible_v<T> && not ::std::is_trivially_copy_constructible_v<T>)
      : _base(s.set_, FWD(s).storage_)
  {
  }
  constexpr optional(optional &&) noexcept
    requires(::std::is_move_constructible_v<T> && ::std::is_trivially_move_constructible_v<T>)
  = default;
  constexpr optional(optional &&s) //
      noexcept(::std::is_nothrow_move_constructible_v<T>)
    requires(::std::is_move_constructible_v<T> && not ::std::is_trivially_move_constructible_v<T>)
      : _base(s.set_, FWD(s).storage_)
  {
  }

  template <class... Args>
  constexpr explicit optional(::std::in_place_t, Args &&...a) //
      noexcept(::std::is_nothrow_constructible_v<T, Args...>) // extension
    requires ::std::is_constructible_v<T, Args...>
      : _base(::std::in_place, FWD(a)...)
  {
  }
  template <class U, class... Args>
  constexpr explicit optional(::std::in_place_t, ::std::initializer_list<U> il, Args &&...a) //
      noexcept(::std::is_nothrow_constructible_v<T, ::std::initializer_list<U> &, Args...>)  // extension
    requires ::std::is_constructible_v<T, ::std::initializer_list<U> &, Args...>
      : _base(::std::in_place, il, FWD(a)...)
  {
  }

  template <class U = ::std::remove_cv_t<T>>
  constexpr explicit(not ::std::is_convertible_v<U, T>) optional(U &&v) // NOSONAR cpp:S6458 _can_convert excludes self
      noexcept(::std::is_nothrow_constructible_v<T, U>)                 // extension
    requires(_base::template _can_convert<U>::value)
      : _base(::std::in_place, FWD(v))
  {
  }
  template <class U>
  constexpr explicit(not ::std::is_convertible_v<U const &, T>) optional(optional<U> const &s) //
      noexcept(::std::is_nothrow_constructible_v<T, U const &>)                                // extension
    requires(_base::template _can_copy_convert<U>::value)
      : _base(s)
  {
  }
  template <class U>
  constexpr explicit(not ::std::is_convertible_v<U, T>) optional(optional<U> &&s) //
      noexcept(::std::is_nothrow_constructible_v<T, U>)                           // extension
    requires(_base::template _can_move_convert<U>::value)
      : _base(::std::move(s))
  {
  }

  // [optional.dtor], destructor
  constexpr ~optional() = default;

  // [optional.assign], assignment
  constexpr optional &operator=(::std::nullopt_t) noexcept
  {
    this->reset();
    return *this;
  }
  constexpr optional &operator=(optional const &) = delete;
  constexpr optional &operator=(optional const &)                                                   //
      noexcept(::std::is_nothrow_copy_assignable_v<T> && ::std::is_nothrow_copy_constructible_v<T>) // extension
    requires(::std::is_copy_constructible_v<T> && ::std::is_copy_assignable_v<T>
             && ::std::is_trivially_copy_constructible_v<T> && ::std::is_trivially_copy_assignable_v<T>
             && ::std::is_trivially_destructible_v<T>)
  = default;
  constexpr optional &operator=(optional const &s)                                                  //
      noexcept(::std::is_nothrow_copy_assignable_v<T> && ::std::is_nothrow_copy_constructible_v<T>) // extension
    requires(::std::is_copy_constructible_v<T> && ::std::is_copy_assignable_v<T>
             && (not ::std::is_trivially_copy_constructible_v<T> || not ::std::is_trivially_copy_assignable_v<T>
                 || not ::std::is_trivially_destructible_v<T>))
  {
    this->_assign(static_cast<_base const &>(s));
    return *this;
  }
  constexpr optional &operator=(optional &&) // NOSONAR cpp:S5018 standard mandated `noexcept` spec.
      noexcept(::std::is_nothrow_move_assignable_v<T> && ::std::is_nothrow_move_constructible_v<T>) // required
    requires(::std::is_move_constructible_v<T> && ::std::is_move_assignable_v<T>
             && ::std::is_trivially_move_constructible_v<T> && ::std::is_trivially_move_assignable_v<T>
             && ::std::is_trivially_destructible_v<T>)
  = default;
  constexpr optional &operator=(optional &&s) // NOSONAR cpp:S5018 standard mandated `noexcept` spec.
      noexcept(::std::is_nothrow_move_assignable_v<T> && ::std::is_nothrow_move_constructible_v<T>) // required
    requires(::std::is_move_constructible_v<T> && ::std::is_move_assignable_v<T>
             && (not ::std::is_trivially_move_constructible_v<T> || not ::std::is_trivially_move_assignable_v<T>
                 || not ::std::is_trivially_destructible_v<T>))
  {
    this->_assign(static_cast<_base &&>(s));
    return *this;
  }

  template <class U = ::std::remove_cv_t<T>>
  constexpr optional &operator=(U &&v)                                                            //
      noexcept(::std::is_nothrow_assignable_v<T &, U> && ::std::is_nothrow_constructible_v<T, U>) // extension
    requires(_base::template _can_assign<U>::value)
  {
    this->_assign_value(FWD(v));
    return *this;
  }
  template <class U>
  constexpr optional &operator=(optional<U> const &s) //
      noexcept(::std::is_nothrow_assignable_v<T &, U const &>
               && ::std::is_nothrow_constructible_v<T, U const &>) // extension
    requires(_base::template _can_copy_assign<U>::value)
  {
    this->_assign_from(s);
    return *this;
  }
  template <class U>
  constexpr optional &operator=(optional<U> &&s)                                                  //
      noexcept(::std::is_nothrow_assignable_v<T &, U> && ::std::is_nothrow_constructible_v<T, U>) // extension
    requires(_base::template _can_move_assign<U>::value)
  {
    this->_assign_from(::std::move(s));
    return *this;
  }

  using _base::emplace;

  // [optional.swap], swap; body delegates to _optional_base helper
  constexpr void swap(optional &rhs) // NOSONAR cpp:S5018 standard mandated `noexcept` spec.
      noexcept(::std::is_nothrow_move_constructible_v<T> && ::std::is_nothrow_swappable_v<T>) // required
  {
    static_assert(::std::is_move_constructible_v<T>);
    this->_swap_with(rhs);
  }

  // [optional.iterators], iterator support
  using _base::begin;
  using _base::end;

  // [optional.observe], observers
  using _base::has_value;
  using _base::operator bool;
  using _base::operator*;
  using _base::operator->;
  using _base::value; // freestanding-deleted
  using _base::value_or;

  // [optional.monadic], monadic operations; bodies delegate to _optional_base helpers
  template <class F>
  constexpr auto and_then(F &&f) &                        //
      noexcept(noexcept(_base::_and_then(*this, FWD(f)))) // extension
      -> decltype(_base::_and_then(*this, FWD(f)))
  {
    return _base::_and_then(*this, FWD(f));
  }
  template <class F>
  constexpr auto and_then(F &&f) &&                                    //
      noexcept(noexcept(_base::_and_then(::std::move(*this), FWD(f)))) // extension
      -> decltype(_base::_and_then(::std::move(*this), FWD(f)))
  {
    return _base::_and_then(::std::move(*this), FWD(f));
  }
  template <class F>
  constexpr auto and_then(F &&f) const &                  //
      noexcept(noexcept(_base::_and_then(*this, FWD(f)))) // extension
      -> decltype(_base::_and_then(*this, FWD(f)))
  {
    return _base::_and_then(*this, FWD(f));
  }
  template <class F>
  constexpr auto and_then(F &&f) const &&                              //
      noexcept(noexcept(_base::_and_then(::std::move(*this), FWD(f)))) // extension
      -> decltype(_base::_and_then(::std::move(*this), FWD(f)))
  {
    return _base::_and_then(::std::move(*this), FWD(f));
  }
  template <class F>
  constexpr auto transform(F &&f) &                        //
      noexcept(noexcept(_base::_transform(*this, FWD(f)))) // extension
      -> decltype(_base::_transform(*this, FWD(f)))
  {
    return _base::_transform(*this, FWD(f));
  }
  template <class F>
  constexpr auto transform(F &&f) &&                                    //
      noexcept(noexcept(_base::_transform(::std::move(*this), FWD(f)))) // extension
      -> decltype(_base::_transform(::std::move(*this), FWD(f)))
  {
    return _base::_transform(::std::move(*this), FWD(f));
  }
  template <class F>
  constexpr auto transform(F &&f) const &                  //
      noexcept(noexcept(_base::_transform(*this, FWD(f)))) // extension
      -> decltype(_base::_transform(*this, FWD(f)))
  {
    return _base::_transform(*this, FWD(f));
  }
  template <class F>
  constexpr auto transform(F &&f) const &&                              //
      noexcept(noexcept(_base::_transform(::std::move(*this), FWD(f)))) // extension
      -> decltype(_base::_transform(::std::move(*this), FWD(f)))
  {
    return _base::_transform(::std::move(*this), FWD(f));
  }
  template <class F>
  constexpr auto or_else(F &&f) &&                                    //
      noexcept(noexcept(_base::_or_else(::std::move(*this), FWD(f)))) // extension
      -> decltype(_base::_or_else(::std::move(*this), FWD(f)))
    requires(::std::invocable<F> && ::std::move_constructible<T>)
  {
    return _base::_or_else(::std::move(*this), FWD(f));
  }
  template <class F>
  constexpr auto or_else(F &&f) const &                  //
      noexcept(noexcept(_base::_or_else(*this, FWD(f)))) // extension
      -> decltype(_base::_or_else(*this, FWD(f)))
    requires(::std::invocable<F> && ::std::copy_constructible<T>)
  {
    return _base::_or_else(*this, FWD(f));
  }

  // [optional.mod], modifiers
  using _base::reset;

private:
  // Direct-non-list-initializes the contained value from the result of std::invoke; used by
  // transform implemented in _optional_base.
  template <class Fn, class... Args>
  constexpr explicit optional(detail::_optional_from_invoke_t tag, Fn &&fn, Args &&...args) //
      noexcept(::std::is_nothrow_constructible_v<_base, detail::_optional_from_invoke_t, Fn, Args...>)
      : _base(tag, FWD(fn), FWD(args)...)
  {
  }
};

template <class T> optional(T) -> optional<T>;

/**
 * @brief The `std::optional` partial specialization for lvalue references
 *        ([optional.optional.ref]): a non-owning reference to `T`, or empty
 *
 * Specified for C++26. Copy assignment and `emplace` rebind the reference - nothing ever assigns
 * through it - and `const` on the optional does not constify the referent; the referent's
 * lifetime stays the caller's responsibility. The `noexcept` and assertion deviations of the
 * primary template apply here equally, plus one deferral: the draft rejects a construction that
 * would bind the reference to a temporary via `reference_constructs_from_temporary_v`, a C++23
 * trait with no portable C++20 fallback - those guards are deferred, and such a construction
 * compiles and dangles.
 *
 *
 * Its members are the standard's, and specified where
 * the reference page for this entity points.
 * @tparam T Referenced type
 */
template <class T> class optional<T &> : private detail::_optional_base<T &, detail::optional_policy> {
  static_assert(detail::_is_valid_optional<T>);
  using _base = detail::_optional_base<T &, detail::optional_policy>;

  // Allow sibling `_optional_base` instantiations to call the private from-invoke ctor
  // below (its caller is another optional's base).
  template <class, class> friend struct detail::_optional_base;

public:
  using value_type = T;
  // [optional.ref.iterators]: the iterator type is implementation-defined
  using iterator = detail::_optional_iterator<T>;

  // [optional.ref.ctor], constructors
  constexpr optional() noexcept = default;
  constexpr optional(::std::nullopt_t) noexcept : optional() {} // NOSONAR cpp:S1709 implicit per spec
  constexpr optional(optional const &rhs) noexcept = default;

  template <class Arg>
  constexpr explicit optional(::std::in_place_t, Arg &&arg) //
      noexcept(::std::is_nothrow_constructible_v<T &, Arg>) // extension
    requires ::std::is_constructible_v<T &, Arg>
      : _base(::std::in_place, FWD(arg))
  {
  }

  template <class U>
  constexpr explicit(not ::std::is_convertible_v<U, T &>)
      optional(U &&u) // NOSONAR cpp:S6458 _can_convert excludes self
      noexcept(::std::is_nothrow_constructible_v<T &, U>)
    requires(_base::template _can_convert<U>::value)
      : _base(::std::in_place, FWD(u))
  {
  }
  template <class U>
  constexpr explicit(not ::std::is_convertible_v<U &, T &>) optional(optional<U> &rhs) //
      noexcept(::std::is_nothrow_constructible_v<T &, U &>)
    requires(_base::template _can_convert_from<U, U &>::value)
      : _base(rhs)
  {
  }
  template <class U>
  constexpr explicit(not ::std::is_convertible_v<U const &, T &>) optional(optional<U> const &rhs) //
      noexcept(::std::is_nothrow_constructible_v<T &, U const &>)
    requires(_base::template _can_convert_from<U, U const &>::value)
      : _base(rhs)
  {
  }
  template <class U>
  constexpr explicit(not ::std::is_convertible_v<U, T &>) optional(optional<U> &&rhs) //
      noexcept(::std::is_nothrow_constructible_v<T &, U>)
    requires(_base::template _can_convert_from<U, U>::value)
      : _base(::std::move(rhs))
  {
  }
  template <class U>
  constexpr explicit(not ::std::is_convertible_v<U const, T &>) optional(optional<U> const &&rhs) //
      noexcept(::std::is_nothrow_constructible_v<T &, U const>)
    requires(_base::template _can_convert_from<U, U const>::value)
      : _base(::std::move(rhs))
  {
  }

  constexpr ~optional() = default;

  // [optional.ref.assign], assignment
  constexpr optional &operator=(::std::nullopt_t) noexcept
  {
    this->reset();
    return *this;
  }
  constexpr optional &operator=(optional const &rhs) noexcept = default;

  using _base::emplace;

  // [optional.ref.swap], swap
  constexpr void swap(optional &rhs) noexcept { this->_swap_with(rhs); }

  // [optional.ref.iterators], iterator support
  using _base::begin;
  using _base::end;

  // [optional.ref.observe], observers
  using _base::has_value;
  using _base::operator bool;
  using _base::operator*;
  using _base::operator->;
  using _base::value; // freestanding-deleted
  using _base::value_or;

  // [optional.ref.monadic], monadic operations; bodies delegate to _optional_base helpers
  template <class F>
  constexpr auto and_then(F &&f) const                    //
      noexcept(noexcept(_base::_and_then(*this, FWD(f)))) // extension
      -> decltype(_base::_and_then(*this, FWD(f)))
  {
    return _base::_and_then(*this, FWD(f));
  }
  template <class F>
  constexpr auto transform(F &&f) const                    //
      noexcept(noexcept(_base::_transform(*this, FWD(f)))) // extension
      -> decltype(_base::_transform(*this, FWD(f)))
  {
    return _base::_transform(*this, FWD(f));
  }
  template <class F>
  constexpr auto or_else(F &&f) const                    //
      noexcept(noexcept(_base::_or_else(*this, FWD(f)))) // extension
      -> decltype(_base::_or_else(*this, FWD(f)))
    requires ::std::invocable<F>
  {
    return _base::_or_else(*this, FWD(f));
  }

  // [optional.ref.mod], modifiers
  using _base::reset;

private:
  // Direct-non-list-initializes the bound reference from the result of std::invoke; used by
  // transform implemented in _optional_base.
  template <class Fn, class... Args>
  constexpr explicit optional(detail::_optional_from_invoke_t tag, Fn &&fn, Args &&...args) //
      noexcept(::std::is_nothrow_constructible_v<_base, detail::_optional_from_invoke_t, Fn, Args...>)
      : _base(tag, FWD(fn), FWD(args)...)
  {
  }
};

// [optional.relops], relational operators
template <class T, class U>
constexpr bool operator==(optional<T> const &x, optional<U> const &y) //
    noexcept(detail::_eq_bool_noexcept<T, U>)                         // extension
  requires detail::_eq_bool<T, U>
{
  if (x.has_value() != y.has_value())
    return false;
  if (not x.has_value())
    return true;
  return *x == *y;
}
template <class T, class U>
constexpr bool operator!=(optional<T> const &x, optional<U> const &y) //
    noexcept(detail::_ne_bool_noexcept<T, U>)                         // extension
  requires detail::_ne_bool<T, U>
{
  if (x.has_value() != y.has_value())
    return true;
  if (not x.has_value())
    return false;
  return *x != *y;
}
template <class T, class U>
constexpr bool operator<(optional<T> const &x, optional<U> const &y) //
    noexcept(detail::_lt_bool_noexcept<T, U>)                        // extension
  requires detail::_lt_bool<T, U>
{
  if (not y.has_value())
    return false;
  if (not x.has_value())
    return true;
  return *x < *y;
}
template <class T, class U>
constexpr bool operator>(optional<T> const &x, optional<U> const &y) //
    noexcept(detail::_gt_bool_noexcept<T, U>)                        // extension
  requires detail::_gt_bool<T, U>
{
  if (not x.has_value())
    return false;
  if (not y.has_value())
    return true;
  return *x > *y;
}
template <class T, class U>
constexpr bool operator<=(optional<T> const &x, optional<U> const &y) //
    noexcept(detail::_le_bool_noexcept<T, U>)                         // extension
  requires detail::_le_bool<T, U>
{
  if (not x.has_value())
    return true;
  if (not y.has_value())
    return false;
  return *x <= *y;
}
template <class T, class U>
constexpr bool operator>=(optional<T> const &x, optional<U> const &y) //
    noexcept(detail::_ge_bool_noexcept<T, U>)                         // extension
  requires detail::_ge_bool<T, U>
{
  if (not y.has_value())
    return true;
  if (not x.has_value())
    return false;
  return *x >= *y;
}
template <class T, ::std::three_way_comparable_with<T> U>
constexpr ::std::compare_three_way_result_t<T, U> operator<=>(optional<T> const &x, optional<U> const &y)
{
  return x.has_value() && y.has_value() ? *x <=> *y : x.has_value() <=> y.has_value();
}

// [optional.nullops], comparison with nullopt
template <class T> constexpr bool operator==(optional<T> const &x, ::std::nullopt_t) noexcept
{
  return not x.has_value();
}
template <class T> constexpr ::std::strong_ordering operator<=>(optional<T> const &x, ::std::nullopt_t) noexcept
{
  return x.has_value() <=> false;
}

// [optional.comp.with.t], comparison with T
template <class T, class U>
constexpr bool operator==(optional<T> const &x, U const &v) //
    noexcept(detail::_eq_bool_noexcept<T, U>)               // extension
  requires(not detail::_is_some_optional<U>) && detail::_eq_bool<T, U>
{
  return x.has_value() ? *x == v : false;
}
template <class T, class U>
constexpr bool operator==(T const &v, optional<U> const &x) //
    noexcept(detail::_eq_bool_noexcept<T, U>)               // extension
  requires(not detail::_is_some_optional<T>) && detail::_eq_bool<T, U>
{
  return x.has_value() ? v == *x : false;
}
template <class T, class U>
constexpr bool operator!=(optional<T> const &x, U const &v) //
    noexcept(detail::_ne_bool_noexcept<T, U>)               // extension
  requires(not detail::_is_some_optional<U>) && detail::_ne_bool<T, U>
{
  return x.has_value() ? *x != v : true;
}
template <class T, class U>
constexpr bool operator!=(T const &v, optional<U> const &x) //
    noexcept(detail::_ne_bool_noexcept<T, U>)               // extension
  requires(not detail::_is_some_optional<T>) && detail::_ne_bool<T, U>
{
  return x.has_value() ? v != *x : true;
}
template <class T, class U>
constexpr bool operator<(optional<T> const &x, U const &v) //
    noexcept(detail::_lt_bool_noexcept<T, U>)              // extension
  requires(not detail::_is_some_optional<U>) && detail::_lt_bool<T, U>
{
  return x.has_value() ? *x < v : true;
}
template <class T, class U>
constexpr bool operator<(T const &v, optional<U> const &x) //
    noexcept(detail::_lt_bool_noexcept<T, U>)              // extension
  requires(not detail::_is_some_optional<T>) && detail::_lt_bool<T, U>
{
  return x.has_value() ? v < *x : false;
}
template <class T, class U>
constexpr bool operator>(optional<T> const &x, U const &v) //
    noexcept(detail::_gt_bool_noexcept<T, U>)              // extension
  requires(not detail::_is_some_optional<U>) && detail::_gt_bool<T, U>
{
  return x.has_value() ? *x > v : false;
}
template <class T, class U>
constexpr bool operator>(T const &v, optional<U> const &x) //
    noexcept(detail::_gt_bool_noexcept<T, U>)              // extension
  requires(not detail::_is_some_optional<T>) && detail::_gt_bool<T, U>
{
  return x.has_value() ? v > *x : true;
}
template <class T, class U>
constexpr bool operator<=(optional<T> const &x, U const &v) //
    noexcept(detail::_le_bool_noexcept<T, U>)               // extension
  requires(not detail::_is_some_optional<U>) && detail::_le_bool<T, U>
{
  return x.has_value() ? *x <= v : true;
}
template <class T, class U>
constexpr bool operator<=(T const &v, optional<U> const &x) //
    noexcept(detail::_le_bool_noexcept<T, U>)               // extension
  requires(not detail::_is_some_optional<T>) && detail::_le_bool<T, U>
{
  return x.has_value() ? v <= *x : false;
}
template <class T, class U>
constexpr bool operator>=(optional<T> const &x, U const &v) //
    noexcept(detail::_ge_bool_noexcept<T, U>)               // extension
  requires(not detail::_is_some_optional<U>) && detail::_ge_bool<T, U>
{
  return x.has_value() ? *x >= v : false;
}
template <class T, class U>
constexpr bool operator>=(T const &v, optional<U> const &x) //
    noexcept(detail::_ge_bool_noexcept<T, U>)               // extension
  requires(not detail::_is_some_optional<T>) && detail::_ge_bool<T, U>
{
  return x.has_value() ? v >= *x : true;
}
template <class T, class U>
  requires(not detail::_is_derived_from_optional<U>) && ::std::three_way_comparable_with<T, U>
constexpr ::std::compare_three_way_result_t<T, U> operator<=>(optional<T> const &x, U const &v)
{
  return x.has_value() ? *x <=> v : ::std::strong_ordering::less;
}

// [optional.specalg], specialized algorithms
template <class T>
constexpr void swap(optional<T> &x, optional<T> &y) noexcept(noexcept(x.swap(y)))
  requires(::std::is_reference_v<T> || (::std::is_move_constructible_v<T> && ::std::is_swappable_v<T>))
{
  x.swap(y);
}

// The int parameter's default lives on the declaration above, along with the explanation of
// the [optional.specalg] constraint it implements.
template <int, class T>
constexpr optional<::std::decay_t<T>> make_optional(T &&v)                      //
    noexcept(::std::is_nothrow_constructible_v<optional<::std::decay_t<T>>, T>) // extension
{
  return optional<::std::decay_t<T>>(FWD(v));
}
template <class T, class... Args>
constexpr optional<T> make_optional(Args &&...args)         //
    noexcept(::std::is_nothrow_constructible_v<T, Args...>) // extension
{
  return optional<T>(::std::in_place, FWD(args)...);
}
template <class T, class U, class... Args>
constexpr optional<T> make_optional(::std::initializer_list<U> il, Args &&...args)        //
    noexcept(::std::is_nothrow_constructible_v<T, ::std::initializer_list<U> &, Args...>) // extension
{
  return optional<T>(::std::in_place, il, FWD(args)...);
}

} // namespace LIBFN_VERSION_BASE
} // namespace pfn

namespace std {
// [optional.hash], hash support
template <class T> struct hash<::pfn::optional<T>> : ::pfn::detail::_optional_hash_base<::pfn::optional<T>, T> {};

#if defined(__cpp_lib_format_ranges)
// [optional.syn]: an optional is never formatted as a range
template <class T> constexpr range_format format_kind<::pfn::optional<T>> = range_format::disabled;
#endif

// [optional.syn]: an optional is a view of at most one element. The nested-namespace block
// mirrors MSVC's own STL (e.g. span): a qualified definition draws C2888 and the compound
// `namespace std::ranges` form is not reliably matched by MSVC either.
namespace ranges {
template <class T> constexpr bool enable_view<::pfn::optional<T>> = true;
} // namespace ranges
} // namespace std

#undef ASSERT

#ifdef INCLUDE_PFN_OPTIONAL__POP_ASSERT
#pragma pop_macro("ASSERT")
#endif

#undef FWD

#ifdef INCLUDE_PFN_OPTIONAL__POP_FWD
#pragma pop_macro("FWD")
#endif

#endif // INCLUDE_PFN_OPTIONAL
// ---------- END pfn/optional.hpp ----------

// ---------- RESUME fn/optional.hpp ----------

// ---------- RESUME fn/optional.hpp ----------

// ---------- RESUME fn/optional.hpp ----------

// ---------- RESUME fn/optional.hpp ----------

// ---------- RESUME fn/optional.hpp ----------

// ---------- RESUME fn/optional.hpp ----------

// ---------- BEGIN fn/detail/macro_begin.hpp ----------
// Deliberately no include guard: this header and fn/detail/macro_end.hpp bracket the section of a
// header that uses the macros below; push_macro/pop_macro make the bracketing safe under nesting
// and preserve any prior user definition.

#pragma push_macro("FWD")
#undef FWD // NOSONAR cpp:S959 saved by push_macro above

// This FWD macro is a functional equivalent to std::forward<decltype(v)>(v),
// but it saves compilation time (and typing) when used frequently.
#define FWD(...) static_cast<decltype(__VA_ARGS__) &&>(__VA_ARGS__)

#pragma push_macro("DEDUCED_RETURN")
#undef DEDUCED_RETURN // NOSONAR cpp:S959 saved by push_macro above

// Spell a function's deduced return type explicitly on MSVC only. MSVC mis-resolves a deduced
// (`auto`/`decltype(auto)`) return whose type derives from a body-local alias, leaking it as an
// opaque dependent type; an explicit trailing return type is the fix. Every other compiler keeps
// `decltype(auto)` — the natural spelling — which by construction deduces `decltype(EXPR)` on
// `return EXPR;`, so the two are the same type and this is a no-op off MSVC.
//
// Confining `decltype(EXPR)` to MSVC also keeps it off clang <= 20, which in C++23 substitutes a
// non-viable constrained overload's trailing return type BEFORE its requires-clause rejects it
// (fixed clang 21), so the explicit form would fail to compile instead of removing the non-viable
// function from the overload set.
#ifndef _MSC_VER
#define DEDUCED_RETURN(...) decltype(auto)
#else
#define DEDUCED_RETURN(...) decltype(__VA_ARGS__)
#endif
// ---------- END fn/detail/macro_begin.hpp ----------

// ---------- RESUME fn/optional.hpp ----------

namespace fn {
inline namespace LIBFN_VERSION {

/**
 * @brief Checks if a type is an `fn::optional` (with any value type)
 *
 * @tparam T Type to check, possibly cv-ref qualified
 */
template <typename T>
concept some_optional = detail::_some_optional<T>;

namespace detail {

// [optional.iterators]: the implementation-defined iterator types for fn::optional. A
// minimal wrapper over T* whose job is to keep pointer-ness out of optional interface.
template <class T> class _optional_iterator {
  static_assert(::std::is_object_v<T>);

  T *p_ = nullptr;

  // Only an optional's base mints iterators from storage pointers; the sibling friendship
  // lets the iterator -> const_iterator converting constructor read p_.
  template <class, class> friend struct ::pfn::detail::_optional_base;
  template <class> friend class _optional_iterator;

  constexpr explicit _optional_iterator(T *p) noexcept : p_(p) {}

public:
  using iterator_concept = ::std::contiguous_iterator_tag;
  using iterator_category = ::std::random_access_iterator_tag;
  using value_type = ::std::remove_cv_t<T>;
  using difference_type = ::std::ptrdiff_t;
  using pointer = T *;
  using reference = T &;

  constexpr _optional_iterator() noexcept = default;

  // iterator -> const_iterator, required by the container iterator requirements
  template <class U>
    requires ::std::is_same_v<U const, T>
  constexpr _optional_iterator(_optional_iterator<U> const &other) noexcept // NOSONAR cpp:S1709 implicit per spec
      : p_(other.p_)
  {
  }

  [[nodiscard]] constexpr T &operator*() const noexcept { return *p_; }
  [[nodiscard]] constexpr T *operator->() const noexcept { return p_; } // std::to_address requires this
  [[nodiscard]] constexpr T &operator[](difference_type n) const noexcept { return p_[n]; }

  constexpr _optional_iterator &operator++() noexcept
  {
    ++p_;
    return *this;
  }
  constexpr _optional_iterator operator++(int) noexcept
  {
    auto r = *this;
    ++p_;
    return r;
  }
  constexpr _optional_iterator &operator--() noexcept
  {
    --p_;
    return *this;
  }
  constexpr _optional_iterator operator--(int) noexcept
  {
    auto r = *this;
    --p_;
    return r;
  }
  constexpr _optional_iterator &operator+=(difference_type n) noexcept
  {
    p_ += n;
    return *this;
  }
  constexpr _optional_iterator &operator-=(difference_type n) noexcept
  {
    p_ -= n;
    return *this;
  }

  [[nodiscard]] constexpr friend _optional_iterator operator+(_optional_iterator i, difference_type n) noexcept
  {
    return i += n;
  }
  [[nodiscard]] constexpr friend _optional_iterator operator+(difference_type n, _optional_iterator i) noexcept
  {
    return i += n;
  }
  [[nodiscard]] constexpr friend _optional_iterator operator-(_optional_iterator i, difference_type n) noexcept
  {
    return i -= n;
  }
  [[nodiscard]] constexpr friend difference_type operator-(_optional_iterator const &x,
                                                           _optional_iterator const &y) noexcept
  {
    return x.p_ - y.p_;
  }

  [[nodiscard]] constexpr friend bool operator==(_optional_iterator const &, _optional_iterator const &) noexcept
      = default;
  [[nodiscard]] constexpr friend ::std::strong_ordering operator<=>(_optional_iterator const &x,
                                                                    _optional_iterator const &y) noexcept
  {
    return x.p_ <=> y.p_;
  }
};

struct optional_policy {
  template <class U> using type = ::fn::optional<U>;
  template <class U> using iterator = _optional_iterator<U>;
  template <class X> static constexpr bool is_specialization = _is_some_optional<X &>;
};

// `or_else` has two arms - the callback's own optional is returned, or its value type and T are
// widened into a copack - and `if constexpr` picks between them. A noexcept-specifier is an ordinary
// constant expression, so it cannot pick: the untaken arm's spelling would have to be well-formed
// too, and it is not. Hence a trait, whose constrained specializations mirror the body's arms. The
// unconstrained primary answers for a callback returning something that is not an optional at all -
// the body's static_assert is the diagnostic there, and it must not be pre-empted by a hard error
// in the specification.
template <typename T, typename Fn, typename ValArg> struct _nothrow_optional_or_else : ::std::false_type {};

template <typename T, typename Fn, typename ValArg>
  requires ::std::is_same_v<::std::remove_cvref_t<typename _apply_result<Fn>::type>, ::fn::optional<T>>
struct _nothrow_optional_or_else<T, Fn, ValArg>
    : ::std::bool_constant<_is_nothrow_applicable<Fn>::value
                               && ::std::is_nothrow_constructible_v<::fn::optional<T>, ::std::in_place_t, ValArg>> {};

template <typename T, typename Fn, typename ValArg>
  requires _is_some_optional<::std::remove_cvref_t<typename _apply_result<Fn>::type> &>
           && (not ::std::is_same_v<::std::remove_cvref_t<typename _apply_result<Fn>::type>, ::fn::optional<T>>)
struct _nothrow_optional_or_else<T, Fn, ValArg> {
  using type = ::std::remove_cvref_t<typename _apply_result<Fn>::type>;
  using new_type = ::fn::optional<copack_for<T, typename type::value_type>>;

  // an empty-copack value can never exist to be relocated: that arm is unreachable, and cannot throw
  static constexpr bool value                                          //
      = _is_nothrow_applicable<Fn>::value                              // the callback
        && _nothrow_initializable<new_type, ::std::in_place_t, ValArg> // self's value
        && (empty_copack<typename type::value_type>
            || _nothrow_initializable<new_type, ::std::in_place_t,
                                      decltype(::std::declval<type>().value())>); // its value
};

// Twin of the trait above for the empty-copack or_else arm, whose body has no engaged branch: the
// self's-value conjunct is dropped, and the callback (with the widening of its value) answers alone.
template <typename T, typename Fn> struct _nothrow_optional_or_else_empty : ::std::false_type {};

template <typename T, typename Fn>
  requires ::std::is_same_v<::std::remove_cvref_t<typename _apply_result<Fn>::type>, ::fn::optional<T>>
struct _nothrow_optional_or_else_empty<T, Fn> : ::std::bool_constant<_is_nothrow_applicable<Fn>::value> {};

template <typename T, typename Fn>
  requires _is_some_optional<::std::remove_cvref_t<typename _apply_result<Fn>::type> &>
           && (not ::std::is_same_v<::std::remove_cvref_t<typename _apply_result<Fn>::type>, ::fn::optional<T>>)
struct _nothrow_optional_or_else_empty<T, Fn> {
  using type = ::std::remove_cvref_t<typename _apply_result<Fn>::type>;
  using new_type = ::fn::optional<copack_for<T, typename type::value_type>>;

  static constexpr bool value             //
      = _is_nothrow_applicable<Fn>::value // the callback
        && _nothrow_initializable<new_type, ::std::in_place_t, decltype(::std::declval<type>().value())>; // its value
};

// The dispatch result of and_then over the value: a plain value answers through _apply_result as
// always; a copack value through the graded join - select for a convergent set (today's behaviour
// and diagnostics verbatim), the joined optional for a heterogeneous all-optional one, absent for
// an invalid one - so the member and the trait below key on one answer and never instantiate the
// select assert for a shape the join owns.
template <typename Fn, typename V> struct _optional_and_then_dispatch : _apply_result<Fn, V> {};
template <typename Fn, typename V>
  requires _some_copack<::std::remove_cvref_t<V>>
struct _optional_and_then_dispatch<Fn, V> : _copack_apply_result<_joining_optional_tag<::fn::optional>, Fn, V> {};

template <typename Fn, typename V>
struct _nothrow_optional_and_then : ::std::bool_constant<_is_nothrow_applicable<Fn, V>::value> {};
template <typename Fn, typename V>
  requires _is_hetero_join<_optional_and_then_dispatch<Fn, V>>
struct _nothrow_optional_and_then<Fn, V> {
  static constexpr bool value = _is_nothrow_rts_applicable<typename _optional_and_then_dispatch<Fn, V>::type, Fn, V>;
};

// Storage layer for ::fn::optional. Inherits the standard-conformant base from
// pfn, then hides the three monadic static helpers with copack-aware variants that
// materialise their result via `optional_policy::template type<U>`.
// The transform helpers hand pfn's _optional_from_invoke constructor a zero-argument
// thunk, so the result's contained value is direct-non-list-initialized from fn's own
// _apply (or copack::transform) result: no extra move, and immovable result types work.
// The statics carry the same extension noexcept as pfn's, computed through fn's own machinery:
// the callback of a copack/pack dispatch is invoked through `_apply`, not called directly, so it is
// `_is_nothrow_applicable` - not the std trait, which is false for a callable that is not directly
// applicable on a copack or a pack - that answers for it.
template <typename T> struct _optional_base : ::pfn::detail::_optional_base<T, optional_policy> {
  using _pfn_base = ::pfn::detail::_optional_base<T, optional_policy>;
  using _pfn_base::_pfn_base;

  // and_then
  template <typename Self, typename Fn>
  static constexpr auto _and_then(Self &&self, Fn &&fn)                                   //
      noexcept(::fn::detail::_nothrow_optional_and_then<Fn, decltype(*FWD(self))>::value) // extension
    requires ::fn::detail::_bind_applicable<Fn, decltype(*FWD(self))>
             && requires { typename ::fn::detail::_optional_and_then_dispatch<Fn, decltype(*FWD(self))>::type; }
  {
    using dispatch = ::fn::detail::_optional_and_then_dispatch<Fn, decltype(*FWD(self))>;
    using type = ::std::remove_cvref_t<typename dispatch::type>;
    static_assert(_is_some_optional<type &>);
    if (self.has_value()) {
      if constexpr (::fn::detail::_is_hetero_join<dispatch>)
        // heterogeneous optional branches: the join announced `type`, every branch converts into
        // it as it returns
        return ::fn::detail::_tagged_join_apply<::fn::detail::_joining_optional_tag<::fn::optional>>(*FWD(self),
                                                                                                     FWD(fn));
      else
        return ::fn::detail::_apply(FWD(fn), *FWD(self));
    } else {
#if defined(__clang__) && __clang_major__ <= 18
      // clang 15-18 miscompile the prvalue return below for three of the four Self ref-qualifier
      // instantiations (&, const &, const &&) at -O1/-O2: the disengaged result is observed with
      // garbage in set_ (storage-poison). The workaround dodges the buggy mandatory copy-elision,
      // at the cost of a move -- an immovable result type must keep the prvalue (the workaround
      // would not compile; the miscompile is not observed in that shape).
      if constexpr (::std::is_move_constructible_v<type>)
        return ::std::move(type(::std::nullopt));
      else
        return type(::std::nullopt);
#else
      return type(::std::nullopt);
#endif
    }
  }

  // and_then, value type is the empty copack: a value can never be constructed, so the callback can
  // never be presented one - it is left alone, not invoked and not even instantiated, and the
  // result is *this unchanged.
  template <typename Self, typename Fn>
  static constexpr auto _and_then(Self &&self, Fn &&)                      //
      noexcept(::std::is_nothrow_constructible_v<::fn::optional<T>, Self>) // extension
      -> ::fn::optional<T>
    requires empty_copack<T> && ::std::is_constructible_v<::fn::optional<T>, Self>
  {
    return FWD(self);
  }

  // or_else (with value-widening into a copack)
  template <typename Self, typename Fn>
  static constexpr auto _or_else(Self &&self, Fn &&fn)                                      //
      noexcept(::fn::detail::_nothrow_optional_or_else<T, Fn, decltype(*FWD(self))>::value) // extension
    requires(not empty_copack<T>) && ::fn::detail::_is_applicable<Fn>::value
            && ::std::is_constructible_v<T, decltype(*FWD(self))>
  {
    using type = ::std::remove_cvref_t<typename ::fn::detail::_apply_result<Fn>::type>;
    static_assert(_is_some_optional<type &>);
    // compare whole optional types (not value_type) so optional<T&> instantiations, whose
    // value_type is the unqualified referent, take the same-type arm
    static_assert(::std::is_same_v<type, ::fn::optional<T>> || some_copack<T>);
    if constexpr (::std::is_same_v<type, ::fn::optional<T>>) {
      if (self.has_value())
        return type(::std::in_place, *FWD(self));
      else
        return ::fn::detail::_apply(FWD(fn));
    } else {
      using new_value_type = copack_for<T, typename type::value_type>;
      using new_type = ::fn::optional<new_value_type>;
      if (self.has_value())
        return new_type{::std::in_place, *FWD(self)};
      else {
        auto t = ::fn::detail::_apply(FWD(fn));
        if (t.has_value()) {
          if constexpr (not empty_copack<typename type::value_type>)
            return new_type{::std::in_place, ::std::move(t).value()};
          else
            ::pfn::unreachable(); // LCOV_EXCL_LINE
        } else
          return new_type{::std::nullopt};
      }
    }
  }

  // or_else, value type is the empty copack: never engaged, so the callback's optional is the whole
  // result - the general overload's engaged arms would have no value to copy. The widening
  // contract is unchanged: copack_for<copack<>, U> is U's own normal form.
  template <typename Self, typename Fn>
  static constexpr auto _or_else(Self &&, Fn &&fn)                          //
      noexcept(::fn::detail::_nothrow_optional_or_else_empty<T, Fn>::value) // extension
    requires empty_copack<T> && ::fn::detail::_is_applicable<Fn>::value
  {
    using type = ::std::remove_cvref_t<typename ::fn::detail::_apply_result<Fn>::type>;
    static_assert(_is_some_optional<type &>);
    if constexpr (::std::is_same_v<type, ::fn::optional<T>>)
      return ::fn::detail::_apply(FWD(fn));
    else {
      using new_value_type = copack_for<T, typename type::value_type>;
      using new_type = ::fn::optional<new_value_type>;
      auto t = ::fn::detail::_apply(FWD(fn));
      if (t.has_value())
        return new_type{::std::in_place, ::std::move(t).value()};
      else
        return new_type{::std::nullopt};
    }
  }

  // or_else for the optional<T&> wrapper: forwards to pfn's reference _or_else (hidden by the
  // _or_else above), propagating its constraints and noexcept -- a reference optional has
  // nothing to copack-widen, so pfn's semantics apply exactly
  template <typename Self, typename Fn>
  static constexpr auto _or_else_ref(Self &&self, Fn &&fn)        //
      noexcept(noexcept(_pfn_base::_or_else(FWD(self), FWD(fn)))) //
      -> decltype(_pfn_base::_or_else(FWD(self), FWD(fn)))
  {
    return _pfn_base::_or_else(FWD(self), FWD(fn));
  }

  // transform, value type is not a copack. In the noexcept spec, only the apply can throw: the
  // result is direct-non-list-initialized from the thunk's result (guaranteed elision).
  template <typename Self, typename Fn>
  static constexpr auto _transform(Self &&self, Fn &&fn)                              //
      noexcept(::fn::detail::_is_nothrow_applicable<Fn, decltype(*FWD(self))>::value) // extension
    requires(not some_copack<T>) && ::fn::detail::_is_applicable_if<not some_copack<T>, Fn, decltype(*FWD(self))>::value
  {
    using new_value_type = ::std::remove_cv_t<typename ::fn::detail::_apply_result<Fn, decltype(*FWD(self))>::type>;
    using type = ::fn::optional<new_value_type>;
    if (self.has_value())
      return type(::pfn::detail::_optional_from_invoke,
                  [&fn, &self]() -> decltype(auto) { return ::fn::detail::_apply(FWD(fn), *FWD(self)); });
    else
      return type(::std::nullopt);
  }

  // transform, value type is a copack (delegates to copack::transform). The callback is constrained here,
  // in the immediate context: the deduced return type instantiates the body, so leaving it to
  // copack::transform's own constraint would make a bad callback a hard error instead of dropping the
  // candidate - and would poison overload resolution, since the losing candidates form their
  // signatures too.
  template <typename Self, typename Fn>
  static constexpr auto _transform(Self &&self, Fn &&fn)  //
      noexcept(noexcept((*FWD(self)).transform(FWD(fn)))) // extension
    requires some_copack<T> && (not empty_copack<T>) && ::fn::detail::_typelist_applicable<Fn, decltype(*FWD(self))>
  {
    using new_value_type = decltype((*FWD(self)).transform(FWD(fn)));
    using type = ::fn::optional<new_value_type>;
    if (self.has_value())
      return type(::pfn::detail::_optional_from_invoke,
                  [&fn, &self]() -> decltype(auto) { return (*FWD(self)).transform(FWD(fn)); });
    else
      return type(::std::nullopt);
  }

  // apply: elimination over both states, both arms required outright - the engaged arm eliminates
  // the value through fn's own _apply (a pack or tuple-like payload by elements, a copack by
  // dispatch), the empty arm is invoked without it. Over an empty-copack value this overload set
  // needs no gate: copack<> has no apply, so _is_applicable and _apply_tagged answer false for every
  // Fn and the general overloads drop out.
  template <typename Self, typename Fn, typename... Args>
  static constexpr auto _apply(Self &&self, Fn &&fn, Args &&...args) //
      noexcept(::fn::detail::_is_nothrow_applicable<Fn, decltype(*FWD(self)), Args...>::value
               && ::fn::detail::_is_nothrow_applicable<Fn, Args...>::value) // extension
      -> decltype(auto)
    requires ::fn::detail::_is_applicable<Fn, decltype(*FWD(self)), Args...>::value
             && ::fn::detail::_is_applicable<Fn, Args...>::value
  {
    // Both arms are viable here, so they must yield the same result type.
    static_assert(::std::is_same_v<typename ::fn::detail::_apply_result<Fn, decltype(*FWD(self)), Args...>::type,
                                   typename ::fn::detail::_apply_result<Fn, Args...>::type>);
    if (self.has_value())
      return ::fn::detail::_apply(FWD(fn), *FWD(self), FWD(args)...);
    else
      return ::fn::detail::_apply(FWD(fn), FWD(args)...);
  }

  template <typename Ret, typename Self, typename Fn, typename... Args>
  static constexpr auto _apply_r(Self &&self, Fn &&fn, Args &&...args) //
      noexcept(::fn::detail::_is_nothrow_applicable_r<Ret, Fn, decltype(*FWD(self)), Args...>::value
               && ::fn::detail::_is_nothrow_applicable_r<Ret, Fn, Args...>::value) // extension
      -> Ret
    requires ::fn::detail::_is_applicable_r<Ret, Fn, decltype(*FWD(self)), Args...>::value
             && ::fn::detail::_is_applicable_r<Ret, Fn, Args...>::value
  {
    if (self.has_value())
      return ::fn::detail::_apply_r<Ret>(FWD(fn), *FWD(self), FWD(args)...);
    else
      return ::fn::detail::_apply_r<Ret>(FWD(fn), FWD(args)...);
  }

  // apply_type: the tagged form - the engaged arm receives ::std::in_place followed by the value
  // as _apply_tagged hands it over (a tuple-like value's elements form is the row's one
  // signature), the empty arm ::std::nullopt alone, passed as a prvalue like every tag; trailing
  // arguments follow either arm's content.
  template <typename Self, typename Fn, typename... Args>
  static constexpr auto _apply_type(Self &&self, Fn &&fn, Args &&...args) //
      noexcept(noexcept(::fn::detail::_apply_tagged<::std::in_place_t>(FWD(fn), *FWD(self), FWD(args)...))
               && ::fn::detail::_is_nothrow_applicable<Fn, ::std::nullopt_t, Args &&...>::value) // extension
      -> decltype(auto)
    requires requires { ::fn::detail::_apply_tagged<::std::in_place_t>(FWD(fn), *FWD(self), FWD(args)...); }
             && ::fn::detail::_is_applicable<Fn, ::std::nullopt_t, Args &&...>::value
  {
    // Both arms are viable here, so they must yield the same result type.
    static_assert(
        ::std::is_same_v<decltype(::fn::detail::_apply_tagged<::std::in_place_t>(FWD(fn), *FWD(self), FWD(args)...)),
                         typename ::fn::detail::_apply_result<Fn, ::std::nullopt_t, Args &&...>::type>);
    if (self.has_value())
      return ::fn::detail::_apply_tagged<::std::in_place_t>(FWD(fn), *FWD(self), FWD(args)...);
    else
      return ::fn::detail::_apply(FWD(fn), ::std::nullopt_t{::std::nullopt}, FWD(args)...);
  }

  template <typename Ret, typename Self, typename Fn, typename... Args>
  static constexpr auto _apply_type_r(Self &&self, Fn &&fn, Args &&...args) //
      noexcept(noexcept(::fn::detail::_apply_tagged_r<Ret, ::std::in_place_t>(FWD(fn), *FWD(self), FWD(args)...))
               && ::fn::detail::_is_nothrow_applicable_r<Ret, Fn, ::std::nullopt_t, Args &&...>::value) // extension
      -> Ret
    requires requires { ::fn::detail::_apply_tagged_r<Ret, ::std::in_place_t>(FWD(fn), *FWD(self), FWD(args)...); }
             && ::fn::detail::_is_applicable_r<Ret, Fn, ::std::nullopt_t, Args &&...>::value
  {
    if (self.has_value())
      return ::fn::detail::_apply_tagged_r<Ret, ::std::in_place_t>(FWD(fn), *FWD(self), FWD(args)...);
    else
      return ::fn::detail::_apply_r<Ret>(FWD(fn), ::std::nullopt_t{::std::nullopt}, FWD(args)...);
  }

  // apply, value type is the empty copack: never engaged, so the empty arm alone is exhaustive and
  // dispatch needs no branch; nothing names the engaged row, so an arm set carrying an arm for it
  // never instantiates it.
  template <typename Self, typename Fn, typename... Args>
  static constexpr auto _apply(Self &&, Fn &&fn, Args &&...args)         //
      noexcept(::fn::detail::_is_nothrow_applicable<Fn, Args...>::value) // extension
      -> decltype(auto)
    requires empty_copack<T> && ::fn::detail::_is_applicable<Fn, Args...>::value
  {
    return ::fn::detail::_apply(FWD(fn), FWD(args)...);
  }

  template <typename Ret, typename Self, typename Fn, typename... Args>
  static constexpr auto _apply_r(Self &&, Fn &&fn, Args &&...args)              //
      noexcept(::fn::detail::_is_nothrow_applicable_r<Ret, Fn, Args...>::value) // extension
      -> Ret
    requires empty_copack<T> && ::fn::detail::_is_applicable_r<Ret, Fn, Args...>::value
  {
    return ::fn::detail::_apply_r<Ret>(FWD(fn), FWD(args)...);
  }

  // apply_type, value type is the empty copack: the nullopt arm alone is exhaustive
  template <typename Self, typename Fn, typename... Args>
  static constexpr auto _apply_type(Self &&, Fn &&fn, Args &&...args)                         //
      noexcept(::fn::detail::_is_nothrow_applicable<Fn, ::std::nullopt_t, Args &&...>::value) // extension
      -> decltype(auto)
    requires empty_copack<T> && ::fn::detail::_is_applicable<Fn, ::std::nullopt_t, Args &&...>::value
  {
    return ::fn::detail::_apply(FWD(fn), ::std::nullopt_t{::std::nullopt}, FWD(args)...);
  }

  template <typename Ret, typename Self, typename Fn, typename... Args>
  static constexpr auto _apply_type_r(Self &&, Fn &&fn, Args &&...args)                              //
      noexcept(::fn::detail::_is_nothrow_applicable_r<Ret, Fn, ::std::nullopt_t, Args &&...>::value) // extension
      -> Ret
    requires empty_copack<T> && ::fn::detail::_is_applicable_r<Ret, Fn, ::std::nullopt_t, Args &&...>::value
  {
    return ::fn::detail::_apply_r<Ret>(FWD(fn), ::std::nullopt_t{::std::nullopt}, FWD(args)...);
  }

  // transform, value type is the empty copack: a value can never be constructed, so the callback can
  // never be presented one - it is left alone, not invoked and not even instantiated, the mapping
  // is the identity and the result is *this unchanged.
  template <typename Self, typename Fn>
  static constexpr auto _transform(Self &&self, Fn &&)                     //
      noexcept(::std::is_nothrow_constructible_v<::fn::optional<T>, Self>) // extension
      -> ::fn::optional<T>
    requires empty_copack<T> && ::std::is_constructible_v<::fn::optional<T>, Self>
  {
    return FWD(self);
  }
};

} // namespace detail

/**
 * @brief The fallible carrier over an empty state: a computation yielding a value or nothing
 *
 * A strict superset of `std::optional` as specified for C++26, provided here by `pfn::optional`:
 * construction, assignment, observers, iterators and comparisons are the standard's, and a valid
 * program switching from `pfn` to `fn` changes neither compilation nor behaviour. On top of the
 * standard contract come the extensions: a `copack` value side enrols the carrier in graded value
 * arithmetic, `copack_value` lifting a plain one; the `apply` family eliminates over both states,
 * the empty arm invoked without a value; `operator&` conjoins and `operator|` disjoins carriers.
 * A `pack` value spreads into callbacks as separate arguments; `optional<T&>` is served by the
 * specialization.
 *
 * @tparam T Value type; an lvalue reference selects the specialization
 */
template <typename T> class optional : private detail::_optional_base<T> { // NOSONAR cpp:S3624 base manages storage
  static_assert(::pfn::detail::_is_valid_optional<T>);
  using _base = detail::_optional_base<T>;

  // Allow sibling _optional_base instantiations to downcast into the private base.
  template <class, class> friend struct ::pfn::detail::_optional_base;
  template <class> friend struct ::fn::detail::_optional_base;

public:
  /**
   * @brief The type of the value side
   */
  using value_type = T;
  // [optional.iterators]: mirrors pfn::optional, with fn's own iterator type
  /**
   * @brief Iterator over the value, if any
   */
  using iterator = detail::_optional_iterator<T>;
  /**
   * @brief Const iterator over the value, if any
   */
  using const_iterator = detail::_optional_iterator<T const>;

  // Constructors. Explicit forwarders to the base mirror pfn::optional.
  /**
   * @brief Default constructor
   */
  constexpr optional() noexcept : _base(::std::nullopt) {}
  /**
   * @brief Constructs the empty state
   */
  constexpr optional(::std::nullopt_t) noexcept : _base(::std::nullopt) {} // NOSONAR cpp:S1709 implicit per spec

  /**
   * @brief Converting constructor from a compatible carrier
   */
  template <class U>
  constexpr explicit(not ::std::is_convertible_v<U const &, T>) optional(optional<U> const &s) //
      noexcept(::std::is_nothrow_constructible_v<T, U const &>)                                // extension
    requires(_base::template _can_copy_convert<U>::value)
      : _base(s)
  {
  }
  /**
   * @brief Converting constructor from a compatible carrier
   */
  template <class U>
  constexpr explicit(not ::std::is_convertible_v<U, T>) optional(optional<U> &&s) //
      noexcept(::std::is_nothrow_constructible_v<T, U>)                           // extension
    requires(_base::template _can_move_convert<U>::value)
      : _base(::std::move(s))
  {
  }
  /**
   * @brief Constructs the value from a value
   */
  template <class U = ::std::remove_cv_t<T>>
  constexpr explicit(not ::std::is_convertible_v<U, T>) optional(U &&v) // NOSONAR cpp:S6458 _can_convert excludes self
      noexcept(::std::is_nothrow_constructible_v<T, U>)                 // extension
    requires(_base::template _can_convert<U>::value)
      : _base(::std::in_place, FWD(v))
  {
  }

  /**
   * @brief Constructs the value in place from the arguments
   */
  template <class... Args>
  constexpr explicit optional(::std::in_place_t, Args &&...a) //
      noexcept(::std::is_nothrow_constructible_v<T, Args...>) // extension
    requires ::std::is_constructible_v<T, Args...>
      : _base(::std::in_place, FWD(a)...)
  {
  }
  /**
   * @brief Constructs the value in place from the arguments
   */
  template <class U, class... Args>
  constexpr explicit optional(::std::in_place_t, ::std::initializer_list<U> il, Args &&...a) //
      noexcept(::std::is_nothrow_constructible_v<T, ::std::initializer_list<U> &, Args...>)  // extension
    requires ::std::is_constructible_v<T, ::std::initializer_list<U> &, Args...>
      : _base(::std::in_place, il, FWD(a)...)
  {
  }

  /**
   * @brief Copy constructor; not available on this carrier
   */
  constexpr optional(optional const &) = delete;
  constexpr optional(optional const &s)                   //
      noexcept(::std::is_nothrow_copy_constructible_v<T>) // extension
    requires(::std::is_copy_constructible_v<T> && ::std::is_trivially_copy_constructible_v<T>)
  = default;
  constexpr optional(optional const &s)                   //
      noexcept(::std::is_nothrow_copy_constructible_v<T>) // extension
    requires(::std::is_copy_constructible_v<T> && not ::std::is_trivially_copy_constructible_v<T>)
      : _base(s.set_, FWD(s).storage_)
  {
  }
  /**
   * @brief Move constructor
   */
  constexpr optional(optional &&) noexcept
    requires(::std::is_move_constructible_v<T> && ::std::is_trivially_move_constructible_v<T>)
  = default;
  constexpr optional(optional &&s) //
      noexcept(::std::is_nothrow_move_constructible_v<T>)
    requires(::std::is_move_constructible_v<T> && not ::std::is_trivially_move_constructible_v<T>)
      : _base(s.set_, FWD(s).storage_)
  {
  }

  /**
   * @brief Destructor
   */
  constexpr ~optional() = default;

  // Assignment. Explicit forwarders to the base mirror pfn::optional.
  /**
   * @brief Assigns the empty state
   */
  constexpr optional &operator=(::std::nullopt_t) noexcept
  {
    this->reset();
    return *this;
  }
  /**
   * @brief Copy assignment; not available on this carrier
   */
  constexpr optional &operator=(optional const &) = delete;
  constexpr optional &operator=(optional const &)                                                   //
      noexcept(::std::is_nothrow_copy_assignable_v<T> && ::std::is_nothrow_copy_constructible_v<T>) // extension
    requires(::std::is_copy_constructible_v<T> && ::std::is_copy_assignable_v<T>
             && ::std::is_trivially_copy_constructible_v<T> && ::std::is_trivially_copy_assignable_v<T>
             && ::std::is_trivially_destructible_v<T>)
  = default;
  constexpr optional &operator=(optional const &s)                                                  //
      noexcept(::std::is_nothrow_copy_assignable_v<T> && ::std::is_nothrow_copy_constructible_v<T>) // extension
    requires(::std::is_copy_constructible_v<T> && ::std::is_copy_assignable_v<T>
             && (not ::std::is_trivially_copy_constructible_v<T> || not ::std::is_trivially_copy_assignable_v<T>
                 || not ::std::is_trivially_destructible_v<T>))
  {
    this->_assign(static_cast<_base const &>(s));
    return *this;
  }
  /**
   * @brief Move assignment
   */
  constexpr optional &operator=(optional &&) //
      noexcept(::std::is_nothrow_move_assignable_v<T> && ::std::is_nothrow_move_constructible_v<T>)
    requires(::std::is_move_constructible_v<T> && ::std::is_move_assignable_v<T>
             && ::std::is_trivially_move_constructible_v<T> && ::std::is_trivially_move_assignable_v<T>
             && ::std::is_trivially_destructible_v<T>)
  = default;
  constexpr optional &operator=(optional &&s) //
      noexcept(::std::is_nothrow_move_assignable_v<T> && ::std::is_nothrow_move_constructible_v<T>)
    requires(::std::is_move_constructible_v<T> && ::std::is_move_assignable_v<T>
             && (not ::std::is_trivially_move_constructible_v<T> || not ::std::is_trivially_move_assignable_v<T>
                 || not ::std::is_trivially_destructible_v<T>))
  {
    this->_assign(static_cast<_base &&>(s));
    return *this;
  }

  /**
   * @brief Assignment from a value
   */
  template <class U = ::std::remove_cv_t<T>>
  constexpr optional &operator=(U &&v)                                                            //
      noexcept(::std::is_nothrow_assignable_v<T &, U> && ::std::is_nothrow_constructible_v<T, U>) // extension
    requires(_base::template _can_assign<U>::value)
  {
    this->_assign_value(FWD(v));
    return *this;
  }
  /**
   * @brief Assignment from a compatible carrier
   */
  template <class U>
  constexpr optional &operator=(optional<U> const &s) //
      noexcept(::std::is_nothrow_assignable_v<T &, U const &>
               && ::std::is_nothrow_constructible_v<T, U const &>) // extension
    requires(_base::template _can_copy_assign<U>::value)
  {
    this->_assign_from(s);
    return *this;
  }
  /**
   * @brief Assignment from a compatible carrier
   */
  template <class U>
  constexpr optional &operator=(optional<U> &&s)                                                  //
      noexcept(::std::is_nothrow_assignable_v<T &, U> && ::std::is_nothrow_constructible_v<T, U>) // extension
    requires(_base::template _can_move_assign<U>::value)
  {
    this->_assign_from(::std::move(s));
    return *this;
  }

  // Emplace and reset inherited from _optional_base
  using _base::emplace;
  using _base::reset;

  // Swap; body delegates to _optional_base helper
  /**
   * @brief Swaps the contents with another `optional`
   */
  constexpr void swap(optional &rhs) //
      noexcept(::std::is_nothrow_move_constructible_v<T> && ::std::is_nothrow_swappable_v<T>)
  {
    static_assert(::std::is_move_constructible_v<T>);
    this->_swap_with(rhs);
  }

  // Iterator support inherited from _optional_base, mirrors pfn::optional
  using _base::begin;
  using _base::end;

  // Observers inherited from _optional_base
  using _base::has_value;
  using _base::operator bool;
  using _base::operator*;
  using _base::operator->;
  using _base::value;
  using _base::value_or;

  // Elimination over both states, mirroring copack's apply family: the engaged arm takes the value
  // unpacked as fn::apply would hand it over, the empty arm takes no value (apply) or the nullopt
  // tag alone (apply_type). Bodies delegate to _optional_base static helpers.
  /**
   * @brief Eliminates over both states: the engaged arm receives the value, the empty arm nothing
   *
   * The engaged arm receives the value as `fn::apply` hands it over - a `pack` or tuple-like
   * value by elements - and the empty arm is invoked with the trailing arguments alone; the arms
   * must yield one result type.
   *
   * @param f Callable with arms for both states; `fn::overload` fuses them
   * @param args Additional arguments, appended after the content
   * @return The callable's result
   */
  template <class F, class... Args>
  [[nodiscard]] constexpr auto apply(F &&f, Args &&...args) &        //
      noexcept(noexcept(_base::_apply(*this, FWD(f), FWD(args)...))) // extension
      -> decltype(_base::_apply(*this, FWD(f), FWD(args)...))
  {
    return _base::_apply(*this, FWD(f), FWD(args)...);
  }
  template <class F, class... Args>
  [[nodiscard]] constexpr auto apply(F &&f, Args &&...args) &&                    //
      noexcept(noexcept(_base::_apply(::std::move(*this), FWD(f), FWD(args)...))) // extension
      -> decltype(_base::_apply(::std::move(*this), FWD(f), FWD(args)...))
  {
    return _base::_apply(::std::move(*this), FWD(f), FWD(args)...);
  }
  template <class F, class... Args>
  [[nodiscard]] constexpr auto apply(F &&f, Args &&...args) const &  //
      noexcept(noexcept(_base::_apply(*this, FWD(f), FWD(args)...))) // extension
      -> decltype(_base::_apply(*this, FWD(f), FWD(args)...))
  {
    return _base::_apply(*this, FWD(f), FWD(args)...);
  }
  template <class F, class... Args>
  [[nodiscard]] constexpr auto apply(F &&f, Args &&...args) const &&              //
      noexcept(noexcept(_base::_apply(::std::move(*this), FWD(f), FWD(args)...))) // extension
      -> decltype(_base::_apply(::std::move(*this), FWD(f), FWD(args)...))
  {
    return _base::_apply(::std::move(*this), FWD(f), FWD(args)...);
  }

  /**
   * @brief Eliminates over both states, converting the result to `Ret`
   *
   * @tparam Ret Type the results convert to
   * @param f Callable with arms for both states; `fn::overload` fuses them
   * @param args Additional arguments, appended after the content
   * @return The callable's result, converted to `Ret`
   */
  template <class Ret, class F, class... Args>
  [[nodiscard]] constexpr auto apply_r(F &&f, Args &&...args) &                      //
      noexcept(noexcept(_base::template _apply_r<Ret>(*this, FWD(f), FWD(args)...))) // extension
      -> decltype(_base::template _apply_r<Ret>(*this, FWD(f), FWD(args)...))
  {
    return _base::template _apply_r<Ret>(*this, FWD(f), FWD(args)...);
  }
  template <class Ret, class F, class... Args>
  [[nodiscard]] constexpr auto apply_r(F &&f, Args &&...args) &&                                  //
      noexcept(noexcept(_base::template _apply_r<Ret>(::std::move(*this), FWD(f), FWD(args)...))) // extension
      -> decltype(_base::template _apply_r<Ret>(::std::move(*this), FWD(f), FWD(args)...))
  {
    return _base::template _apply_r<Ret>(::std::move(*this), FWD(f), FWD(args)...);
  }
  template <class Ret, class F, class... Args>
  [[nodiscard]] constexpr auto apply_r(F &&f, Args &&...args) const &                //
      noexcept(noexcept(_base::template _apply_r<Ret>(*this, FWD(f), FWD(args)...))) // extension
      -> decltype(_base::template _apply_r<Ret>(*this, FWD(f), FWD(args)...))
  {
    return _base::template _apply_r<Ret>(*this, FWD(f), FWD(args)...);
  }
  template <class Ret, class F, class... Args>
  [[nodiscard]] constexpr auto apply_r(F &&f, Args &&...args) const &&                            //
      noexcept(noexcept(_base::template _apply_r<Ret>(::std::move(*this), FWD(f), FWD(args)...))) // extension
      -> decltype(_base::template _apply_r<Ret>(::std::move(*this), FWD(f), FWD(args)...))
  {
    return _base::template _apply_r<Ret>(::std::move(*this), FWD(f), FWD(args)...);
  }

  /**
   * @brief Eliminates over both states, keyed by the tag naming the state
   *
   * The engaged arm receives `std::in_place` followed by the value's content, and the empty arm
   * receives `std::nullopt`.
   *
   * @param f Callable with arms for both tagged states
   * @param args Additional arguments, appended after the content
   * @return The callable's result
   */
  template <class F, class... Args>
  [[nodiscard]] constexpr auto apply_type(F &&f, Args &&...args) &        //
      noexcept(noexcept(_base::_apply_type(*this, FWD(f), FWD(args)...))) // extension
      -> decltype(_base::_apply_type(*this, FWD(f), FWD(args)...))
  {
    return _base::_apply_type(*this, FWD(f), FWD(args)...);
  }
  template <class F, class... Args>
  [[nodiscard]] constexpr auto apply_type(F &&f, Args &&...args) &&                    //
      noexcept(noexcept(_base::_apply_type(::std::move(*this), FWD(f), FWD(args)...))) // extension
      -> decltype(_base::_apply_type(::std::move(*this), FWD(f), FWD(args)...))
  {
    return _base::_apply_type(::std::move(*this), FWD(f), FWD(args)...);
  }
  template <class F, class... Args>
  [[nodiscard]] constexpr auto apply_type(F &&f, Args &&...args) const &  //
      noexcept(noexcept(_base::_apply_type(*this, FWD(f), FWD(args)...))) // extension
      -> decltype(_base::_apply_type(*this, FWD(f), FWD(args)...))
  {
    return _base::_apply_type(*this, FWD(f), FWD(args)...);
  }
  template <class F, class... Args>
  [[nodiscard]] constexpr auto apply_type(F &&f, Args &&...args) const &&              //
      noexcept(noexcept(_base::_apply_type(::std::move(*this), FWD(f), FWD(args)...))) // extension
      -> decltype(_base::_apply_type(::std::move(*this), FWD(f), FWD(args)...))
  {
    return _base::_apply_type(::std::move(*this), FWD(f), FWD(args)...);
  }

  /**
   * @brief Eliminates over both states, keyed by the tag, converting the result to `Ret`
   *
   * @tparam Ret Type the results convert to
   * @param f Callable with arms for both tagged states
   * @param args Additional arguments, appended after the content
   * @return The callable's result, converted to `Ret`
   */
  template <class Ret, class F, class... Args>
  [[nodiscard]] constexpr auto apply_type_r(F &&f, Args &&...args) &                      //
      noexcept(noexcept(_base::template _apply_type_r<Ret>(*this, FWD(f), FWD(args)...))) // extension
      -> decltype(_base::template _apply_type_r<Ret>(*this, FWD(f), FWD(args)...))
  {
    return _base::template _apply_type_r<Ret>(*this, FWD(f), FWD(args)...);
  }
  template <class Ret, class F, class... Args>
  [[nodiscard]] constexpr auto apply_type_r(F &&f, Args &&...args) &&                                  //
      noexcept(noexcept(_base::template _apply_type_r<Ret>(::std::move(*this), FWD(f), FWD(args)...))) // extension
      -> decltype(_base::template _apply_type_r<Ret>(::std::move(*this), FWD(f), FWD(args)...))
  {
    return _base::template _apply_type_r<Ret>(::std::move(*this), FWD(f), FWD(args)...);
  }
  template <class Ret, class F, class... Args>
  [[nodiscard]] constexpr auto apply_type_r(F &&f, Args &&...args) const &                //
      noexcept(noexcept(_base::template _apply_type_r<Ret>(*this, FWD(f), FWD(args)...))) // extension
      -> decltype(_base::template _apply_type_r<Ret>(*this, FWD(f), FWD(args)...))
  {
    return _base::template _apply_type_r<Ret>(*this, FWD(f), FWD(args)...);
  }
  template <class Ret, class F, class... Args>
  [[nodiscard]] constexpr auto apply_type_r(F &&f, Args &&...args) const &&                            //
      noexcept(noexcept(_base::template _apply_type_r<Ret>(::std::move(*this), FWD(f), FWD(args)...))) // extension
      -> decltype(_base::template _apply_type_r<Ret>(::std::move(*this), FWD(f), FWD(args)...))
  {
    return _base::template _apply_type_r<Ret>(::std::move(*this), FWD(f), FWD(args)...);
  }

  // Monadic operations. Bodies delegate to _optional_base static helpers, which perform copack-widening.
  /**
   * @brief Binds the value through the callable, which returns an `optional`
   *
   * As the standard member, extended over the algebra: a copack-valued operand dispatches per
   * alternative, exhaustively, heterogeneous branch values joining into a normalized copack. An
   * empty operand passes through, and over an uninhabited value side the callback is neither
   * invoked nor instantiated.
   *
   * @param f Callable applied on the value, returning an `optional`
   * @return The callback's `optional`; heterogeneous branch values join into a copack
   */
  template <class F>
  constexpr auto and_then(F &&f) &                        //
      noexcept(noexcept(_base::_and_then(*this, FWD(f)))) // extension
      -> decltype(_base::_and_then(*this, FWD(f)))
  {
    return _base::_and_then(*this, FWD(f));
  }
  template <class F>
  constexpr auto and_then(F &&f) &&                                    //
      noexcept(noexcept(_base::_and_then(::std::move(*this), FWD(f)))) // extension
      -> decltype(_base::_and_then(::std::move(*this), FWD(f)))
  {
    return _base::_and_then(::std::move(*this), FWD(f));
  }
  template <class F>
  constexpr auto and_then(F &&f) const &                  //
      noexcept(noexcept(_base::_and_then(*this, FWD(f)))) // extension
      -> decltype(_base::_and_then(*this, FWD(f)))
  {
    return _base::_and_then(*this, FWD(f));
  }
  template <class F>
  constexpr auto and_then(F &&f) const &&                              //
      noexcept(noexcept(_base::_and_then(::std::move(*this), FWD(f)))) // extension
      -> decltype(_base::_and_then(::std::move(*this), FWD(f)))
  {
    return _base::_and_then(::std::move(*this), FWD(f));
  }

  // or_else has only const& and && overloads (mirroring pfn::optional): an extra & or const&&
  // overload would silently change which reference category an engaged value is copied through
  // in a program switched over from pfn::optional.
  /**
   * @brief Binds the empty state through the callable, which returns an `optional`
   *
   * The recovery bind: an engaged operand passes through, and the callback - invoked with no
   * arguments, the empty state carrying no value - names the result. The value sides join under
   * the grading rules, a plain side admitting its singular lift `copack<T>`.
   *
   * @param f Callable invoked with no arguments, returning an `optional`
   * @return The recovery's `optional`, its value side joined with the operand's
   */
  template <class F>
  constexpr auto or_else(F &&f) const &                  //
      noexcept(noexcept(_base::_or_else(*this, FWD(f)))) // extension
      -> decltype(_base::_or_else(*this, FWD(f)))
  {
    return _base::_or_else(*this, FWD(f));
  }
  template <class F>
  constexpr auto or_else(F &&f) &&                                    //
      noexcept(noexcept(_base::_or_else(::std::move(*this), FWD(f)))) // extension
      -> decltype(_base::_or_else(::std::move(*this), FWD(f)))
  {
    return _base::_or_else(::std::move(*this), FWD(f));
  }

  /**
   * @brief Maps the value through the callable, staying inside the carrier
   *
   * As the standard member, extended over the algebra: a `pack` value spreads into the callable
   * by elements, and a copack-valued operand dispatches per alternative - heterogeneous branch
   * results joining into a normalized copack. Over an uninhabited value side the mapping is the
   * identity, and the callback is neither invoked nor instantiated.
   *
   * @param f Callable applied on the value
   * @return An `optional` holding the callable's result
   */
  template <class F>
  constexpr auto transform(F &&f) &                        //
      noexcept(noexcept(_base::_transform(*this, FWD(f)))) // extension
      -> decltype(_base::_transform(*this, FWD(f)))
  {
    return _base::_transform(*this, FWD(f));
  }
  template <class F>
  constexpr auto transform(F &&f) &&                                    //
      noexcept(noexcept(_base::_transform(::std::move(*this), FWD(f)))) // extension
      -> decltype(_base::_transform(::std::move(*this), FWD(f)))
  {
    return _base::_transform(::std::move(*this), FWD(f));
  }
  template <class F>
  constexpr auto transform(F &&f) const &                  //
      noexcept(noexcept(_base::_transform(*this, FWD(f)))) // extension
      -> decltype(_base::_transform(*this, FWD(f)))
  {
    return _base::_transform(*this, FWD(f));
  }
  template <class F>
  constexpr auto transform(F &&f) const &&                              //
      noexcept(noexcept(_base::_transform(::std::move(*this), FWD(f)))) // extension
      -> decltype(_base::_transform(::std::move(*this), FWD(f)))
  {
    return _base::_transform(::std::move(*this), FWD(f));
  }

  // Convert to graded monad. The lifting overloads wrap the value in a copack and that copack in the
  // result, so they weigh both; the ones whose value type already is a copack only return *this.
  /**
   * @brief Lifts the value side into its singular copack: `optional<T>` becomes
   *        `optional<copack<T>>`
   *
   * The explicit entry into the graded world; an already-copack value side returns `*this`
   * unchanged.
   *
   * @return The graded `optional`, relocating the value
   */
  constexpr auto
  copack_value() const & noexcept(::std::is_nothrow_constructible_v<copack<value_type>, value_type const &>
                                  && ::std::is_nothrow_move_constructible_v<copack<value_type>>) // extension
      -> optional<copack<value_type>>
    requires(not some_copack<value_type>)
  {
    using type = optional<copack<value_type>>;
    if (this->has_value())
      return type{::std::in_place, copack<value_type>(this->value())};
    else
      return type{::std::nullopt};
  }
  constexpr auto copack_value() && noexcept(::std::is_nothrow_constructible_v<copack<value_type>, value_type>
                                            && ::std::is_nothrow_move_constructible_v<copack<value_type>>) // extension
      -> optional<copack<value_type>>
    requires(not some_copack<value_type>)
  {
    using type = optional<copack<value_type>>;
    if (this->has_value())
      return type{::std::in_place, copack<value_type>(::std::move(*this).value())};
    else
      return type{::std::nullopt};
  }
  constexpr auto copack_value() & noexcept -> decltype(auto)
    requires(some_copack<value_type>)
  {
    return *this;
  }
  constexpr auto copack_value() const & noexcept -> decltype(auto)
    requires(some_copack<value_type>)
  {
    return *this;
  }
  constexpr auto copack_value() && noexcept -> decltype(auto)
    requires(some_copack<value_type>)
  {
    return ::std::move(*this);
  }
  constexpr auto copack_value() const && noexcept -> decltype(auto)
    requires(some_copack<value_type>)
  {
    return ::std::move(*this);
  }

private:
  // Direct-non-list-initializes the contained value from the result of a callable; used by
  // the monadic functions implemented in _optional_base.
  template <class Fn, class... Args>
  constexpr explicit optional(::pfn::detail::_optional_from_invoke_t tag, Fn &&fn, Args &&...args) //
      noexcept(::std::is_nothrow_constructible_v<_base, ::pfn::detail::_optional_from_invoke_t, Fn, Args...>)
      : _base(tag, FWD(fn), FWD(args)...)
  {
  }
};

template <class T> optional(T) -> optional<T>;

/**
 * @brief The `optional` specialization over an lvalue reference: a rebindable, non-owning view
 *
 * As `std::optional<T&>` is specified for C++26 - the one carrier that holds a raw reference.
 * Lifetime responsibility for the referent stays with the caller. The extensions mirror
 * `optional<T>`'s, the callable always receiving a plain `T&`.
 *
 * @tparam T Referent type
 */
// Partial specialization for lvalue reference types, mirroring pfn::optional<T&>. The monadic
// operations delegate to the same fn::detail::_optional_base statics as optional<T>'s, which
// the underlying pfn reference base makes shallow: the callable always receives plain T&, and
// there is only ever one overload of each (no ref-qualifier/const overload set).
template <class T> class optional<T &> : private detail::_optional_base<T &> {
  static_assert(::pfn::detail::_is_valid_optional<T>);
  using _base = detail::_optional_base<T &>;

  // Allow sibling _optional_base instantiations to downcast into the private base.
  template <class, class> friend struct ::pfn::detail::_optional_base;
  template <class> friend struct ::fn::detail::_optional_base;

public:
  /**
   * @brief The type of the value side
   */
  using value_type = T;
  // [optional.ref.iterators]: mirrors pfn::optional, with fn's own iterator type
  /**
   * @brief Iterator over the value, if any
   */
  using iterator = detail::_optional_iterator<T>;

  // Constructors. Explicit forwarders to the base mirror pfn::optional.
  /**
   * @brief Default constructor
   */
  constexpr optional() noexcept = default;
  /**
   * @brief Constructs the empty state
   */
  constexpr optional(::std::nullopt_t) noexcept : optional() {} // NOSONAR cpp:S1709 implicit per spec
  /**
   * @brief Copy constructor
   */
  constexpr optional(optional const &rhs) noexcept = default;

  /**
   * @brief Constructs the value in place from the arguments
   */
  template <class Arg>
  constexpr explicit optional(::std::in_place_t, Arg &&arg) //
      noexcept(::std::is_nothrow_constructible_v<T &, Arg>) // extension
    requires ::std::is_constructible_v<T &, Arg>
      : _base(::std::in_place, FWD(arg))
  {
  }

  template <class U>
  constexpr explicit(not ::std::is_convertible_v<U, T &>)
      /**
       * @brief Constructs the value from a value
       */
      optional(U &&u) // NOSONAR cpp:S6458 _can_convert excludes self
      noexcept(::std::is_nothrow_constructible_v<T &, U>)
    requires(_base::template _can_convert<U>::value)
      : _base(::std::in_place, FWD(u))
  {
  }
  /**
   * @brief Converting constructor from a compatible carrier
   */
  template <class U>
  constexpr explicit(not ::std::is_convertible_v<U &, T &>) optional(optional<U> &rhs) //
      noexcept(::std::is_nothrow_constructible_v<T &, U &>)
    requires(_base::template _can_convert_from<U, U &>::value)
      : _base(rhs)
  {
  }
  /**
   * @brief Converting constructor from a compatible carrier
   */
  template <class U>
  constexpr explicit(not ::std::is_convertible_v<U const &, T &>) optional(optional<U> const &rhs) //
      noexcept(::std::is_nothrow_constructible_v<T &, U const &>)
    requires(_base::template _can_convert_from<U, U const &>::value)
      : _base(rhs)
  {
  }
  /**
   * @brief Converting constructor from a compatible carrier
   */
  template <class U>
  constexpr explicit(not ::std::is_convertible_v<U, T &>) optional(optional<U> &&rhs) //
      noexcept(::std::is_nothrow_constructible_v<T &, U>)
    requires(_base::template _can_convert_from<U, U>::value)
      : _base(::std::move(rhs))
  {
  }
  /**
   * @brief Converting constructor from a compatible carrier
   */
  template <class U>
  constexpr explicit(not ::std::is_convertible_v<U const, T &>) optional(optional<U> const &&rhs) //
      noexcept(::std::is_nothrow_constructible_v<T &, U const>)
    requires(_base::template _can_convert_from<U, U const>::value)
      : _base(::std::move(rhs))
  {
  }

  /**
   * @brief Destructor
   */
  constexpr ~optional() = default;

  // Assignment
  /**
   * @brief Assigns the empty state
   */
  constexpr optional &operator=(::std::nullopt_t) noexcept
  {
    this->reset();
    return *this;
  }
  /**
   * @brief Copy assignment
   */
  constexpr optional &operator=(optional const &rhs) noexcept = default;

  // Emplace and reset inherited from _optional_base
  using _base::emplace;
  using _base::reset;

  // Swap; body delegates to _optional_base helper
  /**
   * @brief Swaps the contents with another `optional`
   */
  constexpr void swap(optional &rhs) noexcept { this->_swap_with(rhs); }

  // Iterator support inherited from _optional_base, mirrors pfn::optional
  using _base::begin;
  using _base::end;

  // Observers inherited from _optional_base
  using _base::has_value;
  using _base::operator bool;
  using _base::operator*;
  using _base::operator->;
  using _base::value;
  using _base::value_or;

  // Bodies delegate to _optional_base static helpers.

  /**
   * @brief Eliminates over both states: the engaged arm receives the referent, the empty arm
   *        nothing
   *
   * The engaged arm receives a plain `T&` - a reference optional hands the referent over as
   * itself, never by elements - and the empty arm the trailing arguments alone; the arms must
   * yield one result type.
   *
   * @param f Callable with arms for both states; `fn::overload` fuses them
   * @param args Additional arguments, appended after the content
   * @return The callable's result
   */
  template <class F, class... Args>
  [[nodiscard]] constexpr auto apply(F &&f, Args &&...args) const    //
      noexcept(noexcept(_base::_apply(*this, FWD(f), FWD(args)...))) // extension
      -> decltype(_base::_apply(*this, FWD(f), FWD(args)...))
  {
    return _base::_apply(*this, FWD(f), FWD(args)...);
  }

  /**
   * @brief Eliminates over both states, converting the result to `Ret`
   *
   * @tparam Ret Type the results convert to
   * @param f Callable with arms for both states; `fn::overload` fuses them
   * @param args Additional arguments, appended after the content
   * @return The callable's result, converted to `Ret`
   */
  template <class Ret, class F, class... Args>
  [[nodiscard]] constexpr auto apply_r(F &&f, Args &&...args) const                  //
      noexcept(noexcept(_base::template _apply_r<Ret>(*this, FWD(f), FWD(args)...))) // extension
      -> decltype(_base::template _apply_r<Ret>(*this, FWD(f), FWD(args)...))
  {
    return _base::template _apply_r<Ret>(*this, FWD(f), FWD(args)...);
  }

  /**
   * @brief Eliminates over both states, keyed by the tag naming the state
   *
   * The engaged arm receives `std::in_place` followed by the referent, and the empty arm
   * `std::nullopt`.
   *
   * @param f Callable with arms for both tagged states
   * @param args Additional arguments, appended after the content
   * @return The callable's result
   */
  template <class F, class... Args>
  [[nodiscard]] constexpr auto apply_type(F &&f, Args &&...args) const    //
      noexcept(noexcept(_base::_apply_type(*this, FWD(f), FWD(args)...))) // extension
      -> decltype(_base::_apply_type(*this, FWD(f), FWD(args)...))
  {
    return _base::_apply_type(*this, FWD(f), FWD(args)...);
  }

  /**
   * @brief Eliminates over both states, keyed by the tag, converting the result to `Ret`
   *
   * @tparam Ret Type the results convert to
   * @param f Callable with arms for both tagged states
   * @param args Additional arguments, appended after the content
   * @return The callable's result, converted to `Ret`
   */
  template <class Ret, class F, class... Args>
  [[nodiscard]] constexpr auto apply_type_r(F &&f, Args &&...args) const                  //
      noexcept(noexcept(_base::template _apply_type_r<Ret>(*this, FWD(f), FWD(args)...))) // extension
      -> decltype(_base::template _apply_type_r<Ret>(*this, FWD(f), FWD(args)...))
  {
    return _base::template _apply_type_r<Ret>(*this, FWD(f), FWD(args)...);
  }

  // Bodies delegate to _optional_base static helpers.

  /**
   * @brief Binds the referent through the callable, which returns an `optional`
   *
   * The callable receives a plain `T&` and names the result outright, so a bind may leave the
   * reference behind for an owning `optional`. An empty operand passes through.
   *
   * @param f Callable applied on the referent, returning an `optional`
   * @return The callback's `optional`
   */
  template <class F>
  constexpr auto and_then(F &&f) const                    //
      noexcept(noexcept(_base::_and_then(*this, FWD(f)))) // extension
      -> decltype(_base::_and_then(*this, FWD(f)))
  {
    return _base::_and_then(*this, FWD(f));
  }

  /**
   * @brief Maps the referent through the callable, staying inside the carrier
   *
   * The callable receives a plain `T&`, and its result type becomes the new value side - a
   * callable returning a reference keeps the result a view, one returning a value makes it own.
   * An empty operand passes through uninvoked.
   *
   * @param f Callable applied on the referent
   * @return An `optional` holding the callable's result
   */
  template <class F>
  constexpr auto transform(F &&f) const                    //
      noexcept(noexcept(_base::_transform(*this, FWD(f)))) // extension
      -> decltype(_base::_transform(*this, FWD(f)))
  {
    return _base::_transform(*this, FWD(f));
  }

  /**
   * @brief Binds the empty state through the callable, which returns this same `optional`
   *
   * The recovery bind: an engaged operand passes through, and the callback - invoked with no
   * arguments, the empty state carrying no value - supplies the result. A reference optional has
   * no value side to grade, so the callback must return this very type, as the standard member
   * requires.
   *
   * @param f Callable invoked with no arguments, returning an `optional<T &>`
   * @return The recovery's `optional`, or the operand where it is engaged
   */
  template <class F>
  constexpr auto or_else(F &&f) const                        //
      noexcept(noexcept(_base::_or_else_ref(*this, FWD(f)))) // extension
      -> decltype(_base::_or_else_ref(*this, FWD(f)))
    requires ::std::invocable<F>
  {
    return _base::_or_else_ref(*this, FWD(f));
  }

private:
  // Direct-non-list-initializes the bound reference from the result of a callable; used by
  // the monadic functions implemented in _optional_base.
  template <class Fn, class... Args>
  constexpr explicit optional(::pfn::detail::_optional_from_invoke_t tag, Fn &&fn, Args &&...args) //
      noexcept(::std::is_nothrow_constructible_v<_base, ::pfn::detail::_optional_from_invoke_t, Fn, Args...>)
      : _base(tag, FWD(fn), FWD(args)...)
  {
  }
};

namespace detail {
// Deduction probe: deliberately declared without a definition (it is only named in an
// unevaluated context), and called qualified so that ADL cannot pull unrelated overloads.
template <class U> void _derived_from_optional(::fn::optional<U> const &);

template <class T>
concept _is_derived_from_optional = requires(T const &t) { ::fn::detail::_derived_from_optional(t); };
} // namespace detail

// Comparison operators, the same full set as pfn::optional's (whose namespace-scope templates
// do not apply here, since fn::optional does not derive from pfn::optional).

// Relational operators
/**
 * @brief Compares two optionals; two empty optionals are equal
 */
template <class T, class U>
constexpr bool operator==(optional<T> const &x, optional<U> const &y) //
    noexcept(::pfn::detail::_eq_bool_noexcept<T, U>)                  // extension
  requires ::pfn::detail::_eq_bool<T, U>
{
  if (x.has_value() != y.has_value())
    return false;
  if (not x.has_value())
    return true;
  return *x == *y;
}
/**
 * @brief The negation of `==` for two optionals
 */
template <class T, class U>
constexpr bool operator!=(optional<T> const &x, optional<U> const &y) //
    noexcept(::pfn::detail::_ne_bool_noexcept<T, U>)                  // extension
  requires ::pfn::detail::_ne_bool<T, U>
{
  if (x.has_value() != y.has_value())
    return true;
  if (not x.has_value())
    return false;
  return *x != *y;
}
/**
 * @brief Orders two optionals, the empty state before every value
 */
template <class T, class U>
constexpr bool operator<(optional<T> const &x, optional<U> const &y) //
    noexcept(::pfn::detail::_lt_bool_noexcept<T, U>)                 // extension
  requires ::pfn::detail::_lt_bool<T, U>
{
  if (not y.has_value())
    return false;
  if (not x.has_value())
    return true;
  return *x < *y;
}
/**
 * @brief Orders two optionals, the empty state before every value
 */
template <class T, class U>
constexpr bool operator>(optional<T> const &x, optional<U> const &y) //
    noexcept(::pfn::detail::_gt_bool_noexcept<T, U>)                 // extension
  requires ::pfn::detail::_gt_bool<T, U>
{
  if (not x.has_value())
    return false;
  if (not y.has_value())
    return true;
  return *x > *y;
}
/**
 * @brief Orders two optionals, the empty state before every value
 */
template <class T, class U>
constexpr bool operator<=(optional<T> const &x, optional<U> const &y) //
    noexcept(::pfn::detail::_le_bool_noexcept<T, U>)                  // extension
  requires ::pfn::detail::_le_bool<T, U>
{
  if (not x.has_value())
    return true;
  if (not y.has_value())
    return false;
  return *x <= *y;
}
/**
 * @brief Orders two optionals, the empty state before every value
 */
template <class T, class U>
constexpr bool operator>=(optional<T> const &x, optional<U> const &y) //
    noexcept(::pfn::detail::_ge_bool_noexcept<T, U>)                  // extension
  requires ::pfn::detail::_ge_bool<T, U>
{
  if (not y.has_value())
    return true;
  if (not x.has_value())
    return false;
  return *x >= *y;
}
/**
 * @brief Orders two optionals, the empty state before every value
 */
template <class T, ::std::three_way_comparable_with<T> U>
constexpr ::std::compare_three_way_result_t<T, U> operator<=>(optional<T> const &x, optional<U> const &y)
{
  return x.has_value() && y.has_value() ? *x <=> *y : x.has_value() <=> y.has_value();
}

// Comparison with nullopt
/**
 * @brief Whether the optional is empty
 */
template <class T> constexpr bool operator==(optional<T> const &x, ::std::nullopt_t) noexcept
{
  return not x.has_value();
}
/**
 * @brief Orders the optional against the empty state, which precedes every value
 */
template <class T> constexpr ::std::strong_ordering operator<=>(optional<T> const &x, ::std::nullopt_t) noexcept
{
  return x.has_value() <=> false;
}

// Comparison with a value
/**
 * @brief Compares an optional against a value; an empty optional equals nothing
 */
template <class T, class U>
constexpr bool operator==(optional<T> const &x, U const &v) //
    noexcept(::pfn::detail::_eq_bool_noexcept<T, U>)        // extension
  requires(not detail::_is_some_optional<U &>) && ::pfn::detail::_eq_bool<T, U>
{
  return x.has_value() ? *x == v : false;
}
/**
 * @brief Compares a value against an optional; an empty optional equals nothing
 */
template <class T, class U>
constexpr bool operator==(T const &v, optional<U> const &x) //
    noexcept(::pfn::detail::_eq_bool_noexcept<T, U>)        // extension
  requires(not detail::_is_some_optional<T &>) && ::pfn::detail::_eq_bool<T, U>
{
  return x.has_value() ? v == *x : false;
}
/**
 * @brief The negation of `==` against a value
 */
template <class T, class U>
constexpr bool operator!=(optional<T> const &x, U const &v) //
    noexcept(::pfn::detail::_ne_bool_noexcept<T, U>)        // extension
  requires(not detail::_is_some_optional<U &>) && ::pfn::detail::_ne_bool<T, U>
{
  return x.has_value() ? *x != v : true;
}
/**
 * @brief The negation of `==` against a value
 */
template <class T, class U>
constexpr bool operator!=(T const &v, optional<U> const &x) //
    noexcept(::pfn::detail::_ne_bool_noexcept<T, U>)        // extension
  requires(not detail::_is_some_optional<T &>) && ::pfn::detail::_ne_bool<T, U>
{
  return x.has_value() ? v != *x : true;
}
/**
 * @brief Orders an optional against a value, an empty optional before it
 */
template <class T, class U>
constexpr bool operator<(optional<T> const &x, U const &v) //
    noexcept(::pfn::detail::_lt_bool_noexcept<T, U>)       // extension
  requires(not detail::_is_some_optional<U &>) && ::pfn::detail::_lt_bool<T, U>
{
  return x.has_value() ? *x < v : true;
}
/**
 * @brief Orders an optional against a value, an empty optional before it
 */
template <class T, class U>
constexpr bool operator<(T const &v, optional<U> const &x) //
    noexcept(::pfn::detail::_lt_bool_noexcept<T, U>)       // extension
  requires(not detail::_is_some_optional<T &>) && ::pfn::detail::_lt_bool<T, U>
{
  return x.has_value() ? v < *x : false;
}
/**
 * @brief Orders an optional against a value, an empty optional before it
 */
template <class T, class U>
constexpr bool operator>(optional<T> const &x, U const &v) //
    noexcept(::pfn::detail::_gt_bool_noexcept<T, U>)       // extension
  requires(not detail::_is_some_optional<U &>) && ::pfn::detail::_gt_bool<T, U>
{
  return x.has_value() ? *x > v : false;
}
/**
 * @brief Orders an optional against a value, an empty optional before it
 */
template <class T, class U>
constexpr bool operator>(T const &v, optional<U> const &x) //
    noexcept(::pfn::detail::_gt_bool_noexcept<T, U>)       // extension
  requires(not detail::_is_some_optional<T &>) && ::pfn::detail::_gt_bool<T, U>
{
  return x.has_value() ? v > *x : true;
}
/**
 * @brief Orders an optional against a value, an empty optional before it
 */
template <class T, class U>
constexpr bool operator<=(optional<T> const &x, U const &v) //
    noexcept(::pfn::detail::_le_bool_noexcept<T, U>)        // extension
  requires(not detail::_is_some_optional<U &>) && ::pfn::detail::_le_bool<T, U>
{
  return x.has_value() ? *x <= v : true;
}
/**
 * @brief Orders an optional against a value, an empty optional before it
 */
template <class T, class U>
constexpr bool operator<=(T const &v, optional<U> const &x) //
    noexcept(::pfn::detail::_le_bool_noexcept<T, U>)        // extension
  requires(not detail::_is_some_optional<T &>) && ::pfn::detail::_le_bool<T, U>
{
  return x.has_value() ? v <= *x : false;
}
/**
 * @brief Orders an optional against a value, an empty optional before it
 */
template <class T, class U>
constexpr bool operator>=(optional<T> const &x, U const &v) //
    noexcept(::pfn::detail::_ge_bool_noexcept<T, U>)        // extension
  requires(not detail::_is_some_optional<U &>) && ::pfn::detail::_ge_bool<T, U>
{
  return x.has_value() ? *x >= v : false;
}
/**
 * @brief Orders an optional against a value, an empty optional before it
 */
template <class T, class U>
constexpr bool operator>=(T const &v, optional<U> const &x) //
    noexcept(::pfn::detail::_ge_bool_noexcept<T, U>)        // extension
  requires(not detail::_is_some_optional<T &>) && ::pfn::detail::_ge_bool<T, U>
{
  return x.has_value() ? v >= *x : true;
}
/**
 * @brief Orders an optional against a value, an empty optional before it
 */
template <class T, class U>
  requires(not detail::_is_derived_from_optional<U>) && ::std::three_way_comparable_with<T, U>
constexpr ::std::compare_three_way_result_t<T, U> operator<=>(optional<T> const &x, U const &v)
{
  return x.has_value() ? *x <=> v : ::std::strong_ordering::less;
}

// Specialized algorithms
/**
 * @brief Swaps two optionals
 */
template <class T>
constexpr void swap(optional<T> &x, optional<T> &y) noexcept(noexcept(x.swap(y)))
  requires(::std::is_reference_v<T> || (::std::is_move_constructible_v<T> && ::std::is_swappable_v<T>))
{
  x.swap(y);
}

// The leading defaulted non-type parameter mirrors pfn::make_optional: an explicit
// template-argument-list beginning with a type template-argument always selects an in_place
// overload below (for U = X& there is nothing this overload could do: decay_t strips the
// reference and would silently copy the referent).
template <int = 0, class T>
constexpr optional<::std::decay_t<T>> make_optional(T &&v)                      //
    noexcept(::std::is_nothrow_constructible_v<optional<::std::decay_t<T>>, T>) // extension
{
  return optional<::std::decay_t<T>>(FWD(v));
}
template <class T, class... Args>
constexpr optional<T> make_optional(Args &&...args)         //
    noexcept(::std::is_nothrow_constructible_v<T, Args...>) // extension
{
  return optional<T>(::std::in_place, FWD(args)...);
}
template <class T, class U, class... Args>
constexpr optional<T> make_optional(::std::initializer_list<U> il, Args &&...args)        //
    noexcept(::std::is_nothrow_constructible_v<T, ::std::initializer_list<U> &, Args...>) // extension
{
  return optional<T>(::std::in_place, il, FWD(args)...);
}

// Lifts for copack transformation functions
[[nodiscard]] constexpr auto copack_value(some_optional auto &&src) noexcept(noexcept(FWD(src).copack_value()))
    -> decltype(auto)
{
  return FWD(src).copack_value();
}

namespace detail {
// A named type, not a lambda: `operator&`'s specification has to name it, and a lambda cannot be
// spelled in an unevaluated operand before C++20's P0315, which our floor compilers predate.
struct _optional_efn final {
  [[nodiscard]] constexpr auto operator()(auto const &) const noexcept -> ::std::nullopt_t { return ::std::nullopt; }
};
} // namespace detail

// The conjunction of optionals: values multiply into a `pack`, empty is the one failure
//
// `a & b` is engaged only if both operands are, the values folding into one `pack` - a copack
// value distributing into a copack of packs - and empty otherwise: `optional`'s unit error needs
// no summing. Both operands are fully constructed before the operator runs. An identity-cluster
// operand contributes its value and can never be the empty side.
template <some_optional Lh, some_optional Rh>
[[nodiscard]] constexpr auto operator&(Lh &&lh, Rh &&rh) //
    noexcept(noexcept(::fn::detail::_join<fn::optional>(FWD(lh), FWD(rh), detail::_optional_efn{})))
{
  return ::fn::detail::_join<fn::optional>(FWD(lh), FWD(rh), detail::_optional_efn{});
}

// The identity cluster in the conjunction: a just or choice operand always contributes its value
// to the product and adds no term to the error sum, so the optional operand's state decides alone.
// just<void> is the product's unit and elides.
template <typename Lh, some_optional Rh>
  requires(::fn::detail::_some_just<Lh> || ::fn::detail::_some_choice<Lh>)
          && (not ::std::is_void_v<typename ::std::remove_cvref_t<Lh>::value_type>)
[[nodiscard]] constexpr auto operator&(Lh &&lh, Rh &&rh) //
    noexcept(::fn::detail::_nothrow_join<fn::optional, Lh, Rh, detail::_optional_efn>)
{
  using type = optional<::fn::detail::_joined_t<Lh, Rh>>;
  if constexpr (::fn::detail::_uninhabited_join<Lh, Rh>) {
    return type{::std::nullopt};
  } else {
    using VL = ::std::remove_cvref_t<Lh>::value_type;
    using VR = ::std::remove_cvref_t<Rh>::value_type;
    if (rh.has_value())
      return type{::std::in_place, ::fn::detail::_fold_detail::fold<VL, VR>(FWD(lh).value(), FWD(rh).value())};
    return type{::std::nullopt};
  }
}

template <some_optional Lh, typename Rh>
  requires(::fn::detail::_some_just<Rh> || ::fn::detail::_some_choice<Rh>)
          && (not ::std::is_void_v<typename ::std::remove_cvref_t<Rh>::value_type>)
[[nodiscard]] constexpr auto operator&(Lh &&lh, Rh &&rh) //
    noexcept(::fn::detail::_nothrow_join<fn::optional, Lh, Rh, detail::_optional_efn>)
{
  using type = optional<::fn::detail::_joined_t<Lh, Rh>>;
  if constexpr (::fn::detail::_uninhabited_join<Lh, Rh>) {
    return type{::std::nullopt};
  } else {
    using VL = ::std::remove_cvref_t<Lh>::value_type;
    using VR = ::std::remove_cvref_t<Rh>::value_type;
    if (lh.has_value())
      return type{::std::in_place, ::fn::detail::_fold_detail::fold<VL, VR>(FWD(lh).value(), FWD(rh).value())};
    return type{::std::nullopt};
  }
}

template <typename Lh, some_optional Rh>
  requires ::fn::detail::_some_just<Lh> && ::std::is_void_v<typename ::std::remove_cvref_t<Lh>::value_type>
[[nodiscard]] constexpr auto operator&(Lh &&, Rh &&rh) //
    noexcept(::fn::detail::_nothrow_initializable<::std::remove_cvref_t<Rh>, Rh>) -> ::std::remove_cvref_t<Rh>
{
  return ::std::remove_cvref_t<Rh>{FWD(rh)};
}

template <some_optional Lh, typename Rh>
  requires ::fn::detail::_some_just<Rh> && ::std::is_void_v<typename ::std::remove_cvref_t<Rh>::value_type>
[[nodiscard]] constexpr auto operator&(Lh &&lh, Rh &&) //
    noexcept(::fn::detail::_nothrow_initializable<::std::remove_cvref_t<Lh>, Lh>) -> ::std::remove_cvref_t<Lh>
{
  return ::std::remove_cvref_t<Lh>{FWD(lh)};
}

// The identity expected is the cluster's third member: its uninhabited error contributes nothing
// to the sum, so against optional it composes exactly as just does - and expected<void, copack<>>
// elides as the product's unit.
template <typename Lh, some_optional Rh>
  requires ::fn::detail::_some_expected<Lh> && empty_copack<typename ::std::remove_cvref_t<Lh>::error_type>
           && (not ::std::is_void_v<typename ::std::remove_cvref_t<Lh>::value_type>)
[[nodiscard]] constexpr auto operator&(Lh &&lh, Rh &&rh) //
    noexcept(::fn::detail::_nothrow_join<fn::optional, Lh, Rh, detail::_optional_efn>)
{
  using type = optional<::fn::detail::_joined_t<Lh, Rh>>;
  if constexpr (::fn::detail::_uninhabited_join<Lh, Rh>) {
    return type{::std::nullopt};
  } else {
    using VL = ::std::remove_cvref_t<Lh>::value_type;
    using VR = ::std::remove_cvref_t<Rh>::value_type;
    if (rh.has_value())
      return type{::std::in_place, ::fn::detail::_fold_detail::fold<VL, VR>(FWD(lh).value(), FWD(rh).value())};
    return type{::std::nullopt};
  }
}

template <some_optional Lh, typename Rh>
  requires ::fn::detail::_some_expected<Rh> && empty_copack<typename ::std::remove_cvref_t<Rh>::error_type>
           && (not ::std::is_void_v<typename ::std::remove_cvref_t<Rh>::value_type>)
[[nodiscard]] constexpr auto operator&(Lh &&lh, Rh &&rh) //
    noexcept(::fn::detail::_nothrow_join<fn::optional, Lh, Rh, detail::_optional_efn>)
{
  using type = optional<::fn::detail::_joined_t<Lh, Rh>>;
  if constexpr (::fn::detail::_uninhabited_join<Lh, Rh>) {
    return type{::std::nullopt};
  } else {
    using VL = ::std::remove_cvref_t<Lh>::value_type;
    using VR = ::std::remove_cvref_t<Rh>::value_type;
    if (lh.has_value())
      return type{::std::in_place, ::fn::detail::_fold_detail::fold<VL, VR>(FWD(lh).value(), FWD(rh).value())};
    return type{::std::nullopt};
  }
}

template <typename Lh, some_optional Rh>
  requires ::fn::detail::_some_expected<Lh> && empty_copack<typename ::std::remove_cvref_t<Lh>::error_type>
           && ::std::is_void_v<typename ::std::remove_cvref_t<Lh>::value_type>
[[nodiscard]] constexpr auto operator&(Lh &&, Rh &&rh) //
    noexcept(::fn::detail::_nothrow_initializable<::std::remove_cvref_t<Rh>, Rh>) -> ::std::remove_cvref_t<Rh>
{
  return ::std::remove_cvref_t<Rh>{FWD(rh)};
}

template <some_optional Lh, typename Rh>
  requires ::fn::detail::_some_expected<Rh> && empty_copack<typename ::std::remove_cvref_t<Rh>::error_type>
           && ::std::is_void_v<typename ::std::remove_cvref_t<Rh>::value_type>
[[nodiscard]] constexpr auto operator&(Lh &&lh, Rh &&) //
    noexcept(::fn::detail::_nothrow_initializable<::std::remove_cvref_t<Lh>, Lh>) -> ::std::remove_cvref_t<Lh>
{
  return ::std::remove_cvref_t<Lh>{FWD(lh)};
}

// The disjunction of optionals: values sum into a `copack`, empty only when both are
//
// `a | b` holds the leftmost engaged operand's value, injected into the sum of the value types -
// a same-type pair stays bare. The unit errors vanish in the error product, so the result is
// empty exactly when both operands are. Both operands are fully constructed before the operator
// runs: a value-selection rule, not a lazy fallback.
// The disjunction: the value channel is the sum of the value types - a same-type pair stays bare -
// and the unit errors vanish in the product, so the result is empty exactly when both operands
// are. The leftmost engaged operand wins and injects by type.
template <some_optional Lh, some_optional Rh>
  requires ::std::is_same_v<typename ::std::remove_cvref_t<Lh>::value_type,
                            typename ::std::remove_cvref_t<Rh>::value_type>
[[nodiscard]] constexpr auto operator|(Lh &&lh, Rh &&rh) //
    noexcept(::fn::detail::_nothrow_initializable<::std::remove_cvref_t<Lh>, Lh>
             && ::fn::detail::_nothrow_initializable<::std::remove_cvref_t<Lh>, Rh>) -> ::std::remove_cvref_t<Lh>
{
  if (lh.has_value())
    return ::std::remove_cvref_t<Lh>{FWD(lh)};
  return ::std::remove_cvref_t<Lh>{FWD(rh)};
}

template <some_optional Lh, some_optional Rh>
  requires(not ::std::is_same_v<typename ::std::remove_cvref_t<Lh>::value_type,
                                typename ::std::remove_cvref_t<Rh>::value_type>)
[[nodiscard]] constexpr auto operator|(Lh &&lh, Rh &&rh) //
    noexcept(::fn::detail::_nothrow_disj_inject<::fn::detail::_dead_value<Lh>,
                                                optional<::fn::detail::_disjoined_t<Lh, Rh>>, Lh>::value
             && ::fn::detail::_nothrow_disj_inject<::fn::detail::_dead_value<Rh>,
                                                   optional<::fn::detail::_disjoined_t<Lh, Rh>>, Rh>::value)
{
  using type = optional<::fn::detail::_disjoined_t<Lh, Rh>>;
  if constexpr (not ::fn::detail::_dead_value<Lh>) {
    if (lh.has_value())
      return type{::std::in_place, FWD(lh).value()};
  }
  if constexpr (not ::fn::detail::_dead_value<Rh>) {
    if (rh.has_value())
      return type{::std::in_place, FWD(rh).value()};
  }
  return type{::std::nullopt};
}

} // namespace LIBFN_VERSION
} // namespace fn

namespace std {
// hash support, reusing pfn's [optional.hash] machinery (enabled iff hash<remove_const_t<T>>
// is enabled, hence never for reference types)
template <class T> struct hash<::fn::optional<T>> : ::pfn::detail::_optional_hash_base<::fn::optional<T>, T> {};

#if defined(__cpp_lib_format_ranges)
// range-format opt-out, mirroring pfn's [optional.syn] specialization
template <class T> constexpr range_format format_kind<::fn::optional<T>> = range_format::disabled;
#endif

// view opt-in, mirroring pfn's [optional.syn] specialization (nested-namespace block for
// MSVC, as in pfn/optional.hpp)
namespace ranges {
template <class T> constexpr bool enable_view<::fn::optional<T>> = true;
} // namespace ranges
} // namespace std

// ---------- BEGIN fn/detail/macro_end.hpp ----------
// Deliberately no include guard: see fn/detail/macro_begin.hpp.

#undef FWD // NOSONAR cpp:S959 paired with the define in macro_begin.hpp
#pragma pop_macro("FWD")

#undef DEDUCED_RETURN // NOSONAR cpp:S959 paired with the define in macro_begin.hpp
#pragma pop_macro("DEDUCED_RETURN")
// ---------- END fn/detail/macro_end.hpp ----------

// ---------- RESUME fn/optional.hpp ----------

#endif // INCLUDE_FN_OPTIONAL
// ---------- END fn/optional.hpp ----------

// ---------- RESUME fn/concepts.hpp ----------

// ---------- RESUME fn/concepts.hpp ----------

// ---------- BEGIN fn/detail/macro_begin.hpp ----------
// Deliberately no include guard: this header and fn/detail/macro_end.hpp bracket the section of a
// header that uses the macros below; push_macro/pop_macro make the bracketing safe under nesting
// and preserve any prior user definition.

#pragma push_macro("FWD")
#undef FWD // NOSONAR cpp:S959 saved by push_macro above

// This FWD macro is a functional equivalent to std::forward<decltype(v)>(v),
// but it saves compilation time (and typing) when used frequently.
#define FWD(...) static_cast<decltype(__VA_ARGS__) &&>(__VA_ARGS__)

#pragma push_macro("DEDUCED_RETURN")
#undef DEDUCED_RETURN // NOSONAR cpp:S959 saved by push_macro above

// Spell a function's deduced return type explicitly on MSVC only. MSVC mis-resolves a deduced
// (`auto`/`decltype(auto)`) return whose type derives from a body-local alias, leaking it as an
// opaque dependent type; an explicit trailing return type is the fix. Every other compiler keeps
// `decltype(auto)` — the natural spelling — which by construction deduces `decltype(EXPR)` on
// `return EXPR;`, so the two are the same type and this is a no-op off MSVC.
//
// Confining `decltype(EXPR)` to MSVC also keeps it off clang <= 20, which in C++23 substitutes a
// non-viable constrained overload's trailing return type BEFORE its requires-clause rejects it
// (fixed clang 21), so the explicit form would fail to compile instead of removing the non-viable
// function from the overload set.
#ifndef _MSC_VER
#define DEDUCED_RETURN(...) decltype(auto)
#else
#define DEDUCED_RETURN(...) decltype(__VA_ARGS__)
#endif
// ---------- END fn/detail/macro_begin.hpp ----------

// ---------- RESUME fn/concepts.hpp ----------

namespace fn {
inline namespace LIBFN_VERSION {

namespace detail {
// A verb that returns a fresh monad BY VALUE relocates what the source carries into it, in the value
// category the source is piped in - an lvalue is copied, an rvalue moved. So the question is not
// whether the carried type is movable: `is_move_constructible_v` would accept a move-only value
// piped as an lvalue, which the body then cannot copy. It is whether the result can be built from
// what the body actually reaches for, which is what these ask - and what the verbs' noexcept specs
// weigh, one asking "can it", the other "can it throw".
template <typename V>
concept _relocatable_value // `type{::std::in_place, FWD(v).value()}`
    = ::std::is_constructible_v<::std::remove_cvref_t<V>, ::std::in_place_t, decltype(::std::declval<V>().value())>;

template <typename V>
concept _relocatable_error // `type{::fn::unexpect, FWD(v).error()}`
    = ::std::is_constructible_v<::std::remove_cvref_t<V>, ::fn::unexpect_t, decltype(::std::declval<V>().error())>;

template <typename V>
concept _relocatable // `return FWD(v);` - the whole monad, hence both sides
    = ::std::is_constructible_v<::std::remove_cvref_t<V>, V>;
} // namespace detail

/**
 * @brief Checks if two carriers are of the same monadic family, with compatible error sides
 *
 * What `and_then` and the other success-path operations hold a callback's result to: the value
 * side may change freely, the family may not. For `expected` the error sides must also agree -
 * identical plain types, any two graded (copack) sides, or a plain side meeting its own singular
 * lift `copack<E>`, either way round. Any two `optional`s, any two `choice`s and any two `just`s
 * are the same kind.
 *
 * @tparam T Carrier type, possibly cv-ref qualified
 * @tparam U Carrier type, possibly cv-ref qualified
 */
template <typename T, typename U>
concept same_kind
    = (some_expected<T> && some_expected<U>
       && ::std::same_as<typename ::std::remove_cvref_t<T>::error_type, typename ::std::remove_cvref_t<U>::error_type>)
      || (some_expected<T> && some_copack<typename ::std::remove_cvref_t<T>::error_type> //
          && some_expected<U> && some_copack<typename ::std::remove_cvref_t<U>::error_type>)
      || (some_expected<T>
          && (not some_copack<typename ::std::remove_cvref_t<T>::error_type>) // the singular lift
          &&some_expected<U>
          && ::std::is_same_v<typename ::std::remove_cvref_t<U>::error_type,
                              copack<typename ::std::remove_cvref_t<T>::error_type>>)
      || (some_expected<U>
          && (not some_copack<typename ::std::remove_cvref_t<U>::error_type>) // ... and its mirror
          &&some_expected<T>
          && ::std::is_same_v<typename ::std::remove_cvref_t<T>::error_type,
                              copack<typename ::std::remove_cvref_t<U>::error_type>>)
      || (some_optional<T> && some_optional<U>) //
      || (some_choice<T> && some_choice<U>)     //
      || (some_just<T> && some_just<U>);

/**
 * @brief The mirror of `same_kind`: the value side is pinned and the error side may vary
 *
 * What the error-side operations hold a callback's result to. Value sides agree when identical,
 * when both are graded (copack), or - on `expected` - when a plain non-void side meets its own
 * singular lift `copack<T>`, either way round. Any two `choice`s qualify; never two carriers of
 * different families.
 *
 * @tparam T Carrier type, possibly cv-ref qualified
 * @tparam U Carrier type, possibly cv-ref qualified
 */
template <typename T, typename U>
concept same_value_kind
    = (some_expected<T> && some_expected<U>
       && ::std::same_as<typename ::std::remove_cvref_t<T>::value_type, typename ::std::remove_cvref_t<U>::value_type>)
      || (some_expected<T> && some_copack<typename ::std::remove_cvref_t<T>::value_type> //
          && some_expected<U> && some_copack<typename ::std::remove_cvref_t<U>::value_type>)
      || (some_optional<T> && some_optional<U>
          && ::std::same_as<typename ::std::remove_cvref_t<U>::value_type,
                            typename ::std::remove_cvref_t<T>::value_type>)              //
      || (some_optional<T> && some_copack<typename ::std::remove_cvref_t<T>::value_type> //
          && some_optional<U> && some_copack<typename ::std::remove_cvref_t<U>::value_type>)
      || (some_expected<T>
          && (not ::std::is_void_v<typename ::std::remove_cvref_t<T>::value_type>) // the singular lift
          &&(not some_copack<typename ::std::remove_cvref_t<T>::value_type>)
          && some_expected<U>
          && ::std::is_same_v<typename ::std::remove_cvref_t<U>::value_type,
                              copack<typename ::std::remove_cvref_t<T>::value_type>>)
      || (some_expected<U>
          && (not ::std::is_void_v<typename ::std::remove_cvref_t<U>::value_type>) // ... and its mirror
          &&(not some_copack<typename ::std::remove_cvref_t<U>::value_type>)
          && some_expected<T>
          && ::std::is_same_v<typename ::std::remove_cvref_t<T>::value_type,
                              copack<typename ::std::remove_cvref_t<U>::value_type>>)
      || (some_choice<T> && some_choice<U>);

/**
 * @brief Checks if two carriers agree on family, value side and error side alike
 *
 * The conjunction of `same_kind` and `same_value_kind`.
 *
 * @tparam T Carrier type, possibly cv-ref qualified
 * @tparam U Carrier type, possibly cv-ref qualified
 */
template <typename T, typename U>
concept same_monadic_type_as = same_kind<T, U> && same_value_kind<T, U>;

/**
 * @brief Checks if `fn::unexpected` over the decayed type can be built from the value by a cast
 *
 * A `void` answers false - `unexpected<void>` is ill-formed to instantiate, and the concept
 * answers instead. An immovable value answers false as well: there is nothing to move or copy
 * into the carrier.
 *
 * @tparam T Type of the value, possibly cv-ref qualified
 */
// The void conjunct is load-bearing: `unexpected<void>` is ill-formed by a class-body mandate,
// which fires during instantiation - outside any immediate context - so without it the question
// hard-errors instead of answering false. `remove_cvref_t` folds cv-qualified void back to plain
// `void`, so the guard must cover every cv-flavour - `is_void_v`, not a `same_as` test.
template <class T>
concept convertible_to_unexpected = (not ::std::is_void_v<T>) && requires {
  static_cast<::fn::unexpected<::std::remove_cvref_t<T>>>(::std::declval<T>());
};

/**
 * @brief Checks if an `expected` over the decayed type can be built from the value by a cast
 *
 * Unlike the other `convertible_to_*` concepts here, `void` is admitted outright by its own arm:
 * `expected<void, E>` is a legitimate carrier with no value to convert.
 *
 * @tparam T Type of the value, possibly cv-ref qualified
 * @tparam E Error type of the target `expected`
 */
template <class T, typename E>
concept convertible_to_expected
    = (not ::std::is_void_v<T> && requires { static_cast<expected<::std::remove_cvref_t<T>, E>>(::std::declval<T>()); })
      || (::std::is_void_v<T>);

/**
 * @brief Checks if an `optional` over the decayed type can be built from the value by a cast
 *
 * A `void` answers false - `optional<void>` is ill-formed to instantiate, and the concept answers
 * instead.
 *
 * @tparam T Type of the value, possibly cv-ref qualified
 */
// The same load-bearing void conjunct as `convertible_to_unexpected`'s: `optional<void>` and
// `choice<void>` (below) are likewise ill-formed to instantiate, by a class-body mandate.
template <class T>
concept convertible_to_optional
    = (not ::std::is_void_v<T>) && requires { static_cast<optional<::std::remove_cvref_t<T>>>(::std::declval<T>()); };

/**
 * @brief Checks if a `choice` over the decayed type can be built from the value by a cast
 *
 * A `void` answers false - `choice<void>` is ill-formed to instantiate, and the concept answers
 * instead.
 *
 * @tparam T Type of the value, possibly cv-ref qualified
 */
template <class T>
concept convertible_to_choice
    = (not ::std::is_void_v<T>) && requires { static_cast<choice<::std::remove_cvref_t<T>>>(::std::declval<T>()); };

/**
 * @brief Checks if a carrier's error side is uninhabited - it can never hold an error
 *
 * The identity `expected`, and only it: `choice` and `just` have no error channel to empty, so they
 * answer false here while `some_identity` below accepts all three.
 *
 * @tparam T Type to check, possibly cv-ref qualified
 */
template <typename T>
concept some_empty_error = some_expected<T> && empty_copack<typename ::std::remove_cvref_t<T>::error_type>;

/**
 * @brief Checks if a carrier's value side is uninhabited - it can never hold a value
 *
 * An `optional<copack<>>`, which is never engaged, or an `expected<copack<>, E>`, which always holds
 * its error: every value-side operation over one is the identity, and its callback is neither
 * invoked nor instantiated. `optional` belongs here where it cannot belong to the mirror above - its
 * empty state is a state that is, not a channel that can never engage.
 *
 * @tparam T Type to check, possibly cv-ref qualified
 */
template <typename T>
concept some_empty_value
    = (some_expected<T> || some_optional<T>) && empty_copack<typename ::std::remove_cvref_t<T>::value_type>;

/**
 * @brief Checks if a type is an identity carrier - a monad which never short-circuits
 *
 * The equivalence class of the family's unit: `choice` (no error channel at all), `just` (the
 * canonical minimal carrier) and an `expected` whose error is the empty copack (a channel that
 * can never engage). Binding across the cluster is lossless exactly because the channels a
 * carrier switch drops are uninhabited.
 *
 * @tparam T Type to check, possibly cv-ref qualified
 */
template <typename T>
concept some_identity = some_choice<T> || some_just<T> || some_empty_error<T>;

/**
 * @brief Checks if the type casts to `bool` - what `filter` holds its predicate's result to
 *
 * An explicit `operator bool` suffices: the concept casts, it does not ask for an implicit
 * conversion.
 *
 * @tparam T Type to check, possibly cv-ref qualified
 */
template <class T>
concept convertible_to_bool = requires { static_cast<bool>(::std::declval<T>()); };

} // namespace LIBFN_VERSION
} // namespace fn

// ---------- BEGIN fn/detail/macro_end.hpp ----------
// Deliberately no include guard: see fn/detail/macro_begin.hpp.

#undef FWD // NOSONAR cpp:S959 paired with the define in macro_begin.hpp
#pragma pop_macro("FWD")

#undef DEDUCED_RETURN // NOSONAR cpp:S959 paired with the define in macro_begin.hpp
#pragma pop_macro("DEDUCED_RETURN")
// ---------- END fn/detail/macro_end.hpp ----------

// ---------- RESUME fn/concepts.hpp ----------

#endif // INCLUDE_FN_CONCEPTS
// ---------- END fn/concepts.hpp ----------

// ---------- RESUME fn/and_then.hpp ----------

// ---------- RESUME fn/and_then.hpp ----------

// ---------- RESUME fn/and_then.hpp ----------

// ---------- BEGIN fn/functor.hpp ----------
#ifndef INCLUDE_FN_FUNCTOR
#define INCLUDE_FN_FUNCTOR

// ---------- RESUME fn/functor.hpp ----------

// ---------- RESUME fn/functor.hpp ----------

// ---------- RESUME fn/functor.hpp ----------

// ---------- BEGIN fn/utility.hpp ----------
#ifndef INCLUDE_FN_UTILITY
#define INCLUDE_FN_UTILITY

// ---------- RESUME fn/utility.hpp ----------

// ---------- RESUME fn/utility.hpp ----------

// ---------- BEGIN fn/detail/macro_begin.hpp ----------
// Deliberately no include guard: this header and fn/detail/macro_end.hpp bracket the section of a
// header that uses the macros below; push_macro/pop_macro make the bracketing safe under nesting
// and preserve any prior user definition.

#pragma push_macro("FWD")
#undef FWD // NOSONAR cpp:S959 saved by push_macro above

// This FWD macro is a functional equivalent to std::forward<decltype(v)>(v),
// but it saves compilation time (and typing) when used frequently.
#define FWD(...) static_cast<decltype(__VA_ARGS__) &&>(__VA_ARGS__)

#pragma push_macro("DEDUCED_RETURN")
#undef DEDUCED_RETURN // NOSONAR cpp:S959 saved by push_macro above

// Spell a function's deduced return type explicitly on MSVC only. MSVC mis-resolves a deduced
// (`auto`/`decltype(auto)`) return whose type derives from a body-local alias, leaking it as an
// opaque dependent type; an explicit trailing return type is the fix. Every other compiler keeps
// `decltype(auto)` — the natural spelling — which by construction deduces `decltype(EXPR)` on
// `return EXPR;`, so the two are the same type and this is a no-op off MSVC.
//
// Confining `decltype(EXPR)` to MSVC also keeps it off clang <= 20, which in C++23 substitutes a
// non-viable constrained overload's trailing return type BEFORE its requires-clause rejects it
// (fixed clang 21), so the explicit form would fail to compile instead of removing the non-viable
// function from the overload set.
#ifndef _MSC_VER
#define DEDUCED_RETURN(...) decltype(auto)
#else
#define DEDUCED_RETURN(...) decltype(__VA_ARGS__)
#endif
// ---------- END fn/detail/macro_begin.hpp ----------

// ---------- RESUME fn/utility.hpp ----------

namespace fn {
inline namespace LIBFN_VERSION {
/**
 * @brief The type an argument of type `T` is stored as: a non-empty lvalue stays an lvalue
 *        reference, everything else becomes a value
 *
 * What `fn::functor` stores a pipeline operation's arguments as: an rvalue is kept alive by value,
 * while a stateless (empty) callable is stored by value even when passed as an lvalue - it has no
 * state whose identity would matter. A non-empty lvalue stays a reference, which is what lets an
 * immovable callable participate in a pipeline.
 *
 * @tparam T Type of the argument, cv-ref qualified as deduced
 */
template <typename T> using as_value_t = decltype(detail::_as_value<T>);

/**
 * @brief Forwards `v` with the constness and value category of `T` applied
 *
 * @note Unlike `apply_const_lvalue_t`, this is not exact: prvalue parameters are
 * returned as xvalue. This is meant to disable copying of the return value.
 *
 * @tparam T Type whose constness and value category are applied
 * @param v Value to forward
 * @return `v`, cast to `apply_const_lvalue_t<T, decltype(v)>`
 */
template <typename T> [[nodiscard]] constexpr auto apply_const_lvalue(auto &&v) noexcept -> decltype(auto)
{
  return static_cast<apply_const_lvalue_t<T, decltype(v)>>(v);
}

/**
 * @brief Fuses callables into a single overload set
 *
 * The routing helper for multidispatch: `apply` over a `copack` or `choice` selects the arm by
 * ordinary overload resolution, and a missing arm is a compile error. An unconstrained `[](auto)`
 * arm serves every alternative, which defeats that exhaustiveness check; where one arm should
 * serve several alternatives, constrain it with a concept instead.
 *
 * @tparam Ts Callables whose `operator()` overloads combine
 */
template <typename... Ts> struct overload final : Ts... {
  using Ts::operator()...;
};
template <typename... Ts> overload(Ts const &...) -> overload<Ts...>;

/**
 * @brief Lifts arguments into a `T`, preferring braced construction
 *
 * Constructs `T{args...}` where that is available and `T(args...)` where it is not, so a type
 * whose braced form differs from its parenthesised one is reached the way its author meant.
 *
 * @tparam T Type to construct
 * @param args Arguments to construct the `T` from
 * @return The constructed value
 */
template <typename T, typename... Args>
[[nodiscard]] constexpr auto make(Args &&...args) -> T
  requires requires(Args &&...args) { T{FWD(args)...}; }
{
  return T{FWD(args)...};
}

template <typename T, typename... Args>
[[nodiscard]] constexpr auto make(Args &&...args) -> T
  requires requires(Args &&...args) { T(FWD(args)...); } && (not requires(Args &&...args) { T{FWD(args)...}; })
{
  return T(FWD(args)...);
}

} // namespace LIBFN_VERSION
} // namespace fn

// ---------- BEGIN fn/detail/macro_end.hpp ----------
// Deliberately no include guard: see fn/detail/macro_begin.hpp.

#undef FWD // NOSONAR cpp:S959 paired with the define in macro_begin.hpp
#pragma pop_macro("FWD")

#undef DEDUCED_RETURN // NOSONAR cpp:S959 paired with the define in macro_begin.hpp
#pragma pop_macro("DEDUCED_RETURN")
// ---------- END fn/detail/macro_end.hpp ----------

// ---------- RESUME fn/utility.hpp ----------

#endif // INCLUDE_FN_UTILITY
// ---------- END fn/utility.hpp ----------

// ---------- RESUME fn/functor.hpp ----------

// ---------- RESUME fn/functor.hpp ----------

// ---------- BEGIN fn/detail/macro_begin.hpp ----------
// Deliberately no include guard: this header and fn/detail/macro_end.hpp bracket the section of a
// header that uses the macros below; push_macro/pop_macro make the bracketing safe under nesting
// and preserve any prior user definition.

#pragma push_macro("FWD")
#undef FWD // NOSONAR cpp:S959 saved by push_macro above

// This FWD macro is a functional equivalent to std::forward<decltype(v)>(v),
// but it saves compilation time (and typing) when used frequently.
#define FWD(...) static_cast<decltype(__VA_ARGS__) &&>(__VA_ARGS__)

#pragma push_macro("DEDUCED_RETURN")
#undef DEDUCED_RETURN // NOSONAR cpp:S959 saved by push_macro above

// Spell a function's deduced return type explicitly on MSVC only. MSVC mis-resolves a deduced
// (`auto`/`decltype(auto)`) return whose type derives from a body-local alias, leaking it as an
// opaque dependent type; an explicit trailing return type is the fix. Every other compiler keeps
// `decltype(auto)` — the natural spelling — which by construction deduces `decltype(EXPR)` on
// `return EXPR;`, so the two are the same type and this is a no-op off MSVC.
//
// Confining `decltype(EXPR)` to MSVC also keeps it off clang <= 20, which in C++23 substitutes a
// non-viable constrained overload's trailing return type BEFORE its requires-clause rejects it
// (fixed clang 21), so the explicit form would fail to compile instead of removing the non-viable
// function from the overload set.
#ifndef _MSC_VER
#define DEDUCED_RETURN(...) decltype(auto)
#else
#define DEDUCED_RETURN(...) decltype(__VA_ARGS__)
#endif
// ---------- END fn/detail/macro_begin.hpp ----------

// ---------- RESUME fn/functor.hpp ----------

namespace fn {
inline namespace LIBFN_VERSION {
/**
 * @brief A pipeline step waiting for a carrier: the verb and its arguments as one value
 *
 * What a verb call such as `fn::and_then(f)` returns - a description of the operation, executed
 * only when a carrier is piped into it with `operator|`. The arguments are stored as `as_value_t`
 * prescribes: rvalues by value, non-empty lvalues - an immovable callable among them - by
 * reference.
 *
 * @tparam Functor The verb, such as `fn::and_then_t`
 * @tparam Args The verb's arguments as deduced, typically the callback
 */
template <typename Functor, typename... Args> struct functor final {
  using functor_type = Functor;
  using functor_apply = typename functor_type::apply;
  static constexpr unsigned size = sizeof...(Args);
  using data_t = pack<as_value_t<Args>...>;
  data_t data;

  static_assert(::std::is_empty_v<functor_type> && ::std::is_empty_v<functor_apply>
                && ::std::is_default_constructible_v<functor_type> && ::std::is_default_constructible_v<functor_apply>);

  /**
   * @brief Feeds a carrier into the pipeline step
   *
   * @param v The carrier, in any value category
   * @param self The step - this `functor`
   * @return Whatever the verb's `apply` returns for this carrier and the stored arguments
   */
  // The pipeline propagates what the operation itself promises: the verb's `apply` knows, and
  // `_swap_invoke` carries that answer up. Promising `noexcept` here regardless would turn an
  // exception the monad's own member would propagate into a call to std::terminate.
  [[nodiscard]] constexpr friend auto operator|(some_monadic_type auto &&v, auto &&self) //
      noexcept(noexcept(data_t::_swap_invoke(FWD(self).data, functor_apply{}, FWD(v)))) -> decltype(auto)
    requires ::std::same_as<::std::remove_cvref_t<decltype(self)>, functor>
             && monadic_invocable<functor_type, decltype(v), Args...>
  {
    return data_t::_swap_invoke(FWD(self).data, functor_apply{}, FWD(v));
  }
};

} // namespace LIBFN_VERSION
} // namespace fn

// ---------- BEGIN fn/detail/macro_end.hpp ----------
// Deliberately no include guard: see fn/detail/macro_begin.hpp.

#undef FWD // NOSONAR cpp:S959 paired with the define in macro_begin.hpp
#pragma pop_macro("FWD")

#undef DEDUCED_RETURN // NOSONAR cpp:S959 paired with the define in macro_begin.hpp
#pragma pop_macro("DEDUCED_RETURN")
// ---------- END fn/detail/macro_end.hpp ----------

// ---------- RESUME fn/functor.hpp ----------

#endif // INCLUDE_FN_FUNCTOR
// ---------- END fn/functor.hpp ----------

// ---------- RESUME fn/and_then.hpp ----------

// ---------- RESUME fn/and_then.hpp ----------

// ---------- RESUME fn/and_then.hpp ----------

// ---------- BEGIN fn/detail/macro_begin.hpp ----------
// Deliberately no include guard: this header and fn/detail/macro_end.hpp bracket the section of a
// header that uses the macros below; push_macro/pop_macro make the bracketing safe under nesting
// and preserve any prior user definition.

#pragma push_macro("FWD")
#undef FWD // NOSONAR cpp:S959 saved by push_macro above

// This FWD macro is a functional equivalent to std::forward<decltype(v)>(v),
// but it saves compilation time (and typing) when used frequently.
#define FWD(...) static_cast<decltype(__VA_ARGS__) &&>(__VA_ARGS__)

#pragma push_macro("DEDUCED_RETURN")
#undef DEDUCED_RETURN // NOSONAR cpp:S959 saved by push_macro above

// Spell a function's deduced return type explicitly on MSVC only. MSVC mis-resolves a deduced
// (`auto`/`decltype(auto)`) return whose type derives from a body-local alias, leaking it as an
// opaque dependent type; an explicit trailing return type is the fix. Every other compiler keeps
// `decltype(auto)` — the natural spelling — which by construction deduces `decltype(EXPR)` on
// `return EXPR;`, so the two are the same type and this is a no-op off MSVC.
//
// Confining `decltype(EXPR)` to MSVC also keeps it off clang <= 20, which in C++23 substitutes a
// non-viable constrained overload's trailing return type BEFORE its requires-clause rejects it
// (fixed clang 21), so the explicit form would fail to compile instead of removing the non-viable
// function from the overload set.
#ifndef _MSC_VER
#define DEDUCED_RETURN(...) decltype(auto)
#else
#define DEDUCED_RETURN(...) decltype(__VA_ARGS__)
#endif
// ---------- END fn/detail/macro_begin.hpp ----------

// ---------- RESUME fn/and_then.hpp ----------

namespace fn {
inline namespace LIBFN_VERSION {

namespace detail {
// the first join that announces a `type` wins; neither is a hard error to ask
template <typename A, typename B> struct _either_join : B {};
template <typename A, typename B>
  requires requires { typename A::type; }
struct _either_join<A, B> : A {};

template <typename Fn, typename Cp>
constexpr inline bool _cluster_join_forms
    = requires { typename _copack_apply_result<_joining_cluster_tag<::fn::choice>, Fn, Cp>::type; };

// The engine's result over a bound payload, computed assert-free: a copack payload goes through
// the cluster trait - all-choice branch results answer the superset choice, convergent ones the
// select trait's answer - and a branch set the cluster join does not own may still join as
// optionals (the #376 bridge); every other set answers none at all, so asking about any divergent
// callback answers instead of tripping select's convergence assert; a single value goes through
// _apply_result as always.
template <typename Fn, typename... V> struct _and_then_result : _apply_result<Fn, V...> {};
template <typename Fn, typename V>
  requires _some_copack<::std::remove_cvref_t<V>>
struct _and_then_result<Fn, V>
    : _either_join<_typelist_joining_cluster<::fn::choice, Fn, V, ::std::remove_cvref_t<V>>,
                   _typelist_joining_optional<::fn::optional, Fn, V, ::std::remove_cvref_t<V>>> {};

// the copack arm's promise, split on the same choice of tag its body makes
template <typename Fn, typename Cp> struct _nothrow_and_then_join {
  static constexpr bool value = [] {
    if constexpr (_cluster_join_forms<Fn, Cp>)
      return _is_nothrow_rts_applicable<typename _copack_apply_result<_joining_cluster_tag<::fn::choice>, Fn, Cp>::type,
                                        Fn, Cp>;
    else
      return _is_nothrow_rts_applicable<
          typename _copack_apply_result<_joining_optional_tag<::fn::optional>, Fn, Cp>::type, Fn, Cp>;
  }();
};
} // namespace detail

/**
 * @brief Checks if the monadic type can be used with the `and_then` operation
 *
 * @tparam Fn The function to execute on the value
 * @tparam V The monadic type
 */
template <typename Fn, typename V>
concept applicable_and_then //
    = (some_expected_non_void<V> && requires(V &&v) {
        typename detail::_and_then_dispatch<typename ::std::remove_cvref_t<V>::error_type, Fn,
                                            decltype(FWD(v).value())>::type;
        requires same_kind<V, typename detail::_and_then_dispatch<typename ::std::remove_cvref_t<V>::error_type, Fn,
                                                                  decltype(FWD(v).value())>::type>;
      }) || (some_expected_non_void<V> //
         && some_copack<typename ::std::remove_cvref_t<V>::error_type> && requires(V &&v) {
        typename detail::_and_then_dispatch<typename ::std::remove_cvref_t<V>::error_type, Fn,
                                            decltype(FWD(v).value())>::type;
        requires some_expected<typename detail::_and_then_dispatch<typename ::std::remove_cvref_t<V>::error_type, Fn,
                                                                   decltype(FWD(v).value())>::type>;
      }) || (some_expected_void<V> && requires(Fn &&fn) {
        {
          ::fn::apply(FWD(fn))
        } -> same_kind<V>;
      }) || (some_expected_void<V> //
         && some_copack<typename ::std::remove_cvref_t<V>::error_type> && requires(Fn &&fn) {
        {
          ::fn::apply(FWD(fn))
        } -> some_expected;
      }) || (some_optional<V> && requires(V &&v) {
        typename detail::_optional_and_then_dispatch<Fn, decltype(FWD(v).value())>::type;
        requires same_kind<V, typename detail::_optional_and_then_dispatch<Fn, decltype(FWD(v).value())>::type>;
      }) || (some_choice<V> && requires(V &&v) {
        // asked of the assert-free trait, never the member: a divergent branch set must answer
        // false here, where naming the member would trip select's convergence assert
        typename detail::_and_then_result<Fn, decltype(FWD(v).value())>::type;
        requires same_kind<V, typename detail::_and_then_result<Fn, decltype(FWD(v).value())>::type>;
      }) || (some_just<V> && requires(Fn &&fn, V &&v) {
        {
          FWD(v).and_then(FWD(fn))
        } -> same_kind<V>;
      });

/**
 * @brief Checks if the identity carrier can be used with `and_then` binding across the cluster's
 *        carrier kinds
 *
 * The callback may return any identity carrier and the bind follows the function; results of the
 * input's own kind are left to `applicable_and_then` and the carrier's member. Over a copack
 * payload the branches either all return choices - joined into the superset - or converge on one
 * carrier type.
 *
 * @tparam Fn The function to execute on the value
 * @tparam V The identity carrier
 */
template <typename Fn, typename V>
concept applicable_and_then_across //
    = some_identity<V>
      && ((some_choice<V> && (not applicable_and_then<Fn, V>) && requires(V &&v) {
            typename detail::_and_then_result<Fn, decltype(FWD(v).value())>::type;
            requires some_identity<typename detail::_and_then_result<Fn, decltype(FWD(v).value())>::type>
                         || some_optional<typename detail::_and_then_result<Fn, decltype(FWD(v).value())>::type>
                         || some_expected<typename detail::_and_then_result<Fn, decltype(FWD(v).value())>::type>;
          }) || (some_just<V> && (not applicable_and_then<Fn, V>) && (not ::std::is_void_v<typename ::std::remove_cvref_t<V>::value_type>) && requires(V &&v) {
            typename detail::_and_then_result<Fn, decltype(FWD(v).value())>::type;
            requires some_identity<typename detail::_and_then_result<Fn, decltype(FWD(v).value())>::type>
                         || some_optional<typename detail::_and_then_result<Fn, decltype(FWD(v).value())>::type>
                         || some_expected<typename detail::_and_then_result<Fn, decltype(FWD(v).value())>::type>;
          }) || (some_expected_non_void<V> && requires(V &&v) {
            typename detail::_and_then_result<Fn, decltype(FWD(v).value())>::type;
            requires some_identity<typename detail::_and_then_result<Fn, decltype(FWD(v).value())>::type>
                         || some_optional<typename detail::_and_then_result<Fn, decltype(FWD(v).value())>::type>;
            requires not some_expected<typename detail::_and_then_result<Fn, decltype(FWD(v).value())>::type>;
          }) || (some_expected_void<V> && requires {
            typename detail::_and_then_result<Fn>::type;
            requires some_identity<typename detail::_and_then_result<Fn>::type>
                         || some_optional<typename detail::_and_then_result<Fn>::type>;
            // expected results stay on the member: the void identity expected keeps its graded
            // world (a copack<> grade acquiring the callback's error), never the bare carrier
            requires not some_expected<typename detail::_and_then_result<Fn>::type>;
          }) || (some_just<V> && ::std::is_void_v<typename ::std::remove_cvref_t<V>::value_type> && (not applicable_and_then<Fn, V>) && requires {
            typename detail::_and_then_result<Fn>::type;
            requires some_identity<typename detail::_and_then_result<Fn>::type>
                         || some_optional<typename detail::_and_then_result<Fn>::type>
                         || some_expected<typename detail::_and_then_result<Fn>::type>;
          }));

/**
 * @brief Execute a function on the value of the monadic type if the value is present
 *
 * Use through the `fn::and_then` nielbloid.
 */
constexpr inline struct and_then_t final {
  /**
   * @brief Execute a function on the value of the monadic type if the value is present
   * @param fn The function to execute on the value
   * @return A functor that will execute the function on the value
   */
  [[nodiscard]] constexpr auto operator()(auto &&fn) const
      noexcept(noexcept(functor<and_then_t, decltype(fn)>{FWD(fn)})) -> functor<and_then_t, decltype(fn)> //
  {
    return {FWD(fn)};
  }

  struct apply;
} and_then = {}; ///< Binds through a callable returning a carrier: `x | and_then(f)`

struct and_then_t::apply final {
  /**
   * @brief Binds through the carrier's own `and_then` member
   *
   * @param v The monad
   * @param fn The function to apply
   * @return A carrier of the same kind, possibly with a widened error grade
   */
  template <some_monadic_type V, typename Fn>
  [[nodiscard]] constexpr auto operator()(V &&v, Fn &&fn) const //
      noexcept(noexcept(FWD(v).and_then(FWD(fn))))              //
      -> same_kind<V &&> auto
    requires(not(some_expected<V> && some_identity<V>)) && applicable_and_then<Fn &&, V &&>
  {
    return FWD(v).and_then(FWD(fn));
  }

  // An identity expected keeps its member semantics for expected results - the same-kind and
  // error-widening paths above - but must not evaluate applicable_and_then's optional/choice
  // disjuncts through the exclusion in the arm above, hence its own arm.
  template <some_monadic_type V, typename Fn>
  [[nodiscard]] constexpr auto operator()(V &&v, Fn &&fn) const //
      noexcept(noexcept(FWD(v).and_then(FWD(fn))))              //
      -> same_kind<V &&> auto
    requires some_expected<V> && some_identity<V> && applicable_and_then<Fn &&, V &&>
  {
    return FWD(v).and_then(FWD(fn));
  }

  // An uninhabited value side leaves no value to bind - delegate to the member, which is the
  // identity there and neither invokes nor instantiates the callback, as in transform.
  template <some_monadic_type V, typename Fn>
  [[nodiscard]] constexpr auto operator()(V &&v, Fn &&fn) const //
      noexcept(noexcept(FWD(v).and_then(FWD(fn))))              //
      -> same_kind<V &&> auto
    requires some_empty_value<V>
  {
    return FWD(v).and_then(FWD(fn));
  }

  // The cluster arms: an identity input binds across the carrier kinds, and the bind follows the
  // function. Engine-direct - the members are each carrier's own endo-bind, so the cluster cannot
  // ride delegation, and the verb layer is the licensed cross-carrier place. Dropping the input's
  // channels forgets nothing: they are uninhabited, which is what admits the input here at all.
  template <some_monadic_type V, typename Fn>
  [[nodiscard]] constexpr auto operator()(V &&v, Fn &&fn) const                                     //
      noexcept(detail::_nothrow_and_then_join<Fn &&, decltype(::std::declval<V>().value())>::value) //
      -> some_monadic_type auto
    requires applicable_and_then_across<Fn &&, V &&>
             && (not ::std::is_void_v<typename ::std::remove_cvref_t<V>::value_type>)
             && some_copack<::std::remove_cvref_t<decltype(::std::declval<V>().value())>>
  {
    if constexpr (detail::_cluster_join_forms<Fn &&, decltype(FWD(v).value())>)
      return detail::_tagged_join_apply<detail::_joining_cluster_tag<choice>>(FWD(v).value(), FWD(fn));
    else
      return detail::_tagged_join_apply<detail::_joining_optional_tag<::fn::optional>>(FWD(v).value(), FWD(fn));
  }

  template <some_monadic_type V, typename Fn>
  [[nodiscard]] constexpr auto operator()(V &&v, Fn &&fn) const //
      noexcept(noexcept(::fn::apply(FWD(fn), FWD(v).value())))  //
      -> some_monadic_type auto
    requires applicable_and_then_across<Fn &&, V &&>
             && (not ::std::is_void_v<typename ::std::remove_cvref_t<V>::value_type>)
             && (not some_copack<::std::remove_cvref_t<decltype(::std::declval<V>().value())>>)
  {
    return ::fn::apply(FWD(fn), FWD(v).value());
  }

  template <some_monadic_type V, typename Fn>
  [[nodiscard]] constexpr auto operator()(V &&, Fn &&fn) const //
      noexcept(noexcept(::fn::apply(FWD(fn))))                 //
      -> some_monadic_type auto
    requires applicable_and_then_across<Fn &&, V &&> && ::std::is_void_v<typename ::std::remove_cvref_t<V>::value_type>
  {
    return ::fn::apply(FWD(fn));
  }
};

} // namespace LIBFN_VERSION
} // namespace fn

// ---------- BEGIN fn/detail/macro_end.hpp ----------
// Deliberately no include guard: see fn/detail/macro_begin.hpp.

#undef FWD // NOSONAR cpp:S959 paired with the define in macro_begin.hpp
#pragma pop_macro("FWD")

#undef DEDUCED_RETURN // NOSONAR cpp:S959 paired with the define in macro_begin.hpp
#pragma pop_macro("DEDUCED_RETURN")
// ---------- END fn/detail/macro_end.hpp ----------

// ---------- RESUME fn/and_then.hpp ----------

#endif // INCLUDE_FN_AND_THEN
// ---------- END fn/and_then.hpp ----------

// ---------- BEGIN fn/discard.hpp ----------
#ifndef INCLUDE_FN_DISCARD
#define INCLUDE_FN_DISCARD

// ---------- RESUME fn/discard.hpp ----------

// ---------- RESUME fn/discard.hpp ----------

// ---------- RESUME fn/discard.hpp ----------

namespace fn {
inline namespace LIBFN_VERSION {
/**
 * @brief Discard the value explicitly
 *
 * This is useful when only side-effects are desired and the final value is not needed.
 *
 * Use through the `fn::discard` nielbloid.
 */
constexpr inline struct discard_t final {
  /**
   * @brief Unconditionally discards the value
   * @return A functor that explicitly discards the value
   */
  [[nodiscard]] constexpr auto operator()() const noexcept -> functor<discard_t> { return {}; }

  struct apply final {
    constexpr auto operator()(some_monadic_type auto &&) const noexcept -> void {} // NOSONAR cpp:S1186 discards
  };
} discard = {}; ///< Drops the carrier's content: `x | discard`

} // namespace LIBFN_VERSION
} // namespace fn

#endif // INCLUDE_FN_DISCARD
// ---------- END fn/discard.hpp ----------

// ---------- BEGIN fn/fail.hpp ----------
#ifndef INCLUDE_FN_FAIL
#define INCLUDE_FN_FAIL

// ---------- RESUME fn/fail.hpp ----------

// ---------- RESUME fn/fail.hpp ----------

// ---------- RESUME fn/fail.hpp ----------

// ---------- RESUME fn/fail.hpp ----------

// ---------- BEGIN fn/detail/macro_begin.hpp ----------
// Deliberately no include guard: this header and fn/detail/macro_end.hpp bracket the section of a
// header that uses the macros below; push_macro/pop_macro make the bracketing safe under nesting
// and preserve any prior user definition.

#pragma push_macro("FWD")
#undef FWD // NOSONAR cpp:S959 saved by push_macro above

// This FWD macro is a functional equivalent to std::forward<decltype(v)>(v),
// but it saves compilation time (and typing) when used frequently.
#define FWD(...) static_cast<decltype(__VA_ARGS__) &&>(__VA_ARGS__)

#pragma push_macro("DEDUCED_RETURN")
#undef DEDUCED_RETURN // NOSONAR cpp:S959 saved by push_macro above

// Spell a function's deduced return type explicitly on MSVC only. MSVC mis-resolves a deduced
// (`auto`/`decltype(auto)`) return whose type derives from a body-local alias, leaking it as an
// opaque dependent type; an explicit trailing return type is the fix. Every other compiler keeps
// `decltype(auto)` — the natural spelling — which by construction deduces `decltype(EXPR)` on
// `return EXPR;`, so the two are the same type and this is a no-op off MSVC.
//
// Confining `decltype(EXPR)` to MSVC also keeps it off clang <= 20, which in C++23 substitutes a
// non-viable constrained overload's trailing return type BEFORE its requires-clause rejects it
// (fixed clang 21), so the explicit form would fail to compile instead of removing the non-viable
// function from the overload set.
#ifndef _MSC_VER
#define DEDUCED_RETURN(...) decltype(auto)
#else
#define DEDUCED_RETURN(...) decltype(__VA_ARGS__)
#endif
// ---------- END fn/detail/macro_begin.hpp ----------

// ---------- RESUME fn/fail.hpp ----------

namespace fn {
inline namespace LIBFN_VERSION {
/**
 * @brief Checks if the monadic type can be used with the `fail` operation
 *
 * @tparam Fn The function to map the value into the error, or to observe it on `optional`
 * @tparam V The monadic type
 */
template <typename Fn, typename V>
concept applicable_fail //
    = (some_expected_non_void<V> && requires(Fn &&fn, V &&v) {
        {
          ::fn::apply(FWD(fn), FWD(v).value())
        } -> ::std::convertible_to<typename ::std::remove_cvref_t<V>::error_type>;
        requires detail::_relocatable_error<V>; // the error branch carries the existing error over
      }) || (some_expected_void<V> && requires(Fn &&fn) {
        { ::fn::apply(FWD(fn)) } -> ::std::convertible_to<typename ::std::remove_cvref_t<V>::error_type>;
        requires detail::_relocatable_error<V>;
      }) || (some_optional<V> && requires(Fn &&fn, V &&v) {
        { ::fn::apply(FWD(fn), FWD(v).value()) } -> ::std::same_as<void>;
      });

/**
 * @brief Intercept the success value and force a transition to the failure state
 *
 * The dual of `recover`. On `expected` the callback maps the value into the operand's existing
 * error type - `fail` never widens a graded error set - and an operand already holding an error
 * carries it over. On `optional` the callback observes the value, and must return `void`; the
 * result is empty. Rejected on the identity carriers, which have no failure state to enter; over
 * an uninhabited value side the operand passes through and the callback is neither invoked nor
 * instantiated.
 *
 * Use through the `fn::fail` nielbloid.
 */
constexpr inline struct fail_t final {
  /**
   * @brief Intercept the success value and force a transition to the failure state
   * @param fn On `expected`, the function to map the value into the existing error type; on
   *        `optional`, the function to observe the value, returning `void`
   * @return A functor that will fail the monadic type
   */
  [[nodiscard]] constexpr auto operator()(auto &&fn) const noexcept(noexcept(functor<fail_t, decltype(fn)>{FWD(fn)}))
      -> functor<fail_t, decltype(fn)> //
  {
    return {FWD(fn)};
  }

  struct apply;
} fail = {}; ///< Fails a value the predicate selects: `x | fail(f)`

struct fail_t::apply final {
  /**
   * @brief Fails the operand: a value maps into an error, an existing error carries over
   *
   * @param v The monad
   * @param fn The function to map the value into the error
   * @return An `expected` of the same type, holding an error
   */
  template <some_expected_non_void V, typename Fn>
  [[nodiscard]] constexpr auto operator()(V &&v, Fn &&fn) const //
      noexcept(
          ::fn::is_nothrow_applicable_v<Fn, decltype(FWD(v).value())>
          && ::std::is_nothrow_constructible_v<::std::remove_cvref_t<V>, ::fn::unexpect_t,
                                               ::fn::apply_result_t<Fn, decltype(FWD(v).value())>>
          && ::std::is_nothrow_constructible_v<::std::remove_cvref_t<V>, ::fn::unexpect_t, decltype(FWD(v).error())>)
          -> ::std::remove_cvref_t<V>
      // An identity expected cannot fail - there is no error to fail into - so the refusal is
      // stated, not left to the impossible conversion
    requires(not some_identity<V>) && applicable_fail<Fn &&, V &&>
  {
    using type = ::std::remove_cvref_t<V>;
    if (v.has_value()) {
      return type{::fn::unexpect, ::fn::apply(FWD(fn), FWD(v).value())};
    }
    return type{::fn::unexpect, FWD(v).error()};
  }

  template <some_expected_void V, typename Fn>
  [[nodiscard]] constexpr auto operator()(V &&v, Fn &&fn) const //
      noexcept(
          ::fn::is_nothrow_applicable_v<Fn>
          && ::std::is_nothrow_constructible_v<::std::remove_cvref_t<V>, ::fn::unexpect_t, ::fn::apply_result_t<Fn>>
          && ::std::is_nothrow_constructible_v<::std::remove_cvref_t<V>, ::fn::unexpect_t, decltype(FWD(v).error())>)
          -> ::std::remove_cvref_t<V>
    requires(not some_identity<V>) && applicable_fail<Fn &&, V &&>
  {
    using type = ::std::remove_cvref_t<V>;
    if (v.has_value()) {
      return type{::fn::unexpect, ::fn::apply(FWD(fn))};
    }
    return type{::fn::unexpect, FWD(v).error()};
  }

  /**
   * @brief Fails the operand: the value is observed, the result is empty
   *
   * @param v The optional
   * @param fn The function to observe the value; must return `void`
   * @return An `optional` of the same type, empty
   */
  template <some_optional V, typename Fn>
  [[nodiscard]] constexpr auto operator()(V &&v, Fn &&fn) const //
      noexcept(::fn::is_nothrow_applicable_v<Fn, decltype(FWD(v).value())>
               && ::std::is_nothrow_constructible_v<::std::remove_cvref_t<V>, ::std::nullopt_t>)
          -> ::std::remove_cvref_t<V>
    requires applicable_fail<Fn &&, V &&>
  {
    using type = ::std::remove_cvref_t<V>;
    if (v.has_value()) {
      ::fn::apply(FWD(fn), FWD(v).value());
    }
    return type{::std::nullopt};
  }

  // An uninhabited value side never holds a value to fail on, so the failure can never fire: the
  // operand passes through, and the callback is neither invoked nor instantiated. Unlike an identity
  // carrier, which is refused above, such an operand does have somewhere to fail into - it is
  // already there.
  template <some_monadic_type V, typename Fn>
  [[nodiscard]] constexpr auto operator()(V &&v, Fn &&) const
      noexcept(::std::is_nothrow_constructible_v<::std::remove_cvref_t<V>, V>) -> ::std::remove_cvref_t<V>
    requires some_empty_value<V> && detail::_relocatable<V>
  {
    return FWD(v);
  }
};

} // namespace LIBFN_VERSION
} // namespace fn

// ---------- BEGIN fn/detail/macro_end.hpp ----------
// Deliberately no include guard: see fn/detail/macro_begin.hpp.

#undef FWD // NOSONAR cpp:S959 paired with the define in macro_begin.hpp
#pragma pop_macro("FWD")

#undef DEDUCED_RETURN // NOSONAR cpp:S959 paired with the define in macro_begin.hpp
#pragma pop_macro("DEDUCED_RETURN")
// ---------- END fn/detail/macro_end.hpp ----------

// ---------- RESUME fn/fail.hpp ----------

#endif // INCLUDE_FN_FAIL
// ---------- END fn/fail.hpp ----------

// ---------- BEGIN fn/filter.hpp ----------
#ifndef INCLUDE_FN_FILTER
#define INCLUDE_FN_FILTER

// ---------- RESUME fn/filter.hpp ----------

// ---------- RESUME fn/filter.hpp ----------

// ---------- RESUME fn/filter.hpp ----------

// ---------- BEGIN fn/detail/macro_begin.hpp ----------
// Deliberately no include guard: this header and fn/detail/macro_end.hpp bracket the section of a
// header that uses the macros below; push_macro/pop_macro make the bracketing safe under nesting
// and preserve any prior user definition.

#pragma push_macro("FWD")
#undef FWD // NOSONAR cpp:S959 saved by push_macro above

// This FWD macro is a functional equivalent to std::forward<decltype(v)>(v),
// but it saves compilation time (and typing) when used frequently.
#define FWD(...) static_cast<decltype(__VA_ARGS__) &&>(__VA_ARGS__)

#pragma push_macro("DEDUCED_RETURN")
#undef DEDUCED_RETURN // NOSONAR cpp:S959 saved by push_macro above

// Spell a function's deduced return type explicitly on MSVC only. MSVC mis-resolves a deduced
// (`auto`/`decltype(auto)`) return whose type derives from a body-local alias, leaking it as an
// opaque dependent type; an explicit trailing return type is the fix. Every other compiler keeps
// `decltype(auto)` — the natural spelling — which by construction deduces `decltype(EXPR)` on
// `return EXPR;`, so the two are the same type and this is a no-op off MSVC.
//
// Confining `decltype(EXPR)` to MSVC also keeps it off clang <= 20, which in C++23 substitutes a
// non-viable constrained overload's trailing return type BEFORE its requires-clause rejects it
// (fixed clang 21), so the explicit form would fail to compile instead of removing the non-viable
// function from the overload set.
#ifndef _MSC_VER
#define DEDUCED_RETURN(...) decltype(auto)
#else
#define DEDUCED_RETURN(...) decltype(__VA_ARGS__)
#endif
// ---------- END fn/detail/macro_begin.hpp ----------

// ---------- RESUME fn/filter.hpp ----------

namespace fn {
inline namespace LIBFN_VERSION {
/**
 * @brief Checks if the monadic type can be used with the `filter` operation
 *
 * @tparam Pred The predicate to filter the value
 * @tparam Err The error handler
 * @tparam V The monadic type
 */
// A rejected operand is returned whole (`return FWD(v)`), and a kept one is rebuilt around its
// existing value - so both sides must survive the trip.
template <typename Pred, typename Err, typename V>
concept applicable_filter //
    = (some_expected_non_void<V> && requires(Pred &&pred, Err &&on_err, V &&v) {
        { ::fn::apply(FWD(pred), ::std::as_const(v).value()) } -> convertible_to_bool;
        {
          ::fn::apply(FWD(on_err), FWD(v).value())
        } -> ::std::convertible_to<typename ::std::remove_cvref_t<V>::error_type>;
        requires detail::_relocatable<V> && detail::_relocatable_value<V>;
      }) || (some_expected_void<V> && requires(Pred &&pred, Err &&on_err, V &&v) {
        { ::fn::apply(FWD(pred)) } -> convertible_to_bool;
        { ::fn::apply(FWD(on_err)) } -> ::std::convertible_to<typename ::std::remove_cvref_t<V>::error_type>;
        requires detail::_relocatable<V>;
      }) || (some_optional<V> && ::std::same_as<Err, void> && requires(Pred &&pred, V &&v) {
        { ::fn::apply(FWD(pred), ::std::as_const(v).value()) } -> convertible_to_bool;
        requires detail::_relocatable<V> && detail::_relocatable_value<V>;
      });

/**
 * @brief Filter the value of the monadic type using a predicate and an error handler
 *
 * When used on `fn::expected`, this operation takes both a predicate and an error handler.
 * However, when used on `fn::optional`, this operation only takes a predicate.
 *
 * Use through the `fn::filter` nielbloid.
 */
constexpr inline struct filter_t final {
  /**
   * @brief Filter the value of the monadic type using a predicate and an error handler
   * @param pred The predicate to filter the value, takes the value by const reference and returns bool
   * @param on_err The error handler, returning the error type; consumes the value in the operand's
   *        value category
   * @return A functor that will filter the value of the monadic type
   */
  [[nodiscard]] constexpr auto operator()(auto &&pred, auto &&on_err) const
      noexcept(noexcept(functor<filter_t, decltype(pred), decltype(on_err)>{FWD(pred), FWD(on_err)}))
          -> functor<filter_t, decltype(pred), decltype(on_err)>
  {
    return {FWD(pred), FWD(on_err)};
  }

  /**
   * @brief Filter the value of the `fn::optional` using a predicate and an error handler
   * @param pred The predicate to filter the value, takes the value by const reference and returns bool
   * @return A functor that will filter the value of the monadic type
   */
  [[nodiscard]] constexpr auto operator()(auto &&pred) const
      noexcept(noexcept(functor<filter_t, decltype(pred)>{FWD(pred)})) -> functor<filter_t, decltype(pred)>
  {
    return {FWD(pred)};
  }

  struct apply;
} filter = {}; ///< Rejects a value the predicate refuses: `x | filter(f)`

struct filter_t::apply final {
  /**
   * @brief Filters the operand: a value failing the predicate is replaced by the handler's error
   *
   * @param v The monad
   * @param pred The predicate, applied on the value as const
   * @param on_err The error handler, consuming the value where the predicate answered false
   * @return An `expected` of the same type
   */
  template <some_expected_non_void V, typename Pred, typename OnErr>
  [[nodiscard]] constexpr auto operator()(V &&v, Pred &&pred, OnErr &&on_err) const //
      noexcept(
          ::fn::is_nothrow_applicable_v<Pred, decltype(::std::as_const(v).value())>
          && ::fn::is_nothrow_applicable_v<OnErr, decltype(FWD(v).value())>
          && ::std::is_nothrow_constructible_v<::std::remove_cvref_t<V>, ::std::in_place_t, decltype(FWD(v).value())>
          && ::std::is_nothrow_constructible_v<::std::remove_cvref_t<V>, ::fn::unexpect_t,
                                               ::fn::apply_result_t<OnErr, decltype(FWD(v).value())>>
          && ::std::is_nothrow_constructible_v<::std::remove_cvref_t<V>, V>) -> ::std::remove_cvref_t<V>
      // An identity expected cannot reject a value - there is no error to fail into - so the refusal
      // is stated, not left to the impossible conversion
    requires(not some_identity<V>) && applicable_filter<Pred &&, OnErr &&, V &&>
  {
    using type = ::std::remove_cvref_t<V>;
    if (::std::as_const(v).has_value()) {
      bool const keep = ::fn::apply(FWD(pred), ::std::as_const(v).value());
      return (keep ? type{::std::in_place, FWD(v).value()}
                   : type{::fn::unexpect, ::fn::apply(FWD(on_err), FWD(v).value())});
    }
    return FWD(v);
  }

  template <some_expected_void V, typename Pred, typename OnErr>
  [[nodiscard]] constexpr auto operator()(V &&v, Pred &&pred, OnErr &&on_err) const //
      noexcept(
          ::fn::is_nothrow_applicable_v<Pred> && ::fn::is_nothrow_applicable_v<OnErr>
          && ::std::is_nothrow_constructible_v<::std::remove_cvref_t<V>, ::std::in_place_t>
          && ::std::is_nothrow_constructible_v<::std::remove_cvref_t<V>, ::fn::unexpect_t, ::fn::apply_result_t<OnErr>>
          && ::std::is_nothrow_constructible_v<::std::remove_cvref_t<V>, V>) -> ::std::remove_cvref_t<V>
    requires(not some_identity<V>) && applicable_filter<Pred &&, OnErr &&, V &&>
  {
    using type = ::std::remove_cvref_t<V>;
    if (::std::as_const(v).has_value()) {
      bool const keep = ::fn::apply(FWD(pred));
      return (keep ? type{::std::in_place} //
                   : type{::fn::unexpect, ::fn::apply(FWD(on_err))});
    }
    return FWD(v);
  }

  /**
   * @brief Filters the operand: a value failing the predicate is replaced by the empty state
   *
   * @param v The optional
   * @param pred The predicate, applied on the value as const
   * @return An `optional` of the same type
   */
  template <some_optional V, typename Pred>
  [[nodiscard]] constexpr auto operator()(V &&v, Pred &&pred) const //
      noexcept(
          ::fn::is_nothrow_applicable_v<Pred, decltype(::std::as_const(v).value())>
          && ::std::is_nothrow_constructible_v<::std::remove_cvref_t<V>, ::std::in_place_t, decltype(FWD(v).value())>
          && ::std::is_nothrow_constructible_v<::std::remove_cvref_t<V>, ::std::nullopt_t>
          && ::std::is_nothrow_constructible_v<::std::remove_cvref_t<V>, V>) -> ::std::remove_cvref_t<V>
    requires applicable_filter<Pred &&, void, V &&>
  {
    using type = ::std::remove_cvref_t<V>;
    if (::std::as_const(v).has_value()) {
      bool const keep = ::fn::apply(FWD(pred), ::std::as_const(v).value());
      return (keep ? type{::std::in_place, FWD(v).value()} //
                   : type{::std::nullopt});
    }
    return FWD(v);
  }

  // An uninhabited value side never holds a value to test, so nothing can be rejected: the operand
  // passes through, and neither callback is invoked or instantiated. Unlike an identity carrier,
  // which is refused above, such an operand does have somewhere to fail into - it is already there.
  template <some_expected V, typename Pred, typename OnErr>
  [[nodiscard]] constexpr auto operator()(V &&v, Pred &&, OnErr &&) const
      noexcept(::std::is_nothrow_constructible_v<::std::remove_cvref_t<V>, V>) -> ::std::remove_cvref_t<V>
    requires some_empty_value<V> && detail::_relocatable<V>
  {
    return FWD(v);
  }

  template <some_optional V, typename Pred>
  [[nodiscard]] constexpr auto operator()(V &&v, Pred &&) const
      noexcept(::std::is_nothrow_constructible_v<::std::remove_cvref_t<V>, V>) -> ::std::remove_cvref_t<V>
    requires some_empty_value<V> && detail::_relocatable<V>
  {
    return FWD(v);
  }
};

} // namespace LIBFN_VERSION
} // namespace fn

// ---------- BEGIN fn/detail/macro_end.hpp ----------
// Deliberately no include guard: see fn/detail/macro_begin.hpp.

#undef FWD // NOSONAR cpp:S959 paired with the define in macro_begin.hpp
#pragma pop_macro("FWD")

#undef DEDUCED_RETURN // NOSONAR cpp:S959 paired with the define in macro_begin.hpp
#pragma pop_macro("DEDUCED_RETURN")
// ---------- END fn/detail/macro_end.hpp ----------

// ---------- RESUME fn/filter.hpp ----------

#endif // INCLUDE_FN_FILTER
// ---------- END fn/filter.hpp ----------

// ---------- BEGIN fn/inspect.hpp ----------
#ifndef INCLUDE_FN_INSPECT
#define INCLUDE_FN_INSPECT

// ---------- RESUME fn/inspect.hpp ----------

// ---------- RESUME fn/inspect.hpp ----------

// ---------- RESUME fn/inspect.hpp ----------

// ---------- RESUME fn/inspect.hpp ----------

// ---------- RESUME fn/inspect.hpp ----------

// ---------- RESUME fn/inspect.hpp ----------

// ---------- BEGIN fn/detail/macro_begin.hpp ----------
// Deliberately no include guard: this header and fn/detail/macro_end.hpp bracket the section of a
// header that uses the macros below; push_macro/pop_macro make the bracketing safe under nesting
// and preserve any prior user definition.

#pragma push_macro("FWD")
#undef FWD // NOSONAR cpp:S959 saved by push_macro above

// This FWD macro is a functional equivalent to std::forward<decltype(v)>(v),
// but it saves compilation time (and typing) when used frequently.
#define FWD(...) static_cast<decltype(__VA_ARGS__) &&>(__VA_ARGS__)

#pragma push_macro("DEDUCED_RETURN")
#undef DEDUCED_RETURN // NOSONAR cpp:S959 saved by push_macro above

// Spell a function's deduced return type explicitly on MSVC only. MSVC mis-resolves a deduced
// (`auto`/`decltype(auto)`) return whose type derives from a body-local alias, leaking it as an
// opaque dependent type; an explicit trailing return type is the fix. Every other compiler keeps
// `decltype(auto)` — the natural spelling — which by construction deduces `decltype(EXPR)` on
// `return EXPR;`, so the two are the same type and this is a no-op off MSVC.
//
// Confining `decltype(EXPR)` to MSVC also keeps it off clang <= 20, which in C++23 substitutes a
// non-viable constrained overload's trailing return type BEFORE its requires-clause rejects it
// (fixed clang 21), so the explicit form would fail to compile instead of removing the non-viable
// function from the overload set.
#ifndef _MSC_VER
#define DEDUCED_RETURN(...) decltype(auto)
#else
#define DEDUCED_RETURN(...) decltype(__VA_ARGS__)
#endif
// ---------- END fn/detail/macro_begin.hpp ----------

// ---------- RESUME fn/inspect.hpp ----------

namespace fn {
inline namespace LIBFN_VERSION {
/**
 * @brief Checks if the monadic type can be used with the `inspect` operation
 *
 * @tparam Fn The function to observe the value
 * @tparam V The monadic type
 */
template <typename Fn, typename V>
concept applicable_inspect //
    = (some_expected_non_void<V> && requires(Fn &&fn, V &&v) {
        { ::fn::apply(FWD(fn), ::std::as_const(v).value()) } -> ::std::same_as<void>;
      }) || (some_expected_void<V> && requires(Fn &&fn) {
        { ::fn::apply(FWD(fn)) } -> ::std::same_as<void>;
      }) || (some_optional<V> && requires(Fn &&fn, V &&v) {
        { ::fn::apply(FWD(fn), ::std::as_const(v).value()) } -> ::std::same_as<void>;
      }) || (some_choice<V> && requires(Fn &&fn, V &&v) {
        { ::fn::apply(FWD(fn), ::std::as_const(v).value()) } -> ::std::same_as<void>;
      }) || (some_just<V> && (not ::std::is_void_v<typename ::std::remove_cvref_t<V>::value_type>) && requires(Fn &&fn, V &&v) {
        { ::fn::apply(FWD(fn), ::std::as_const(v).value()) } -> ::std::same_as<void>;
      }) || (some_just<V> && ::std::is_void_v<typename ::std::remove_cvref_t<V>::value_type> && requires(Fn &&fn) {
        { ::fn::apply(FWD(fn)) } -> ::std::same_as<void>;
      });

/**
 * @brief Observe the value for side-effects, passing the operand through unchanged
 *
 * The callback receives the value as const and must return `void`: observation can neither mutate
 * the operand nor replace it. Where the carrier can be empty or hold an error, the callback runs
 * only when a value is present; on `choice` and `just` it always runs; over an uninhabited value
 * side it is neither invoked nor instantiated.
 *
 * Use through the `fn::inspect` nielbloid.
 */
constexpr inline struct inspect_t final {
  /**
   * @brief Observe the value for side-effects, passing the operand through unchanged
   * @param fn The function to observe the value; invoked with no arguments where the value is `void`
   * @return A functor that will execute the function on the value
   */
  [[nodiscard]] constexpr auto operator()(auto &&fn) const noexcept(noexcept(functor<inspect_t, decltype(fn)>{FWD(fn)}))
      -> functor<inspect_t, decltype(fn)>
  {
    return {FWD(fn)};
  }

  struct apply;
} inspect = {}; ///< Observes the value in passing: `x | inspect(f)`

struct inspect_t::apply final {
  /**
   * @brief Observes the value for side-effects, when one is present
   *
   * @param v The monad
   * @param fn The function to observe the value
   * @return The operand, forwarded unchanged
   */
  template <some_expected_non_void V, typename Fn>
  [[nodiscard]] constexpr auto operator()(V &&v, Fn &&fn) const
      noexcept(::fn::is_nothrow_applicable_v<Fn, decltype(::std::as_const(v).value())>) -> V &&
    requires applicable_inspect<Fn &&, V &&>
  {
    if (v.has_value()) {
      ::fn::apply(FWD(fn), ::std::as_const(v).value()); // side-effects only
    }
    return FWD(v);
  }

  template <some_expected_void V, typename Fn>
  [[nodiscard]] constexpr auto operator()(V &&v, Fn &&fn) const noexcept(::fn::is_nothrow_applicable_v<Fn>) -> V &&
    requires applicable_inspect<Fn &&, V &&>
  {
    if (v.has_value()) {
      ::fn::apply(FWD(fn)); // side-effects only
    }
    return FWD(v);
  }

  template <some_optional V, typename Fn>
  [[nodiscard]] constexpr auto operator()(V &&v, Fn &&fn) const
      noexcept(::fn::is_nothrow_applicable_v<Fn, decltype(::std::as_const(v).value())>) -> V &&
    requires applicable_inspect<Fn &&, V &&>
  {
    if (v.has_value()) {
      ::fn::apply(FWD(fn), ::std::as_const(v).value()); // side-effects only
    }
    return FWD(v);
  }

  template <some_choice V, typename Fn>
  [[nodiscard]] constexpr auto operator()(V &&v, Fn &&fn) const
      noexcept(::fn::is_nothrow_applicable_v<Fn, decltype(::std::as_const(v).value())>) -> V &&
    requires applicable_inspect<Fn &&, V &&>
  {
    ::fn::apply(FWD(fn), ::std::as_const(v).value()); // side-effects only
    return FWD(v);
  }

  template <some_just V, typename Fn>
    requires(not ::std::is_void_v<typename ::std::remove_cvref_t<V>::value_type>)
  [[nodiscard]] constexpr auto operator()(V &&v, Fn &&fn) const
      noexcept(::fn::is_nothrow_applicable_v<Fn, decltype(::std::as_const(v).value())>) -> V &&
    requires applicable_inspect<Fn &&, V &&>
  {
    ::fn::apply(FWD(fn), ::std::as_const(v).value()); // side-effects only
    return FWD(v);
  }

  template <some_just V, typename Fn>
    requires ::std::is_void_v<typename ::std::remove_cvref_t<V>::value_type>
  [[nodiscard]] constexpr auto operator()(V &&v, Fn &&fn) const noexcept(::fn::is_nothrow_applicable_v<Fn>) -> V &&
    requires applicable_inspect<Fn &&, V &&>
  {
    ::fn::apply(FWD(fn)); // side-effects only
    return FWD(v);
  }

  // An uninhabited value side never holds a value, so there is nothing to observe: the operand
  // passes through, and the callback is neither invoked nor instantiated.
  template <some_monadic_type V, typename Fn>
  [[nodiscard]] constexpr auto operator()(V &&v, Fn &&) const noexcept -> V &&
    requires some_empty_value<V>
  {
    return FWD(v);
  }
};

} // namespace LIBFN_VERSION
} // namespace fn

// ---------- BEGIN fn/detail/macro_end.hpp ----------
// Deliberately no include guard: see fn/detail/macro_begin.hpp.

#undef FWD // NOSONAR cpp:S959 paired with the define in macro_begin.hpp
#pragma pop_macro("FWD")

#undef DEDUCED_RETURN // NOSONAR cpp:S959 paired with the define in macro_begin.hpp
#pragma pop_macro("DEDUCED_RETURN")
// ---------- END fn/detail/macro_end.hpp ----------

// ---------- RESUME fn/inspect.hpp ----------

#endif // INCLUDE_FN_INSPECT
// ---------- END fn/inspect.hpp ----------

// ---------- BEGIN fn/inspect_error.hpp ----------
#ifndef INCLUDE_FN_INSPECT_ERROR
#define INCLUDE_FN_INSPECT_ERROR

// ---------- RESUME fn/inspect_error.hpp ----------

// ---------- RESUME fn/inspect_error.hpp ----------

// ---------- RESUME fn/inspect_error.hpp ----------

// ---------- BEGIN fn/detail/macro_begin.hpp ----------
// Deliberately no include guard: this header and fn/detail/macro_end.hpp bracket the section of a
// header that uses the macros below; push_macro/pop_macro make the bracketing safe under nesting
// and preserve any prior user definition.

#pragma push_macro("FWD")
#undef FWD // NOSONAR cpp:S959 saved by push_macro above

// This FWD macro is a functional equivalent to std::forward<decltype(v)>(v),
// but it saves compilation time (and typing) when used frequently.
#define FWD(...) static_cast<decltype(__VA_ARGS__) &&>(__VA_ARGS__)

#pragma push_macro("DEDUCED_RETURN")
#undef DEDUCED_RETURN // NOSONAR cpp:S959 saved by push_macro above

// Spell a function's deduced return type explicitly on MSVC only. MSVC mis-resolves a deduced
// (`auto`/`decltype(auto)`) return whose type derives from a body-local alias, leaking it as an
// opaque dependent type; an explicit trailing return type is the fix. Every other compiler keeps
// `decltype(auto)` — the natural spelling — which by construction deduces `decltype(EXPR)` on
// `return EXPR;`, so the two are the same type and this is a no-op off MSVC.
//
// Confining `decltype(EXPR)` to MSVC also keeps it off clang <= 20, which in C++23 substitutes a
// non-viable constrained overload's trailing return type BEFORE its requires-clause rejects it
// (fixed clang 21), so the explicit form would fail to compile instead of removing the non-viable
// function from the overload set.
#ifndef _MSC_VER
#define DEDUCED_RETURN(...) decltype(auto)
#else
#define DEDUCED_RETURN(...) decltype(__VA_ARGS__)
#endif
// ---------- END fn/detail/macro_begin.hpp ----------

// ---------- RESUME fn/inspect_error.hpp ----------

namespace fn {
inline namespace LIBFN_VERSION {
/**
 * @brief Checks if the monadic type can be used with the `inspect_error` operation
 *
 * @tparam Fn The function to observe the error
 * @tparam V The monadic type
 */
template <typename Fn, typename V>
concept applicable_inspect_error //
    = (some_expected<V> && requires(Fn &&fn, V &&v) {
        { ::fn::apply(FWD(fn), ::std::as_const(v).error()) } -> ::std::same_as<void>;
      }) || (some_optional<V> && requires(Fn &&fn) {
        { ::fn::apply(FWD(fn)) } -> ::std::same_as<void>;
      });

/**
 * @brief Observe the error for side-effects, passing the operand through unchanged
 *
 * The callback receives the error as const and must return `void`; on `optional` it is invoked
 * with no arguments - the empty state carries no error value. Rejected on `choice` and `just`,
 * which have no error side; on the identity `expected` it is vacuous - the operand passes through
 * and the callback is never instantiated.
 *
 * Use through the `fn::inspect_error` nielbloid.
 */
constexpr inline struct inspect_error_t final {
  /**
   * @brief Observe the error for side-effects, passing the operand through unchanged
   * @param fn The function to observe the error; invoked with no arguments on `optional`
   * @return A functor that will execute the function on the error
   */
  [[nodiscard]] constexpr auto operator()(auto &&fn) const
      noexcept(noexcept(functor<inspect_error_t, decltype(fn)>{FWD(fn)})) -> functor<inspect_error_t, decltype(fn)> //
  {
    return {FWD(fn)};
  }

  struct apply;
} inspect_error = {}; ///< Observes the error in passing: `x | inspect_error(f)`

struct inspect_error_t::apply final {
  /**
   * @brief Observes the error for side-effects, when one is present
   *
   * @param v The monad
   * @param fn The function to observe the error
   * @return The operand, forwarded unchanged
   */
  template <some_expected V, typename Fn>
  [[nodiscard]] constexpr auto operator()(V &&v, Fn &&fn) const
      noexcept(::fn::is_nothrow_applicable_v<Fn, decltype(::std::as_const(v).error())>) -> V &&
    requires(not some_identity<V>) && applicable_inspect_error<Fn &&, V &&>
  {
    if (not v.has_value()) {
      ::fn::apply(FWD(fn), ::std::as_const(v).error()); // side-effects only
    }
    return FWD(v);
  }

  // An identity expected's error side is uninhabited - there is nothing to observe, the operand
  // passes through and the callback is never instantiated
  template <some_expected V, typename Fn>
  [[nodiscard]] constexpr auto operator()(V &&v, Fn &&) const noexcept -> V &&
    requires some_identity<V>
  {
    return FWD(v);
  }

  template <some_optional V, typename Fn>
  [[nodiscard]] constexpr auto operator()(V &&v, Fn &&fn) const noexcept(::fn::is_nothrow_applicable_v<Fn>) -> V &&
    requires applicable_inspect_error<Fn &&, V &&>
  {
    if (not v.has_value()) {
      ::fn::apply(FWD(fn)); // side-effects only
    }
    return FWD(v);
  }
};

} // namespace LIBFN_VERSION
} // namespace fn

// ---------- BEGIN fn/detail/macro_end.hpp ----------
// Deliberately no include guard: see fn/detail/macro_begin.hpp.

#undef FWD // NOSONAR cpp:S959 paired with the define in macro_begin.hpp
#pragma pop_macro("FWD")

#undef DEDUCED_RETURN // NOSONAR cpp:S959 paired with the define in macro_begin.hpp
#pragma pop_macro("DEDUCED_RETURN")
// ---------- END fn/detail/macro_end.hpp ----------

// ---------- RESUME fn/inspect_error.hpp ----------

#endif // INCLUDE_FN_INSPECT_ERROR
// ---------- END fn/inspect_error.hpp ----------

// ---------- BEGIN fn/or_else.hpp ----------
#ifndef INCLUDE_FN_OR_ELSE
#define INCLUDE_FN_OR_ELSE

// ---------- RESUME fn/or_else.hpp ----------

// ---------- RESUME fn/or_else.hpp ----------

// ---------- RESUME fn/or_else.hpp ----------

// ---------- RESUME fn/or_else.hpp ----------

// ---------- RESUME fn/or_else.hpp ----------

// ---------- RESUME fn/or_else.hpp ----------

// ---------- BEGIN fn/detail/macro_begin.hpp ----------
// Deliberately no include guard: this header and fn/detail/macro_end.hpp bracket the section of a
// header that uses the macros below; push_macro/pop_macro make the bracketing safe under nesting
// and preserve any prior user definition.

#pragma push_macro("FWD")
#undef FWD // NOSONAR cpp:S959 saved by push_macro above

// This FWD macro is a functional equivalent to std::forward<decltype(v)>(v),
// but it saves compilation time (and typing) when used frequently.
#define FWD(...) static_cast<decltype(__VA_ARGS__) &&>(__VA_ARGS__)

#pragma push_macro("DEDUCED_RETURN")
#undef DEDUCED_RETURN // NOSONAR cpp:S959 saved by push_macro above

// Spell a function's deduced return type explicitly on MSVC only. MSVC mis-resolves a deduced
// (`auto`/`decltype(auto)`) return whose type derives from a body-local alias, leaking it as an
// opaque dependent type; an explicit trailing return type is the fix. Every other compiler keeps
// `decltype(auto)` — the natural spelling — which by construction deduces `decltype(EXPR)` on
// `return EXPR;`, so the two are the same type and this is a no-op off MSVC.
//
// Confining `decltype(EXPR)` to MSVC also keeps it off clang <= 20, which in C++23 substitutes a
// non-viable constrained overload's trailing return type BEFORE its requires-clause rejects it
// (fixed clang 21), so the explicit form would fail to compile instead of removing the non-viable
// function from the overload set.
#ifndef _MSC_VER
#define DEDUCED_RETURN(...) decltype(auto)
#else
#define DEDUCED_RETURN(...) decltype(__VA_ARGS__)
#endif
// ---------- END fn/detail/macro_begin.hpp ----------

// ---------- RESUME fn/or_else.hpp ----------

namespace fn {
inline namespace LIBFN_VERSION {

namespace detail {
// optional -> expected: the empty state's nullary callback names the target carrier, and self's
// value joins the target's value side under the grade-sticky rules
template <typename T, typename Fn> struct _or_else_to_expected {};
template <typename T, typename Fn>
  requires(_is_applicable<Fn>::value)
          && _joining_superset::is_kind<::fn::expected, ::std::remove_cvref_t<typename _apply_result<Fn>::type>>
          && requires {
               typename _joining_expected::graded_join<T, typename _joining_expected::parts<::std::remove_cvref_t<
                                                              typename _apply_result<Fn>::type>>::value_type>::type;
             }
struct _or_else_to_expected<T, Fn> {
  using _result = ::std::remove_cvref_t<typename _apply_result<Fn>::type>;
  using type = ::fn::expected<
      typename _joining_expected::graded_join<T, typename _joining_expected::parts<_result>::value_type>::type,
      typename _joining_expected::parts<_result>::error_type>;
};

// expected -> optional: the error's callback (per alternative when graded) names the target;
// the pass-through value joins every branch's value
template <typename T, typename Fn, typename ErrArg> struct _or_else_to_optional {};
template <typename T, typename Fn, typename ErrArg>
  requires(not _some_copack<::std::remove_cvref_t<ErrArg>>) && (_is_applicable<Fn, ErrArg>::value)
          && _joining_superset::is_kind<::fn::optional, ::std::remove_cvref_t<typename _apply_result<Fn, ErrArg>::type>>
struct _or_else_to_optional<T, Fn, ErrArg>
    : _joined_optional_recovery<::fn::optional, T, ::std::remove_cvref_t<typename _apply_result<Fn, ErrArg>::type>> {};
template <typename T, typename Fn, typename ErrArg>
  requires _some_copack<::std::remove_cvref_t<ErrArg>>
struct _or_else_to_optional<T, Fn, ErrArg>
    : _copack_apply_result<_joining_optional_recovery_tag<::fn::optional, T>, Fn, ErrArg> {};

// the promises, computed per arm; a dead arm never weighs
template <typename T, typename Fn, typename ValArg> struct _nothrow_or_else_to_expected {
  using _result = ::std::remove_cvref_t<typename _apply_result<Fn>::type>;
  using _type = typename _or_else_to_expected<T, Fn>::type;
  static constexpr bool _convert
      = ::std::is_same_v<_result, _type>
        || ((empty_copack<typename _result::value_type>
             || ::std::is_nothrow_constructible_v<_type, ::std::in_place_t, typename _result::value_type &&>)
            && ::std::is_nothrow_constructible_v<_type, ::fn::unexpect_t, typename _result::error_type &&>);
  static constexpr bool value
      = _is_nothrow_applicable<Fn>::value && _convert
        && (empty_copack<T> || ::std::is_nothrow_constructible_v<_type, ::std::in_place_t, ValArg>);
};

template <typename T, typename Fn, typename ErrArg, typename ValArg> struct _nothrow_or_else_to_optional;
template <typename T, typename Fn, typename ErrArg, typename ValArg>
  requires _some_copack<::std::remove_cvref_t<ErrArg>>
struct _nothrow_or_else_to_optional<T, Fn, ErrArg, ValArg> {
  using _type = typename _or_else_to_optional<T, Fn, ErrArg>::type;
  static constexpr bool value
      = _is_nothrow_rts_applicable<_type, Fn, ErrArg>
        && (empty_copack<T> || ::std::is_nothrow_constructible_v<_type, ::std::in_place_t, ValArg>);
};
template <typename T, typename Fn, typename ErrArg, typename ValArg>
  requires(not _some_copack<::std::remove_cvref_t<ErrArg>>)
struct _nothrow_or_else_to_optional<T, Fn, ErrArg, ValArg> {
  using _result = ::std::remove_cvref_t<typename _apply_result<Fn, ErrArg>::type>;
  using _type = typename _or_else_to_optional<T, Fn, ErrArg>::type;
  static constexpr bool _convert
      = ::std::is_same_v<_result, _type>
        || (empty_copack<typename _result::value_type>
            || ::std::is_nothrow_constructible_v<_type, ::std::in_place_t, typename _result::value_type &&>);
  static constexpr bool value
      = _is_nothrow_applicable<Fn, ErrArg>::value && _convert
        && (empty_copack<T> || ::std::is_nothrow_constructible_v<_type, ::std::in_place_t, ValArg>);
};
} // namespace detail
/**
 * @brief Checks if the monadic type can be used with the `or_else` operation
 *
 * @tparam Fn The function to execute on the dead state
 * @tparam V The monadic type
 */
template <typename Fn, typename V>
concept applicable_or_else //
    = (some_expected<V> && requires(V &&v) {
        typename detail::_or_else_dispatch<typename ::std::remove_cvref_t<V>::value_type, Fn,
                                           decltype(FWD(v).error())>::type;
        requires same_value_kind<V, typename detail::_or_else_dispatch<typename ::std::remove_cvref_t<V>::value_type,
                                                                       Fn, decltype(FWD(v).error())>::type>;
      }) || (some_expected<V> //
         && some_copack<typename ::std::remove_cvref_t<V>::value_type> && requires(V &&v) {
        typename detail::_or_else_dispatch<typename ::std::remove_cvref_t<V>::value_type, Fn,
                                           decltype(FWD(v).error())>::type;
        requires some_expected<typename detail::_or_else_dispatch<typename ::std::remove_cvref_t<V>::value_type, Fn,
                                                                  decltype(FWD(v).error())>::type>;
      }) || (some_optional<V> && requires(Fn &&fn) {
        {
          ::fn::apply(FWD(fn))
        } -> same_value_kind<V>;
      }) || (some_optional<V>  //
         && some_copack<typename ::std::remove_cvref_t<V>::value_type> && requires(Fn &&fn, V &&v) {
        {
          ::fn::apply(FWD(fn))
        } -> some_optional;
      });

/**
 * @brief Checks if the callback can be used with `or_else` recovering across the expected/optional
 *        pair
 *
 * The callback witnesses the inhabited dead state - optional's empty state (nullary) or expected's
 * error (per alternative) - and its declared carrier names the result kind; self's value joins the
 * target's value side under the grade-sticky rules. An identity expected is excluded: the fold of
 * the callback over zero error alternatives has no inputs, so those keep the vacuous identity.
 *
 * @tparam Fn The function to execute on the dead state
 * @tparam V The monadic type
 */
template <typename Fn, typename V>
concept applicable_or_else_across //
    = (some_optional<V> && (not applicable_or_else<Fn, V>) && requires {
        typename detail::_or_else_to_expected<typename ::std::remove_cvref_t<V>::value_type, Fn>::type;
      } && (empty_copack<typename ::std::remove_cvref_t<V>::value_type> || requires(V &&v) {
         requires ::std::is_constructible_v<
             typename detail::_or_else_to_expected<typename ::std::remove_cvref_t<V>::value_type, Fn>::type,
             ::std::in_place_t, decltype(*FWD(v))>;
       })) || (some_expected<V> && (not some_identity<V>) && (not applicable_or_else<Fn, V>) && requires(V &&v) {
        typename detail::_or_else_to_optional<typename ::std::remove_cvref_t<V>::value_type, Fn,
                                              decltype(FWD(v).error())>::type;
      } && (empty_copack<typename ::std::remove_cvref_t<V>::value_type> || requires(V &&v) {
                 requires ::std::is_constructible_v<
                     typename detail::_or_else_to_optional<typename ::std::remove_cvref_t<V>::value_type, Fn,
                                                           decltype(FWD(v).error())>::type,
                     ::std::in_place_t, decltype(FWD(v).value())>;
               }));

/**
 * @brief Sequence a recovery computation on the failure path, joining its values
 *
 * The callback witnesses the dead state - `expected`'s error, per alternative when graded, or
 * `optional`'s empty state, with no arguments - and returns a carrier; a successful operand passes
 * through, bypassing it. Recovery branches may return heterogeneous carriers of the same value
 * kind: their values join, and an error alternative handled by a branch leaves the grade unless
 * re-returned. In the pipeline form the callback's carrier may also bridge across the
 * expected/optional pair; on the identity `expected` the operation is vacuous - nothing is asked
 * of the handler, not even that it be callable.
 *
 * Use through the `fn::or_else` nielbloid.
 */
constexpr inline struct or_else_t final {
  /**
   * @brief Sequence a recovery computation on the failure path, joining its values
   * @param fn The function to execute on the dead state - the error on `expected`, no arguments
   *        on `optional` - returning a carrier
   * @return A functor that will recover the monadic type
   */
  [[nodiscard]] constexpr auto operator()(auto &&fn) const noexcept(noexcept(functor<or_else_t, decltype(fn)>{FWD(fn)}))
      -> functor<or_else_t, decltype(fn)> //
  {
    return {FWD(fn)};
  }

  struct apply;
} or_else = {}; ///< Binds the dead state, returning a carrier: `x | or_else(f)`

struct or_else_t::apply final {
  /**
   * @brief Recovers through the carrier's own `or_else` member
   *
   * @param v The monad
   * @param fn The function to execute on the dead state
   * @return A carrier of the same value kind
   */
  template <some_monadic_type V, typename Fn>
  [[nodiscard]] constexpr auto operator()(V &&v, Fn &&fn) const //
      noexcept(noexcept(FWD(v).or_else(FWD(fn))))               //
      -> same_value_kind<V &&> auto
    requires(not some_identity<V>) && applicable_or_else<Fn &&, V &&>
  {
    return FWD(v).or_else(FWD(fn));
  }

  // An identity expected's error side is uninhabited - delegate to the vacuous member, which
  // accepts any callback and never instantiates it
  template <some_expected V, typename Fn>
  [[nodiscard]] constexpr auto operator()(V &&v, Fn &&fn) const //
      noexcept(noexcept(FWD(v).or_else(FWD(fn))))               //
      -> same_value_kind<V &&> auto
    requires some_identity<V>
  {
    return FWD(v).or_else(FWD(fn));
  }

  // The cross arms: the callback witnesses the inhabited dead state and names the target carrier -
  // or_else invokes on 1-states and is silent on 0-states, which is why an identity expected keeps
  // the vacuous arm above. Engine-direct: the members are each carrier's own recovery, and the
  // verb layer is the licensed cross-carrier place.
  template <some_optional V, typename Fn>
  [[nodiscard]] constexpr auto operator()(V &&v, Fn &&fn) const //
      noexcept(detail::_nothrow_or_else_to_expected<typename ::std::remove_cvref_t<V>::value_type, Fn &&,
                                                    decltype(*::std::declval<V>())>::value) //
      -> some_expected auto
    requires applicable_or_else_across<Fn &&, V &&>
  {
    using T = typename ::std::remove_cvref_t<V>::value_type;
    using type = typename detail::_or_else_to_expected<T, Fn &&>::type;
    if constexpr (not empty_copack<T>)
      if (v.has_value())
        return type{::std::in_place, *FWD(v)};
    using result = ::std::remove_cvref_t<typename detail::_apply_result<Fn &&>::type>;
    if constexpr (::std::is_same_v<result, type>)
      return ::fn::detail::_apply(FWD(fn));
    else {
      auto t = ::fn::detail::_apply(FWD(fn));
      if (t.has_value()) {
        if constexpr (not empty_copack<typename result::value_type>)
          return type{::std::in_place, ::std::move(t).value()};
        else
          ::pfn::unreachable(); // LCOV_EXCL_LINE
      } else
        return type{::fn::unexpect, ::std::move(t).error()};
    }
  }

  template <some_expected V, typename Fn>
  [[nodiscard]] constexpr auto operator()(V &&v, Fn &&fn) const //
      noexcept(detail::_nothrow_or_else_to_optional<typename ::std::remove_cvref_t<V>::value_type, Fn &&,
                                                    decltype(::std::declval<V>().error()),
                                                    decltype(::std::declval<V>().value())>::value) //
      -> some_optional auto
    requires applicable_or_else_across<Fn &&, V &&>
  {
    using T = typename ::std::remove_cvref_t<V>::value_type;
    using type = typename detail::_or_else_to_optional<T, Fn &&, decltype(FWD(v).error())>::type;
    if constexpr (not empty_copack<T>)
      if (v.has_value())
        return type{::std::in_place, FWD(v).value()};
    if constexpr (detail::_some_copack<::std::remove_cvref_t<decltype(v.error())>>)
      return ::fn::detail::_tagged_join_apply<detail::_joining_optional_recovery_tag<::fn::optional, T>>(FWD(v).error(),
                                                                                                         FWD(fn));
    else {
      using result = ::std::remove_cvref_t<typename detail::_apply_result<Fn &&, decltype(FWD(v).error())>::type>;
      if constexpr (::std::is_same_v<result, type>)
        return ::fn::detail::_apply(FWD(fn), FWD(v).error());
      else {
        auto t = ::fn::detail::_apply(FWD(fn), FWD(v).error());
        if (t.has_value()) {
          if constexpr (not empty_copack<typename result::value_type>)
            return type{::std::in_place, ::std::move(t).value()};
          else
            ::pfn::unreachable(); // LCOV_EXCL_LINE
        } else
          return type{::std::nullopt};
      }
    }
  }
};

} // namespace LIBFN_VERSION
} // namespace fn

// ---------- BEGIN fn/detail/macro_end.hpp ----------
// Deliberately no include guard: see fn/detail/macro_begin.hpp.

#undef FWD // NOSONAR cpp:S959 paired with the define in macro_begin.hpp
#pragma pop_macro("FWD")

#undef DEDUCED_RETURN // NOSONAR cpp:S959 paired with the define in macro_begin.hpp
#pragma pop_macro("DEDUCED_RETURN")
// ---------- END fn/detail/macro_end.hpp ----------

// ---------- RESUME fn/or_else.hpp ----------

#endif // INCLUDE_FN_OR_ELSE
// ---------- END fn/or_else.hpp ----------

// ---------- BEGIN fn/recover.hpp ----------
#ifndef INCLUDE_FN_RECOVER
#define INCLUDE_FN_RECOVER

// ---------- RESUME fn/recover.hpp ----------

// ---------- RESUME fn/recover.hpp ----------

// ---------- RESUME fn/recover.hpp ----------

// ---------- RESUME fn/recover.hpp ----------

// ---------- BEGIN fn/detail/macro_begin.hpp ----------
// Deliberately no include guard: this header and fn/detail/macro_end.hpp bracket the section of a
// header that uses the macros below; push_macro/pop_macro make the bracketing safe under nesting
// and preserve any prior user definition.

#pragma push_macro("FWD")
#undef FWD // NOSONAR cpp:S959 saved by push_macro above

// This FWD macro is a functional equivalent to std::forward<decltype(v)>(v),
// but it saves compilation time (and typing) when used frequently.
#define FWD(...) static_cast<decltype(__VA_ARGS__) &&>(__VA_ARGS__)

#pragma push_macro("DEDUCED_RETURN")
#undef DEDUCED_RETURN // NOSONAR cpp:S959 saved by push_macro above

// Spell a function's deduced return type explicitly on MSVC only. MSVC mis-resolves a deduced
// (`auto`/`decltype(auto)`) return whose type derives from a body-local alias, leaking it as an
// opaque dependent type; an explicit trailing return type is the fix. Every other compiler keeps
// `decltype(auto)` — the natural spelling — which by construction deduces `decltype(EXPR)` on
// `return EXPR;`, so the two are the same type and this is a no-op off MSVC.
//
// Confining `decltype(EXPR)` to MSVC also keeps it off clang <= 20, which in C++23 substitutes a
// non-viable constrained overload's trailing return type BEFORE its requires-clause rejects it
// (fixed clang 21), so the explicit form would fail to compile instead of removing the non-viable
// function from the overload set.
#ifndef _MSC_VER
#define DEDUCED_RETURN(...) decltype(auto)
#else
#define DEDUCED_RETURN(...) decltype(__VA_ARGS__)
#endif
// ---------- END fn/detail/macro_begin.hpp ----------

// ---------- RESUME fn/recover.hpp ----------

namespace fn {
inline namespace LIBFN_VERSION {
/**
 * @brief Checks if the monadic type can be used with the `recover` operation
 *
 * @tparam Fn The function to map the dead state into a value
 * @tparam V The monadic type
 */
// The recovered value builds the RESULT, not merely its value type: for an `optional<T&>` those
// differ - the value type is the referent, which a prvalue can construct, but the result binds a
// reference to it, which a prvalue cannot. The success branch carries the existing value over, so
// that must survive the trip too.
template <typename Fn, typename V>
concept applicable_recover //
    = (some_expected_non_void<V> && requires(Fn &&fn, V &&v) {
        {
          ::fn::apply(FWD(fn), FWD(v).error())
        } -> ::std::convertible_to<typename ::std::remove_cvref_t<V>::value_type>;
        requires ::std::is_constructible_v<::std::remove_cvref_t<V>, ::std::in_place_t,
                                           decltype(::fn::apply(FWD(fn), FWD(v).error()))>;
        requires detail::_relocatable_value<V>;
      }) || (some_expected_void<V> && requires(Fn &&fn, V &&v) {
        { ::fn::apply(FWD(fn), FWD(v).error()) } -> ::std::same_as<void>;
      }) || (some_optional<V> && requires(Fn &&fn, V &&v) {
        { ::fn::apply(FWD(fn)) } -> ::std::convertible_to<typename ::std::remove_cvref_t<V>::value_type>;
        requires ::std::is_constructible_v<::std::remove_cvref_t<V>, ::std::in_place_t, decltype(::fn::apply(FWD(fn)))>;
        requires detail::_relocatable_value<V>;
      });

/**
 * @brief Intercept the failure and force a transition back to the success state
 *
 * The dual of `fail`. On `expected` the callback maps the error into the operand's existing value
 * type, never widening it; where the value type is `void`, the callback observes the error and
 * must return `void`. On `optional` the callback is invoked with no arguments - the empty state
 * carries no error value. Rejected on `choice` and `just`, which have no failure to recover from;
 * on the identity `expected` the operand passes through and the callback is never instantiated.
 *
 * Use through the `fn::recover` nielbloid.
 */
constexpr inline struct recover_t final {
  /**
   * @brief Intercept the failure and force a transition back to the success state
   * @param fn The function to produce the replacement value - from the error on `expected`, from
   *        no arguments on `optional`
   * @return A functor that will recover the monadic type
   */
  [[nodiscard]] constexpr auto operator()(auto &&fn) const noexcept(noexcept(functor<recover_t, decltype(fn)>{FWD(fn)}))
      -> functor<recover_t, decltype(fn)> //
  {
    return {FWD(fn)};
  }

  struct apply;
} recover = {}; ///< Supplies a value for the dead state: `x | recover(f)`

struct recover_t::apply final {
  /**
   * @brief Recovers the operand: an error maps into a value, an existing value carries over
   *
   * @param v The monad
   * @param fn The function to map the error into the value
   * @return An `expected` of the same type, holding a value
   */
  template <some_expected_non_void V, typename Fn>
  [[nodiscard]] constexpr auto operator()(V &&v, Fn &&fn) const //
      noexcept(
          ::fn::is_nothrow_applicable_v<Fn, decltype(FWD(v).error())>
          && ::std::is_nothrow_constructible_v<::std::remove_cvref_t<V>, ::std::in_place_t, decltype(FWD(v).value())>
          && ::std::is_nothrow_constructible_v<::std::remove_cvref_t<V>, ::std::in_place_t,
                                               ::fn::apply_result_t<Fn, decltype(FWD(v).error())>>)
          -> ::std::remove_cvref_t<V>
    requires(not some_identity<V>) && applicable_recover<Fn &&, V &&>
  {
    using type = ::std::remove_cvref_t<V>;
    if (v.has_value()) {
      return type{::std::in_place, FWD(v).value()};
    }
    return type{::std::in_place, ::fn::apply(FWD(fn), FWD(v).error())};
  }

  template <some_expected_void V, typename Fn>
  [[nodiscard]] constexpr auto operator()(V &&v, Fn &&fn) const //
      noexcept(::fn::is_nothrow_applicable_v<Fn, decltype(FWD(v).error())>
               && ::std::is_nothrow_constructible_v<::std::remove_cvref_t<V>, ::std::in_place_t>)
          -> ::std::remove_cvref_t<V>
    requires(not some_identity<V>) && applicable_recover<Fn &&, V &&>
  {
    using type = ::std::remove_cvref_t<V>;
    if (v.has_value()) {
      return type{::std::in_place};
    }
    ::fn::apply(FWD(fn), FWD(v).error()); // side-effects only
    return type{::std::in_place};
  }

  // An identity expected has nothing to recover from - the input passes through and the callback
  // is never instantiated
  template <some_expected V, typename Fn>
  [[nodiscard]] constexpr auto operator()(V &&v, Fn &&) const noexcept -> V &&
    requires some_identity<V>
  {
    return FWD(v);
  }

  /**
   * @brief Recovers the operand: the empty state is replaced by the callback's value
   *
   * @param v The optional
   * @param fn The function to produce the replacement value, invoked with no arguments
   * @return An `optional` of the same type, holding a value
   */
  template <some_optional V, typename Fn>
  [[nodiscard]] constexpr auto operator()(V &&v, Fn &&fn) const //
      noexcept(
          ::fn::is_nothrow_applicable_v<Fn>
          && ::std::is_nothrow_constructible_v<::std::remove_cvref_t<V>, ::std::in_place_t, decltype(FWD(v).value())>
          && ::std::is_nothrow_constructible_v<::std::remove_cvref_t<V>, ::std::in_place_t, ::fn::apply_result_t<Fn>>)
          -> ::std::remove_cvref_t<V>
    requires applicable_recover<Fn &&, V &&>
  {
    using type = ::std::remove_cvref_t<V>;
    if (v.has_value()) {
      return type{::std::in_place, FWD(v).value()};
    }
    return type{::std::in_place, ::fn::apply(FWD(fn))};
  }
};

} // namespace LIBFN_VERSION
} // namespace fn

// ---------- BEGIN fn/detail/macro_end.hpp ----------
// Deliberately no include guard: see fn/detail/macro_begin.hpp.

#undef FWD // NOSONAR cpp:S959 paired with the define in macro_begin.hpp
#pragma pop_macro("FWD")

#undef DEDUCED_RETURN // NOSONAR cpp:S959 paired with the define in macro_begin.hpp
#pragma pop_macro("DEDUCED_RETURN")
// ---------- END fn/detail/macro_end.hpp ----------

// ---------- RESUME fn/recover.hpp ----------

#endif // INCLUDE_FN_RECOVER
// ---------- END fn/recover.hpp ----------

// ---------- BEGIN fn/transform.hpp ----------
#ifndef INCLUDE_FN_TRANSFORM
#define INCLUDE_FN_TRANSFORM

// ---------- RESUME fn/transform.hpp ----------

// ---------- RESUME fn/transform.hpp ----------

// ---------- RESUME fn/transform.hpp ----------

// ---------- RESUME fn/transform.hpp ----------

// ---------- RESUME fn/transform.hpp ----------

// ---------- RESUME fn/transform.hpp ----------

// ---------- RESUME fn/transform.hpp ----------

// ---------- RESUME fn/transform.hpp ----------

// ---------- BEGIN fn/detail/macro_begin.hpp ----------
// Deliberately no include guard: this header and fn/detail/macro_end.hpp bracket the section of a
// header that uses the macros below; push_macro/pop_macro make the bracketing safe under nesting
// and preserve any prior user definition.

#pragma push_macro("FWD")
#undef FWD // NOSONAR cpp:S959 saved by push_macro above

// This FWD macro is a functional equivalent to std::forward<decltype(v)>(v),
// but it saves compilation time (and typing) when used frequently.
#define FWD(...) static_cast<decltype(__VA_ARGS__) &&>(__VA_ARGS__)

#pragma push_macro("DEDUCED_RETURN")
#undef DEDUCED_RETURN // NOSONAR cpp:S959 saved by push_macro above

// Spell a function's deduced return type explicitly on MSVC only. MSVC mis-resolves a deduced
// (`auto`/`decltype(auto)`) return whose type derives from a body-local alias, leaking it as an
// opaque dependent type; an explicit trailing return type is the fix. Every other compiler keeps
// `decltype(auto)` — the natural spelling — which by construction deduces `decltype(EXPR)` on
// `return EXPR;`, so the two are the same type and this is a no-op off MSVC.
//
// Confining `decltype(EXPR)` to MSVC also keeps it off clang <= 20, which in C++23 substitutes a
// non-viable constrained overload's trailing return type BEFORE its requires-clause rejects it
// (fixed clang 21), so the explicit form would fail to compile instead of removing the non-viable
// function from the overload set.
#ifndef _MSC_VER
#define DEDUCED_RETURN(...) decltype(auto)
#else
#define DEDUCED_RETURN(...) decltype(__VA_ARGS__)
#endif
// ---------- END fn/detail/macro_begin.hpp ----------

// ---------- RESUME fn/transform.hpp ----------

namespace fn {
inline namespace LIBFN_VERSION {
/**
 * @brief Checks if the monadic type can be used with the `transform` operation
 *
 * @tparam Fn The function to execute on the value
 * @tparam V The monadic type
 */
template <typename Fn, typename V>
concept applicable_transform //
    = (some_expected_non_void<V>//
           && (not some_copack<typename ::std::remove_cvref_t<V>::value_type>) && requires(Fn &&fn, V &&v) {
        {
          ::fn::apply(FWD(fn), FWD(v).value())
        } -> convertible_to_expected<typename ::std::remove_cvref_t<decltype(v)>::error_type>;
      }) || (some_expected<V> && some_copack<typename ::std::remove_cvref_t<V>::value_type> && requires(Fn &&fn, V &&v) {
        {
          FWD(v).value().transform(FWD(fn))
        } -> convertible_to_expected<typename ::std::remove_cvref_t<decltype(v)>::error_type>;
      }) || (some_expected_void<V> && requires(Fn &&fn, V &&v) {
        {
          ::fn::apply(FWD(fn))
        } -> convertible_to_expected<typename ::std::remove_cvref_t<decltype(v)>::error_type>;
      }) || (some_optional<V> //
            && (not some_copack<typename ::std::remove_cvref_t<V>::value_type>) && requires(Fn &&fn, V &&v) {
        {
          ::fn::apply(FWD(fn), FWD(v).value())
        } -> convertible_to_optional;
      }) || (some_optional<V> && some_copack<typename ::std::remove_cvref_t<V>::value_type> && requires(Fn &&fn, V &&v) {
        {
          FWD(v).value().transform(FWD(fn))
        } -> convertible_to_optional;
      }) || (some_choice<V> && requires(Fn &&fn, V &&v) {
        {
          FWD(v).transform(FWD(fn))
        } -> convertible_to_choice;
      }) || (some_just<V> && requires(Fn &&fn, V &&v) {
        {
          FWD(v).transform(FWD(fn))
        } -> same_kind<V>;
      });

namespace detail {
// A copack result of a just's transform is guaranteed a mandate error as just<copack<...>> - the
// verb instead promotes it to the carrier which means exactly that: the choice over the same
// alternatives. Verb-level only, along the canonical isomorphism; the member stays uncoupled.
template <typename T> struct _promoted_choice;
template <typename... Ts> struct _promoted_choice<::fn::copack<Ts...>> {
  using type = ::fn::choice<Ts...>;
};
template <typename Fn, typename... V>
using _promote_t = typename _promoted_choice<::std::remove_cvref_t<typename _apply_result<Fn, V...>::type>>::type;
} // namespace detail

/**
 * @brief Checks if `transform` of a `just` operand promotes the callable's copack result to the
 *        choice over the same alternatives
 *
 * @tparam Fn The function to execute on the value
 * @tparam V The just operand
 */
template <typename Fn, typename V>
concept applicable_transform_promote //
    = (some_just<V> && (not ::std::is_void_v<typename ::std::remove_cvref_t<V>::value_type>) && requires(V &&v) {
        typename detail::_apply_result<Fn, decltype(FWD(v).value())>::type;
        requires some_copack<::std::remove_cvref_t<typename detail::_apply_result<Fn, decltype(FWD(v).value())>::type>>;
        requires not empty_copack<
            ::std::remove_cvref_t<typename detail::_apply_result<Fn, decltype(FWD(v).value())>::type>>;
      }) || (some_just<V> && ::std::is_void_v<typename ::std::remove_cvref_t<V>::value_type> && requires {
        typename detail::_apply_result<Fn>::type;
        requires some_copack<::std::remove_cvref_t<typename detail::_apply_result<Fn>::type>>;
        requires not empty_copack<::std::remove_cvref_t<typename detail::_apply_result<Fn>::type>>;
      });

/**
 * @brief Map the value of the monadic type, keeping the carrier's shape
 *
 * The callable's result becomes the new value, in the same carrier family; a bare (non-monadic)
 * callback result belongs here rather than to `and_then`. Over a copack-valued carrier the
 * callable is dispatched per alternative, heterogeneous branch results joining into a normalized
 * copack. In the pipeline form only, a copack result over a `just` operand is promoted to the
 * `choice` over the same alternatives.
 *
 * Use through the `fn::transform` nielbloid.
 */
constexpr inline struct transform_t final {
  /**
   * @brief Map the value of the monadic type, keeping the carrier's shape
   * @param fn The function to execute on the value
   * @return A functor that will execute the function on the value
   */
  [[nodiscard]] constexpr auto operator()(auto &&fn) const
      noexcept(noexcept(functor<transform_t, decltype(fn)>{FWD(fn)})) -> functor<transform_t, decltype(fn)> //
  {
    return {FWD(fn)};
  }

  struct apply;
} transform = {}; ///< Maps the value, staying in the carrier: `x | transform(f)`

struct transform_t::apply final {
  /**
   * @brief Maps the value through the carrier's own `transform` member
   *
   * @param v The monad
   * @param fn The function to apply
   * @return A carrier of the same kind, holding the mapped value
   */
  template <some_monadic_type V, typename Fn>
  [[nodiscard]] constexpr auto operator()(V &&v, Fn &&fn) const noexcept(noexcept(FWD(v).transform(FWD(fn))))
      -> same_kind<V &&> auto
    requires applicable_transform<Fn &&, V &&>
  {
    return FWD(v).transform(FWD(fn));
  }

  // An uninhabited value side leaves no value to map - delegate to the member, which is the
  // identity there and neither invokes nor instantiates the callback. The verb must reach wherever
  // the member does, so this arm mirrors transform_error's over an uninhabited error side.
  template <some_monadic_type V, typename Fn>
  [[nodiscard]] constexpr auto operator()(V &&v, Fn &&fn) const noexcept(noexcept(FWD(v).transform(FWD(fn))))
      -> same_kind<V &&> auto
    requires some_empty_value<V>
  {
    return FWD(v).transform(FWD(fn));
  }

  // The promotion arms: a copack result over a just operand becomes the choice over the same
  // alternatives - verb-level only, along the canonical isomorphism the member's mandate names
  template <some_monadic_type V, typename Fn>
  [[nodiscard]] constexpr auto operator()(V &&v, Fn &&fn) const
      noexcept(noexcept(detail::_promote_t<Fn &&, decltype(FWD(v).value())>{::fn::apply(FWD(fn), FWD(v).value())})) //
      -> some_choice auto
    requires applicable_transform_promote<Fn &&, V &&>
             && (not ::std::is_void_v<typename ::std::remove_cvref_t<V>::value_type>)
  {
    return detail::_promote_t<Fn &&, decltype(FWD(v).value())>{::fn::apply(FWD(fn), FWD(v).value())};
  }

  template <some_monadic_type V, typename Fn>
  [[nodiscard]] constexpr auto operator()(V &&, Fn &&fn) const            //
      noexcept(noexcept(detail::_promote_t<Fn &&>{::fn::apply(FWD(fn))})) //
      -> some_choice auto
    requires applicable_transform_promote<Fn &&, V &&>
             && ::std::is_void_v<typename ::std::remove_cvref_t<V>::value_type>
  {
    return detail::_promote_t<Fn &&>{::fn::apply(FWD(fn))};
  }
};

} // namespace LIBFN_VERSION
} // namespace fn

// ---------- BEGIN fn/detail/macro_end.hpp ----------
// Deliberately no include guard: see fn/detail/macro_begin.hpp.

#undef FWD // NOSONAR cpp:S959 paired with the define in macro_begin.hpp
#pragma pop_macro("FWD")

#undef DEDUCED_RETURN // NOSONAR cpp:S959 paired with the define in macro_begin.hpp
#pragma pop_macro("DEDUCED_RETURN")
// ---------- END fn/detail/macro_end.hpp ----------

// ---------- RESUME fn/transform.hpp ----------

#endif // INCLUDE_FN_TRANSFORM
// ---------- END fn/transform.hpp ----------

// ---------- BEGIN fn/transform_error.hpp ----------
#ifndef INCLUDE_FN_TRANSFORM_ERROR
#define INCLUDE_FN_TRANSFORM_ERROR

// ---------- RESUME fn/transform_error.hpp ----------

// ---------- RESUME fn/transform_error.hpp ----------

// ---------- RESUME fn/transform_error.hpp ----------

// ---------- RESUME fn/transform_error.hpp ----------

// ---------- BEGIN fn/detail/macro_begin.hpp ----------
// Deliberately no include guard: this header and fn/detail/macro_end.hpp bracket the section of a
// header that uses the macros below; push_macro/pop_macro make the bracketing safe under nesting
// and preserve any prior user definition.

#pragma push_macro("FWD")
#undef FWD // NOSONAR cpp:S959 saved by push_macro above

// This FWD macro is a functional equivalent to std::forward<decltype(v)>(v),
// but it saves compilation time (and typing) when used frequently.
#define FWD(...) static_cast<decltype(__VA_ARGS__) &&>(__VA_ARGS__)

#pragma push_macro("DEDUCED_RETURN")
#undef DEDUCED_RETURN // NOSONAR cpp:S959 saved by push_macro above

// Spell a function's deduced return type explicitly on MSVC only. MSVC mis-resolves a deduced
// (`auto`/`decltype(auto)`) return whose type derives from a body-local alias, leaking it as an
// opaque dependent type; an explicit trailing return type is the fix. Every other compiler keeps
// `decltype(auto)` — the natural spelling — which by construction deduces `decltype(EXPR)` on
// `return EXPR;`, so the two are the same type and this is a no-op off MSVC.
//
// Confining `decltype(EXPR)` to MSVC also keeps it off clang <= 20, which in C++23 substitutes a
// non-viable constrained overload's trailing return type BEFORE its requires-clause rejects it
// (fixed clang 21), so the explicit form would fail to compile instead of removing the non-viable
// function from the overload set.
#ifndef _MSC_VER
#define DEDUCED_RETURN(...) decltype(auto)
#else
#define DEDUCED_RETURN(...) decltype(__VA_ARGS__)
#endif
// ---------- END fn/detail/macro_begin.hpp ----------

// ---------- RESUME fn/transform_error.hpp ----------

namespace fn {
inline namespace LIBFN_VERSION {
/**
 * @brief Checks if the monadic type can be used with the `transform_error` operation
 *
 * @tparam Fn The function to execute on the error
 * @tparam V The monadic type
 */
template <typename Fn, typename V>
concept applicable_transform_error //
    = (some_expected<V> && (not some_copack<typename ::std::remove_cvref_t<V>::error_type>) && requires(Fn &&fn, V &&v) {
        { ::fn::apply(FWD(fn), FWD(v).error()) } -> convertible_to_unexpected;
      }) || (some_expected<V> && some_copack<typename ::std::remove_cvref_t<V>::error_type> && requires(Fn &&fn, V &&v) {
        {
          FWD(v).error().transform(FWD(fn))
        } -> convertible_to_expected<typename ::std::remove_cvref_t<decltype(v)>::error_type>;
      });

/**
 * @brief Map the error of the `expected`, keeping the carrier's shape
 *
 * The operation that narrows a graded error set: over a graded (copack) error side the matching is
 * exhaustive, so the branches may map diverse alternatives into one common type - the grade
 * collapses to its singular copack - or into a narrower copack. Rejected on `optional`, which has
 * no error value to map; on the identity `expected` it is vacuous - well-formed, with the callback
 * neither invoked nor instantiated.
 *
 * Use through the `fn::transform_error` nielbloid.
 */
constexpr inline struct transform_error_t final {
  /**
   * @brief Map the error of the `expected`, keeping the carrier's shape
   * @param fn The function to execute on the error
   * @return A functor that will execute the function on the error
   */
  [[nodiscard]] constexpr auto operator()(auto &&fn) const
      noexcept(noexcept(functor<transform_error_t, decltype(fn)>{FWD(fn)}))
          -> functor<transform_error_t, decltype(fn)> //
  {
    return {FWD(fn)};
  }

  struct apply;
} transform_error = {}; ///< Maps the error, staying in the carrier: `x | transform_error(f)`

struct transform_error_t::apply final {
  /**
   * @brief Maps the error through the carrier's own `transform_error` member
   *
   * @param v The monad
   * @param fn The function to apply
   * @return An `expected` with the same value side and the mapped error side
   */
  template <some_expected V, typename Fn>
  [[nodiscard]] constexpr auto operator()(V &&v, Fn &&fn) const noexcept(noexcept(FWD(v).transform_error(FWD(fn))))
      -> same_value_kind<V &&> auto
    requires(not some_identity<V>) && applicable_transform_error<Fn &&, V &&>
  {
    return FWD(v).transform_error(FWD(fn));
  }

  // An identity expected's error side is uninhabited - delegate to the vacuous member, which
  // accepts any callback and never instantiates it
  template <some_expected V, typename Fn>
  [[nodiscard]] constexpr auto operator()(V &&v, Fn &&fn) const noexcept(noexcept(FWD(v).transform_error(FWD(fn))))
      -> same_value_kind<V &&> auto
    requires some_identity<V>
  {
    return FWD(v).transform_error(FWD(fn));
  }
};

} // namespace LIBFN_VERSION
} // namespace fn

// ---------- BEGIN fn/detail/macro_end.hpp ----------
// Deliberately no include guard: see fn/detail/macro_begin.hpp.

#undef FWD // NOSONAR cpp:S959 paired with the define in macro_begin.hpp
#pragma pop_macro("FWD")

#undef DEDUCED_RETURN // NOSONAR cpp:S959 paired with the define in macro_begin.hpp
#pragma pop_macro("DEDUCED_RETURN")
// ---------- END fn/detail/macro_end.hpp ----------

// ---------- RESUME fn/transform_error.hpp ----------

#endif // INCLUDE_FN_TRANSFORM_ERROR
// ---------- END fn/transform_error.hpp ----------

// ---------- BEGIN fn/value_or.hpp ----------
#ifndef INCLUDE_FN_VALUE_OR
#define INCLUDE_FN_VALUE_OR

// ---------- RESUME fn/value_or.hpp ----------

// ---------- RESUME fn/value_or.hpp ----------

// ---------- RESUME fn/value_or.hpp ----------

// ---------- BEGIN fn/detail/macro_begin.hpp ----------
// Deliberately no include guard: this header and fn/detail/macro_end.hpp bracket the section of a
// header that uses the macros below; push_macro/pop_macro make the bracketing safe under nesting
// and preserve any prior user definition.

#pragma push_macro("FWD")
#undef FWD // NOSONAR cpp:S959 saved by push_macro above

// This FWD macro is a functional equivalent to std::forward<decltype(v)>(v),
// but it saves compilation time (and typing) when used frequently.
#define FWD(...) static_cast<decltype(__VA_ARGS__) &&>(__VA_ARGS__)

#pragma push_macro("DEDUCED_RETURN")
#undef DEDUCED_RETURN // NOSONAR cpp:S959 saved by push_macro above

// Spell a function's deduced return type explicitly on MSVC only. MSVC mis-resolves a deduced
// (`auto`/`decltype(auto)`) return whose type derives from a body-local alias, leaking it as an
// opaque dependent type; an explicit trailing return type is the fix. Every other compiler keeps
// `decltype(auto)` — the natural spelling — which by construction deduces `decltype(EXPR)` on
// `return EXPR;`, so the two are the same type and this is a no-op off MSVC.
//
// Confining `decltype(EXPR)` to MSVC also keeps it off clang <= 20, which in C++23 substitutes a
// non-viable constrained overload's trailing return type BEFORE its requires-clause rejects it
// (fixed clang 21), so the explicit form would fail to compile instead of removing the non-viable
// function from the overload set.
#ifndef _MSC_VER
#define DEDUCED_RETURN(...) decltype(auto)
#else
#define DEDUCED_RETURN(...) decltype(__VA_ARGS__)
#endif
// ---------- END fn/detail/macro_begin.hpp ----------

// ---------- RESUME fn/value_or.hpp ----------

namespace fn {
inline namespace LIBFN_VERSION {
/**
 * @brief Checks if the monadic type can be used with the pipeline `value_or` operation
 *
 * @tparam V The monadic type
 * @tparam Args Arguments the fallback value is built from
 */
// The fallback builds the RESULT, not merely its value type: for an `optional<T&>` those differ -
// the value type is the referent, which a prvalue can construct, but the result binds a reference to
// it, which a prvalue cannot. And the existing value is carried over when there is one, so it must
// be able to survive that: an immovable value type would otherwise satisfy this and then fail inside
// the body. A void value is the degenerate case of both: `value_or()` substitutes the empty value,
// so the arguments must be none at all, and there is nothing to carry over.
template <typename V, typename... Args>
concept applicable_value_or                                                                                         //
    = (some_expected_non_void<V> && ::std::is_constructible_v<::std::remove_cvref_t<V>, ::std::in_place_t, Args...> //
       && detail::_relocatable_value<V>)
      || (some_expected_void<V> && ::std::is_constructible_v<::std::remove_cvref_t<V>, ::std::in_place_t, Args...>)
      || (some_optional<V> && ::std::is_constructible_v<::std::remove_cvref_t<V>, ::std::in_place_t, Args...>
          && detail::_relocatable_value<V>);

/**
 * @brief Supply a fallback for the failure state, keeping the carrier
 *
 * Unlike the member `value_or`, which eliminates the carrier and yields a value, the pipeline form
 * returns the carrier engaged with either its own value or a fallback built in place from the
 * arguments. Where the value type is `void`, `value_or()` takes no arguments at all. Rejected on
 * `choice` and `just`, which can never lack a value; on the identity `expected` the fallback stays
 * constrained yet dead - generic code compiles, the branch is never taken.
 *
 * Use through the `fn::value_or` nielbloid.
 */
constexpr inline struct value_or_t final {
  /**
   * @brief Supply a fallback for the failure state, keeping the carrier
   * @param args Arguments the fallback value is built from, in place
   * @return A functor that will substitute the fallback where the value is missing
   */
  template <typename... Args>
  [[nodiscard]] constexpr auto operator()(Args &&...args) const
      noexcept(noexcept(functor<value_or_t, Args &&...>{FWD(args)...})) -> functor<value_or_t, Args &&...> //
  {
    return {FWD(args)...};
  }

  struct apply;
} value_or = {}; ///< Substitutes a fallback for the dead state: `x | value_or(v)`

struct value_or_t::apply final {
  /**
   * @brief Returns the operand engaged with its own value, or the fallback built from the arguments
   *
   * @param v The monad
   * @param args Arguments the fallback value is built from, in place
   * @return A carrier of the same type, holding a value
   */
  // The fallback is built inside, so its construction is weighed here rather than propagated: the
  // callable or_else receives is a lambda, which cannot be named in this specification.
  // An identity expected is deliberately not excluded with choice and just: its fallback stays
  // constrained yet dead, the delegated member or_else being vacuous.
  template <some_monadic_type V, typename... Args>
  [[nodiscard]] constexpr auto operator()(V &&v, Args &&...args) const //
      noexcept(::std::is_nothrow_constructible_v<::std::remove_cvref_t<V>, ::std::in_place_t, Args...>
               && detail::_nothrow_carry_value<::std::remove_cvref_t<V>, V>) -> ::std::remove_cvref_t<V>
    requires(not some_choice<V>) && (not some_just<V>) && applicable_value_or<V &&, Args...>
  {
    using type = ::std::remove_cvref_t<V>;
    return FWD(v).or_else([&args...](auto &&...) -> type { return type{::std::in_place, FWD(args)...}; });
  }
};

} // namespace LIBFN_VERSION
} // namespace fn

// ---------- BEGIN fn/detail/macro_end.hpp ----------
// Deliberately no include guard: see fn/detail/macro_begin.hpp.

#undef FWD // NOSONAR cpp:S959 paired with the define in macro_begin.hpp
#pragma pop_macro("FWD")

#undef DEDUCED_RETURN // NOSONAR cpp:S959 paired with the define in macro_begin.hpp
#pragma pop_macro("DEDUCED_RETURN")
// ---------- END fn/detail/macro_end.hpp ----------

// ---------- RESUME fn/value_or.hpp ----------

#endif // INCLUDE_FN_VALUE_OR
// ---------- END fn/value_or.hpp ----------

#endif // INCLUDE_LIBFN_AMALGAMATED
