diff options
author | Steven Le Rouzic <steven.lerouzic@gmail.com> | 2025-03-11 23:51:51 +0100 |
---|---|---|
committer | Steven Le Rouzic <steven.lerouzic@gmail.com> | 2025-03-11 23:51:51 +0100 |
commit | af4e29f8c071b089fb46b5d8b964dd2b1fb3f57a (patch) | |
tree | 13d2607d79b54750bca4d7ef11220faa9e4eecc0 /asl | |
parent | 636882316b5191931e144212d93665c10859ac95 (diff) |
Remake deref
Diffstat (limited to 'asl')
-rw-r--r-- | asl/base/meta.hpp | 42 | ||||
-rw-r--r-- | asl/base/meta_tests.cpp | 11 | ||||
-rw-r--r-- | asl/containers/intrusive_list.hpp | 2 | ||||
-rw-r--r-- | asl/types/box.hpp | 17 | ||||
-rw-r--r-- | asl/types/span.hpp | 10 |
5 files changed, 47 insertions, 35 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 diff --git a/asl/base/meta_tests.cpp b/asl/base/meta_tests.cpp index 774f9bc..6c8efab 100644 --- a/asl/base/meta_tests.cpp +++ b/asl/base/meta_tests.cpp @@ -255,16 +255,22 @@ static_assert(asl::is_enum<Enum2>); static_assert(asl::derefs_as<int, int>); static_assert(asl::derefs_as<int*, int>); +static_assert(!asl::derefs_as<const int*, int>); static_assert(asl::derefs_as<int&, int>); +static_assert(!asl::derefs_as<const int&, int>); static_assert(asl::derefs_as<asl::box<int>, int>); static_assert(asl::derefs_as<Derived, Base>); +static_assert(!asl::derefs_as<Base, Derived>); static_assert(asl::derefs_as<Derived*, Base>); static_assert(asl::derefs_as<Derived&, Base>); +static_assert(!asl::derefs_as<Base&, Derived>); static_assert(asl::derefs_as<asl::box<Derived>, Base>); +static_assert(asl::derefs_as<asl::box<Derived>, Derived>); +static_assert(asl::derefs_as<asl::box<Base>, Base>); static void wants_int(int) {} -static void wants_base(Base&) {} +static void wants_base(const Base&) {} static void wants_base_ptr(Base*) {} ASL_TEST(deref) @@ -285,10 +291,11 @@ ASL_TEST(deref) wants_base(asl::deref<Base>(&c)); wants_base(asl::deref<Base>(d)); - wants_base_ptr(&asl::deref<Base>(Derived{})); wants_base_ptr(&asl::deref<Base>(c)); wants_base_ptr(&asl::deref<Base>(&c)); wants_base_ptr(&asl::deref<Base>(d)); + + wants_base(asl::deref<Base>(std::move(d))); } static_assert(asl::same_as<asl::copy_cref_t<int, float>, float>); diff --git a/asl/containers/intrusive_list.hpp b/asl/containers/intrusive_list.hpp index a58bbfd..af11424 100644 --- a/asl/containers/intrusive_list.hpp +++ b/asl/containers/intrusive_list.hpp @@ -19,7 +19,7 @@ struct intrusive_list_node }; template<typename T> -concept is_intrusive_list_node = convertible_from<intrusive_list_node<T>*, T*>; +concept is_intrusive_list_node = derived_from<T, intrusive_list_node<T>>; template<is_intrusive_list_node T> class IntrusiveList diff --git a/asl/types/box.hpp b/asl/types/box.hpp index 6501e3e..bb4e620 100644 --- a/asl/types/box.hpp +++ b/asl/types/box.hpp @@ -76,18 +76,21 @@ public: } } - constexpr T* get() const { return m_ptr; } + constexpr auto* get(this auto&& self) + { + return self.m_ptr; + } - constexpr T& operator*() const + constexpr auto&& operator*(this auto&& self) { - ASL_ASSERT(m_ptr != nullptr); - return *m_ptr; + ASL_ASSERT(self.m_ptr != nullptr); + return std::forward_like<decltype(self)&&>(*self.m_ptr); } - constexpr T* operator->() const + constexpr auto* operator->(this auto&& self) { - ASL_ASSERT(m_ptr != nullptr); - return m_ptr; + ASL_ASSERT(self.m_ptr != nullptr); + return self.m_ptr; } constexpr bool operator==(niche_t) const diff --git a/asl/types/span.hpp b/asl/types/span.hpp index eff6ac7..bb2257a 100644 --- a/asl/types/span.hpp +++ b/asl/types/span.hpp @@ -75,21 +75,21 @@ public: } template<isize_t N> - constexpr span(T (&array)[N]) // NOLINT(*-explicit-conversions) + constexpr span(T (&array)[N]) // NOLINT(*explicit*) requires (kIsDynamic) : m_data{array} , m_size{N} {} template<isize_t N> - constexpr span(T (&array)[N]) // NOLINT(*-explicit-conversions) + constexpr span(T (&array)[N]) // NOLINT(*explicit*) requires (!kIsDynamic) && (N == kSize) : m_data{array} {} template<is_object U, isize_t kOtherSize> constexpr explicit(!kIsDynamic) - span(const span<U, kOtherSize>& other) // NOLINT(*-explicit-conversions) + span(const span<U, kOtherSize>& other) requires ( ( kIsDynamic || @@ -217,7 +217,7 @@ template<is_object T, isize_t kSize> inline span<const byte> as_bytes(span<T, kSize> s) { return span<const byte>( - reinterpret_cast<const byte*>(s.data()), + reinterpret_cast<const byte*>(s.data()), // NOLINT(*-reinterpret-cast) s.size_bytes()); } @@ -226,7 +226,7 @@ inline span<byte> as_mutable_bytes(span<T, kSize> s) requires (!is_const<T>) { return span<byte>( - reinterpret_cast<byte*>(s.data()), + reinterpret_cast<byte*>(s.data()), // NOLINT(*-reinterpret-cast) s.size_bytes()); } |