diff --git a/src/entt/entity/fwd.hpp b/src/entt/entity/fwd.hpp index 771cd13f8..ce33f35db 100644 --- a/src/entt/entity/fwd.hpp +++ b/src/entt/entity/fwd.hpp @@ -28,46 +28,8 @@ class basic_sparse_set; template, typename = void> class basic_storage; -template -class sigh_mixin; - -/** - * @brief Provides a common way to define storage types. - * @tparam Type Storage value type. - * @tparam Entity A valid entity type. - * @tparam Allocator Type of allocator used to manage memory and elements. - */ -template, typename = void> -struct storage_type { - /*! @brief Type-to-storage conversion result. */ - using type = sigh_mixin>; -}; - -/** - * @brief Helper type. - * @tparam Args Arguments to forward. - */ -template -using storage_type_t = typename storage_type::type; - -/** - * Type-to-storage conversion utility that preserves constness. - * @tparam Type Storage value type, eventually const. - * @tparam Entity A valid entity type. - * @tparam Allocator Type of allocator used to manage memory and elements. - */ -template>> -struct storage_for { - /*! @brief Type-to-storage conversion result. */ - using type = constness_as_t, Entity, Allocator>, Type>; -}; - -/** - * @brief Helper type. - * @tparam Args Arguments to forward. - */ -template -using storage_for_t = typename storage_for::type; +template +class basic_sigh_mixin; template> class basic_registry; @@ -99,6 +61,67 @@ class basic_snapshot_loader; template class basic_continuous_loader; +/*! @brief Alias declaration for the most common use case. */ +using sparse_set = basic_sparse_set<>; + +/** + * @brief Alias declaration for the most common use case. + * @tparam Type Type of objects assigned to the entities. + */ +template +using storage = basic_storage; + +/** + * @brief Alias declaration for the most common use case. + * @tparam Type Underlying storage type. + */ +template +using sigh_mixin = basic_sigh_mixin>; + +/*! @brief Alias declaration for the most common use case. */ +using registry = basic_registry<>; + +/*! @brief Alias declaration for the most common use case. */ +using observer = basic_observer; + +/*! @brief Alias declaration for the most common use case. */ +using organizer = basic_organizer; + +/*! @brief Alias declaration for the most common use case. */ +using handle = basic_handle; + +/*! @brief Alias declaration for the most common use case. */ +using const_handle = basic_handle; + +/** + * @brief Alias declaration for the most common use case. + * @tparam Args Other template parameters. + */ +template +using handle_view = basic_handle; + +/** + * @brief Alias declaration for the most common use case. + * @tparam Args Other template parameters. + */ +template +using const_handle_view = basic_handle; + +/*! @brief Alias declaration for the most common use case. */ +using snapshot = basic_snapshot; + +/*! @brief Alias declaration for the most common use case. */ +using snapshot_loader = basic_snapshot_loader; + +/*! @brief Alias declaration for the most common use case. */ +using continuous_loader = basic_continuous_loader; + +/*! @brief Alias declaration for the most common use case. */ +using runtime_view = basic_runtime_view; + +/*! @brief Alias declaration for the most common use case. */ +using const_runtime_view = basic_runtime_view; + /** * @brief Alias for exclusion lists. * @tparam Type List of types. @@ -183,53 +206,43 @@ struct type_list_transform, Op> { using type = owned_t::type...>; }; -/*! @brief Alias declaration for the most common use case. */ -using sparse_set = basic_sparse_set<>; - /** - * @brief Alias declaration for the most common use case. - * @tparam Type Type of objects assigned to the entities. + * @brief Provides a common way to define storage types. + * @tparam Type Storage value type. + * @tparam Entity A valid entity type. + * @tparam Allocator Type of allocator used to manage memory and elements. */ -template -using storage = basic_storage; - -/*! @brief Alias declaration for the most common use case. */ -using registry = basic_registry<>; - -/*! @brief Alias declaration for the most common use case. */ -using observer = basic_observer; - -/*! @brief Alias declaration for the most common use case. */ -using organizer = basic_organizer; - -/*! @brief Alias declaration for the most common use case. */ -using handle = basic_handle; - -/*! @brief Alias declaration for the most common use case. */ -using const_handle = basic_handle; +template, typename = void> +struct storage_type { + /*! @brief Type-to-storage conversion result. */ + using type = sigh_mixin>; +}; /** - * @brief Alias declaration for the most common use case. - * @tparam Args Other template parameters. + * @brief Helper type. + * @tparam Args Arguments to forward. */ template -using handle_view = basic_handle; +using storage_type_t = typename storage_type::type; /** - * @brief Alias declaration for the most common use case. - * @tparam Args Other template parameters. + * Type-to-storage conversion utility that preserves constness. + * @tparam Type Storage value type, eventually const. + * @tparam Entity A valid entity type. + * @tparam Allocator Type of allocator used to manage memory and elements. + */ +template>> +struct storage_for { + /*! @brief Type-to-storage conversion result. */ + using type = constness_as_t, Entity, Allocator>, Type>; +}; + +/** + * @brief Helper type. + * @tparam Args Arguments to forward. */ template -using const_handle_view = basic_handle; - -/*! @brief Alias declaration for the most common use case. */ -using snapshot = basic_snapshot; - -/*! @brief Alias declaration for the most common use case. */ -using snapshot_loader = basic_snapshot_loader; - -/*! @brief Alias declaration for the most common use case. */ -using continuous_loader = basic_continuous_loader; +using storage_for_t = typename storage_for::type; /** * @brief Alias declaration for the most common use case. @@ -239,12 +252,6 @@ using continuous_loader = basic_continuous_loader; template> using view = basic_view, type_list_transform_t>; -/*! @brief Alias declaration for the most common use case. */ -using runtime_view = basic_runtime_view; - -/*! @brief Alias declaration for the most common use case. */ -using const_runtime_view = basic_runtime_view; - /** * @brief Alias declaration for the most common use case. * @tparam Owned Types of storage _owned_ by the group. diff --git a/src/entt/entity/mixin.hpp b/src/entt/entity/mixin.hpp index 7a7aa92c7..49233f89e 100644 --- a/src/entt/entity/mixin.hpp +++ b/src/entt/entity/mixin.hpp @@ -22,18 +22,23 @@ namespace entt { * * This applies to all signals made available. * - * @tparam Type The type of the underlying storage. + * @tparam Type Underlying storage type. + * @tparam Registry Basic registry type. */ -template -class sigh_mixin final: public Type { +template +class basic_sigh_mixin final: public Type { using underlying_type = Type; + using owner_type = Registry; + using basic_registry_type = basic_registry; - using sigh_type = sigh; + using sigh_type = sigh; using underlying_iterator = typename underlying_type::base_type::basic_iterator; - basic_registry_type &owner_or_assert() const noexcept { + static_assert(std::is_base_of_v, "Invalid registry type"); + + owner_type &owner_or_assert() const noexcept { ENTT_ASSERT(owner != nullptr, "Invalid pointer to registry"); - return *owner; + return static_cast(*owner); } void pop(underlying_iterator first, underlying_iterator last) final { @@ -85,17 +90,17 @@ public: /*! @brief Underlying entity identifier. */ using entity_type = typename underlying_type::entity_type; /*! @brief Expected registry type. */ - using registry_type = basic_registry_type; + using registry_type = owner_type; /*! @brief Default constructor. */ - sigh_mixin() - : sigh_mixin{allocator_type{}} {} + basic_sigh_mixin() + : basic_sigh_mixin{allocator_type{}} {} /** * @brief Constructs an empty storage with a given allocator. * @param allocator The allocator to use. */ - explicit sigh_mixin(const allocator_type &allocator) + explicit basic_sigh_mixin(const allocator_type &allocator) : underlying_type{allocator}, owner{}, construction{allocator}, @@ -106,7 +111,7 @@ public: * @brief Move constructor. * @param other The instance to move from. */ - sigh_mixin(sigh_mixin &&other) noexcept + basic_sigh_mixin(basic_sigh_mixin &&other) noexcept : underlying_type{std::move(other)}, owner{other.owner}, construction{std::move(other.construction)}, @@ -118,7 +123,7 @@ public: * @param other The instance to move from. * @param allocator The allocator to use. */ - sigh_mixin(sigh_mixin &&other, const allocator_type &allocator) noexcept + basic_sigh_mixin(basic_sigh_mixin &&other, const allocator_type &allocator) noexcept : underlying_type{std::move(other), allocator}, owner{other.owner}, construction{std::move(other.construction), allocator}, @@ -130,7 +135,7 @@ public: * @param other The instance to move from. * @return This storage. */ - sigh_mixin &operator=(sigh_mixin &&other) noexcept { + basic_sigh_mixin &operator=(basic_sigh_mixin &&other) noexcept { underlying_type::operator=(std::move(other)); owner = other.owner; construction = std::move(other.construction); @@ -143,7 +148,7 @@ public: * @brief Exchanges the contents with those of a given storage. * @param other Storage to exchange the content with. */ - void swap(sigh_mixin &other) { + void swap(basic_sigh_mixin &other) { using std::swap; underlying_type::swap(other); swap(owner, other.owner); diff --git a/test/entt/entity/sigh_mixin.cpp b/test/entt/entity/sigh_mixin.cpp index 6f81ba492..5de9f9191 100644 --- a/test/entt/entity/sigh_mixin.cpp +++ b/test/entt/entity/sigh_mixin.cpp @@ -10,6 +10,7 @@ #include #include #include +#include "../common/custom_entity.h" #include "../common/non_default_constructible.h" #include "../common/pointer_stable.h" #include "../common/throwing_allocator.hpp" @@ -20,6 +21,13 @@ void listener(std::size_t &counter, Registry &, typename Registry::entity_type) ++counter; } +struct custom_registry: entt::basic_registry {}; + +template +struct entt::storage_type { + using type = entt::basic_sigh_mixin, custom_registry>; +}; + template struct SighMixin: testing::Test { using type = Type; @@ -414,6 +422,30 @@ TYPED_TEST(SighMixin, Swap) { ASSERT_EQ(on_destroy, 3u); } +TYPED_TEST(SighMixin, CustomRegistry) { + using value_type = typename TestFixture::type; + entt::basic_sigh_mixin, custom_registry> pool; + custom_registry registry; + + std::size_t on_construct{}; + std::size_t on_destroy{}; + + pool.bind(entt::forward_as_any(static_cast &>(registry))); + pool.on_construct().template connect<&listener>(on_construct); + pool.on_destroy().template connect<&listener>(on_destroy); + + pool.emplace(test::custom_entity{3}); + pool.emplace(test::custom_entity{42}); + + ASSERT_EQ(on_construct, 2u); + ASSERT_EQ(on_destroy, 0u); + + pool.clear(); + + ASSERT_EQ(on_construct, 2u); + ASSERT_EQ(on_destroy, 2u); +} + TYPED_TEST(SighMixin, CustomAllocator) { using value_type = typename TestFixture::type; test::throwing_allocator allocator{};