diff options
Diffstat (limited to 'asl/base/meta.hpp')
-rw-r--r-- | asl/base/meta.hpp | 42 |
1 files changed, 22 insertions, 20 deletions
diff --git a/asl/base/meta.hpp b/asl/base/meta.hpp index 06c7c59..8376d5c 100644 --- a/asl/base/meta.hpp +++ b/asl/base/meta.hpp @@ -90,6 +90,9 @@ template<typename T> concept moveable = move_constructible<T> && move_assignable template<typename To, typename From> concept convertible_from = __is_convertible(From, To); +template<typename From, typename To> +concept convertible_to = __is_convertible(From, To); + template<typename Derived, class Base> concept derived_from = __is_class(Derived) && __is_class(Base) && convertible_from<const volatile Base*, const volatile Derived*>; @@ -244,29 +247,28 @@ concept has_niche = constructible_from<T, niche_t> && equality_comparable_with<T template<typename T> concept is_niche = same_as<un_cvref_t<T>, niche_t>; -template<typename T, typename U> -concept _derefs_with_indirection_as = requires(T& t) +template<typename From, typename To> +concept _dereferenceable_as_convertible = requires(From& t) { - *t; - requires convertible_from<U&, decltype(*t)>; + { *t } -> convertible_to<To&>; }; -template<typename T, typename U> -concept _derefs_reference_as = is_ref<T> && convertible_from<U&, T>; - -template<typename T, typename U> -concept _derefs_value_as = !is_ref<T> && convertible_from<U&, T&>; - -template<typename U, _derefs_with_indirection_as<U> T> -constexpr U& deref(T&& t) { return static_cast<U&>(*t); } - -template<typename U, _derefs_reference_as<U> T> -constexpr U& deref(T&& t) { return static_cast<U&>(t); } - -template<typename U, _derefs_value_as<U> T> -constexpr U& deref(T&& t) { return static_cast<U&>(t); } +template<typename From, typename To> +concept derefs_as = is_object<To> && + (convertible_to<un_ref_t<From>&, To&> || _dereferenceable_as_convertible<un_ref_t<From>, To>); -template<typename T, typename U> -concept derefs_as = _derefs_with_indirection_as<T, U> || _derefs_reference_as<T, U> || _derefs_value_as<T, U>; +template<typename To, derefs_as<To> From> +constexpr auto&& deref(From&& from) // NOLINT(*forward*) +{ + if constexpr (_dereferenceable_as_convertible<From, To>) + { + using deref_type = decltype(*declval<From&&>()); + return static_cast<copy_cref_t<deref_type, To>>(*static_cast<From&&>(from)); + } + else + { + return static_cast<copy_cref_t<From&&, To>>(from); + } +} } // namespace asl |