Adding polymorphic boxing helpers.

Fortune for libexopt's current commit: Small blessing − 小吉
error-handling
Avril 2 years ago
parent 044006aef0
commit 2d30b3ce85
Signed by: flanchan
GPG Key ID: 284488987C31F630

@ -34,6 +34,8 @@ namespace exopt::types { namespace boxed {
#endif #endif
return std::make_unique<T>(*c); } return std::make_unique<T>(*c); }
template<typename From, typename To>
concept binary_convertible = std::is_convertible_v<From, To> and std::is_convertible_v<To, From>;
template<typename T> template<typename T>
struct Box { struct Box {
@ -102,6 +104,21 @@ namespace exopt::types { namespace boxed {
std::unique_ptr<T> m_ptr; // Unique<T> m_ptr; std::unique_ptr<T> m_ptr; // Unique<T> m_ptr;
}; };
#define _EO_ADD_RV std::add_rvalue_reference_v
template<typename Base, typename T = Base>
constexpr inline bool is_boxable_v = binary_convertible<_EO_ADD_RV<T>, _EO_ADD_RV<Base> > and requires(T&& value) {
typename Box<Base>;
typename Box<Base>::type;
{ std::make_unique<T>(std::move(value)) } -> std::same_as<std::unique_ptr<T>>;
};
template<typename T> concept is_boxable = is_boxable_v<T>;
template<typename T>
constexpr inline bool is_nothrow_boxable_v = is_boxable_v<T> && std::is_nothrow_constructible_v<Box<T>, T>;
#undef _EO_ADD_RV
template<typename T, typename U> requires(requires(T&& o) { static_cast<U&&>(o); }) template<typename T, typename U> requires(requires(T&& o) { static_cast<U&&>(o); })
constexpr Box<U> static_box_cast(Box<T>&& b) noexcept { return Box<U>::from_raw_ptr(static_cast<U*>(b.release())); } constexpr Box<U> static_box_cast(Box<T>&& b) noexcept { return Box<U>::from_raw_ptr(static_cast<U*>(b.release())); }
@ -115,6 +132,21 @@ namespace exopt::types { namespace boxed {
throw; throw;
} }
} //TODO: Overload for `const&` that does the type check *before* the copy allocation. } //TODO: Overload for `const&` that does the type check *before* the copy allocation.
template<typename T, typename R /*XXX: Maybe remove this, and put the requires after the definition, using `auto&& value` instead of `R&& value`*/> requires(std::derived_from<R, T>)
constexpr Box<T> box(R&& value, util::comptime<bool> auto Check = _EO_CONSTANT_VALUE(false)) noexcept(std::is_nothrow_invocable_v< Box<T>::new_dynamic<R, bool(Check)>) //XXX: This seems illegal...
{ return Box<T>::template new_dynamic<R, Check>(std::move(value)); }
template<typename T>
constexpr Box<T> box(std::convertible_to<T> auto&& value) noexcept(std::is_nothrow_constructible_v<Box<T>, std::add_rvalue_reference_v<T>>)
{
/*if constexpr(requires(decltype(value) v) { static_cast<T&&>(std::move(v)); }) {
return Box<T>::template new_dynamic<T>(std::move(value));
} else */return { static_cast<T>(std::move(value)) };
}
template<typename T>
constexpr Box<T> box(T&& value) noexcept(std::is_nothrow_constructible_v<Box<T>, T>)
{ return { std::move(value) }; }
} }
using boxed::Box; using boxed::Box;
} }

Loading…
Cancel
Save