|
|
@ -39,8 +39,55 @@ namespace exopt::types { namespace optional [[gnu::visibility("internal")]] {
|
|
|
|
class null_optimise<boxed::Box<T> > {
|
|
|
|
class null_optimise<boxed::Box<T> > {
|
|
|
|
using boxed::Box;
|
|
|
|
using boxed::Box;
|
|
|
|
using box_t = Box<T>;
|
|
|
|
using box_t = Box<T>;
|
|
|
|
struct /*XXX: Shouldn't be needed alignas(box_t)*/ invariant : box_t {
|
|
|
|
class /*XXX: Shouldn't be needed alignas(box_t)*/ invariant : box_t {
|
|
|
|
//TODO: See phone notes.
|
|
|
|
//TODO: See phone notes.
|
|
|
|
|
|
|
|
using box_t::UNSAFE;
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
constexpr box_t& operator*() & noexcept { return *static_assert<box_t *>(this); }
|
|
|
|
|
|
|
|
constexpr box_t const& operator*() const& noexcept { return *static_assert<box_t const*>(this); }
|
|
|
|
|
|
|
|
constexpr box_t&& operator*() && noexcept { return std::move(*static_assert<box_t *>(this)); }
|
|
|
|
|
|
|
|
constexpr box_t const&& operator*() const&& noexcept { return std::move(*static_assert<box_t const*>(this)); }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
constexpr static invariant&& back_conv(box_t&& b) noexcept { return static_cast<invariant&&>(b); }
|
|
|
|
|
|
|
|
constexpr static invariant const& back_conv(box_t const& b) noexcept { return static_cast<invariant const&>(b); }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
constexpr static invariant& back_conv(box_t& b) noexcept { return static_cast<invariant&>(b); }
|
|
|
|
|
|
|
|
constexpr static invariant const&& back_conv(box_t const&& b) noexcept { return static_cast<invariant const&&>(b); }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
constexpr invariant(box_t&& m) noexcept
|
|
|
|
|
|
|
|
: box_t(UNSAFE, std::move(std::move(m).as_unique(UNSAFE))) {}
|
|
|
|
|
|
|
|
constexpr invariant(box_t const& m) noexcept
|
|
|
|
|
|
|
|
: box_t(UNSAFE, m) {}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
constexpr invariant(std::unique_ptr<T>&& m) noexcept
|
|
|
|
|
|
|
|
: box_t(UNSAFE, std::move(m)) {}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
constexpr invariant(std::nullptr_t) noexcept
|
|
|
|
|
|
|
|
: box_t(UNSAFE, std::unique_ptr<T> { nullptr } ) {}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
constexpr friend auto operator<=>(invariant const& a, invariant const& b) noexcept { return (*a).as_unsafe_ptr(UNSAFE) <=> (*b).as_unsafe_ptr(UNSAFE); }
|
|
|
|
|
|
|
|
constexpr friend auto operator<=>(invariant const& a, box_t const& b) noexcept { return (*a).as_unsafe_ptr(UNSAFE) <=> b.as_unsafe_ptr(UNSAFE); }
|
|
|
|
|
|
|
|
constexpr friend auto operator<=>(invariant const& a, T const* p) noexcept { return (*a).as_unsafe_ptr(UNSAFE) <=> p; }
|
|
|
|
|
|
|
|
constexpr friend auto operator<=>(invariant const& a, std::nullptr_t) noexcept { return (*a).as_unsafe_ptr(UNSAFE) <=> nullptr; }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
constexpr invariant& operator=(box_t &&) noexcept = delete;
|
|
|
|
|
|
|
|
constexpr invariant& operator=(box_t const&) = delete;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
constexpr invariant& operator=(invariant &&) noexcept = default;
|
|
|
|
|
|
|
|
constexpr invariant& operator=(invariant const&) = default;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
constexpr invariant& operator=(std::nullptr_t)
|
|
|
|
|
|
|
|
{ box_t::as_unique(UNSAFE).reset(); return *this; }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
constexpr invariant& operator=(T* const&& p)
|
|
|
|
|
|
|
|
{ box_t::as_unique(UNSAFE).reset(p); return *this; }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
constexpr invariant(invariant&& m) noexcept
|
|
|
|
|
|
|
|
: invariant( std::move((*std::move(m)).as_unique(UNSAFE)) ) {}
|
|
|
|
|
|
|
|
constexpr invariant(invariant const& m) noexcept
|
|
|
|
|
|
|
|
: box_t(UNSAFE, (*m).as_unique(UNSAFE)) {}
|
|
|
|
|
|
|
|
|
|
|
|
constexpr ~invariant() = default;
|
|
|
|
constexpr ~invariant() = default;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
static_assert(util::shares_layout<invariant, box_t>, "invariant (held_type) does not share layout with viewed type (Box<T>)");
|
|
|
|
static_assert(util::shares_layout<invariant, box_t>, "invariant (held_type) does not share layout with viewed type (Box<T>)");
|
|
|
@ -48,6 +95,16 @@ namespace exopt::types { namespace optional [[gnu::visibility("internal")]] {
|
|
|
|
typedef invariant held_type; // invariant ^: Held internal type.
|
|
|
|
typedef invariant held_type; // invariant ^: Held internal type.
|
|
|
|
using type = box_t; // Box<T>: API seen & operated on type
|
|
|
|
using type = box_t; // Box<T>: API seen & operated on type
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
constexpr static decltype(auto) convert_to_held(type ty) noexcept { return held_type{std::move(ty)}; }
|
|
|
|
|
|
|
|
constexpr static decltype(auto) convert_to_held(type& ty) noexcept { return held_type::back_conv(ty); }
|
|
|
|
|
|
|
|
constexpr static decltype(auto) convert_to_held(type&& ty) noexcept { return held_type::back_conv(std::move(ty)); }
|
|
|
|
|
|
|
|
constexpr static decltype(auto) convert_to_held(type const& ty) noexcept { return held_type::back_conv(ty); }
|
|
|
|
|
|
|
|
constexpr static decltype(auto) convert_to_held(type const&& ty) noexcept { return held_type::back_conv(std::move(ty)); }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
constexpr static type& convert_from_held(held_type& ty) noexcept { return *ty; }
|
|
|
|
|
|
|
|
constexpr static type const&& convert_from_held(held_type const&& ty) noexcept { return std::move(*std::move(ty)); }
|
|
|
|
|
|
|
|
constexpr static type&& convert_from_held(held_type&& ty) noexcept { return std::move(*std::move(ty)); }
|
|
|
|
|
|
|
|
constexpr static type const& convert_from_held(held_type const& ty) noexcept { return *ty; }
|
|
|
|
//TODO: See phone notes.
|
|
|
|
//TODO: See phone notes.
|
|
|
|
|
|
|
|
|
|
|
|
constexpr static inline auto sentinel = nullptr;
|
|
|
|
constexpr static inline auto sentinel = nullptr;
|
|
|
|