diff --git a/TODO b/TODO index 1221a2f8b..9f216ab42 100644 --- a/TODO +++ b/TODO @@ -12,7 +12,7 @@ DOC: * update entity doc when the storage based model is in place TODO (high prio): -* make component_traits depend on the entity type +* check natvis files (periodically :) * remove the static storage from the const assure in the registry WIP: diff --git a/docs/md/entity.md b/docs/md/entity.md index 16a035eba..58fa8099a 100644 --- a/docs/md/entity.md +++ b/docs/md/entity.md @@ -990,9 +990,9 @@ The non-specialized version of this class contains the following members: * `page_size`: `Type::page_size` if present, `ENTT_PACKED_PAGE` for non-empty types and 0 otherwise. -Where `Type` is any type of component. All properties can be customized by -specializing the above class and defining all its members, or by adding only -those of interest to a component definition: +Where `Type` is any type of component. Properties are customized by specializing +the above class and defining its members, or by adding only those of interest to +a component definition: ```cpp struct transform { @@ -1001,10 +1001,27 @@ struct transform { }; ``` -The `component_traits` class template will take care of correctly extracting the -properties from the supplied type to pass them to the rest of the library.
-In the case of a direct specialization, the class is also _sfinae-friendly_. It -supports single and multi type specializations as well as feature-based ones. +The `component_traits` class template takes care of _extracting_ the properties +from the supplied type.
+Plus, it's _sfinae-friendly_ and also supports feature-based specialization: + +```cpp +template +struct entt::component_traits> { + using type = Type; + static constexpr auto in_place_delete = false; + static constexpr auto page_size = 0u; +}; +``` + +The second template parameter isn't used directly by this class and could be any +type actually.
+However, quite often the library provides an entity type as a parameter, such as +when a storage retrieves component traits for its value type. This also makes it +possible to create specializations based on the entity type, if needed.
+If in doubt, it's recommended to use the chosen entity type, avoid passing the +parameter (since it has a default) or use a more generic type to _extend_ the +specialization to all entity types. ## Pointer stability diff --git a/src/entt/entity/component.hpp b/src/entt/entity/component.hpp index b1802ab64..00d343844 100644 --- a/src/entt/entity/component.hpp +++ b/src/entt/entity/component.hpp @@ -4,6 +4,7 @@ #include #include #include "../config/config.h" +#include "fwd.hpp" namespace entt { @@ -45,7 +46,7 @@ struct page_size +template struct component_traits { static_assert(std::is_same_v, Type>, "Unsupported type"); diff --git a/src/entt/entity/fwd.hpp b/src/entt/entity/fwd.hpp index 867234688..fc1ec71a5 100644 --- a/src/entt/entity/fwd.hpp +++ b/src/entt/entity/fwd.hpp @@ -11,6 +11,9 @@ namespace entt { /*! @brief Default entity identifier. */ enum class entity : id_type {}; +template +struct component_traits; + template> class basic_sparse_set; diff --git a/src/entt/entity/storage.hpp b/src/entt/entity/storage.hpp index a8e798351..94b8f6940 100644 --- a/src/entt/entity/storage.hpp +++ b/src/entt/entity/storage.hpp @@ -380,7 +380,7 @@ public: /*! @brief Base type. */ using base_type = underlying_type; /*! @brief Component traits. */ - using traits_type = component_traits; + using traits_type = component_traits; /*! @brief Allocator type. */ using allocator_type = Allocator; /*! @brief Type of the objects assigned to entities. */ @@ -745,7 +745,7 @@ private: /*! @copydoc basic_storage */ template -class basic_storage::page_size == 0u>> +class basic_storage::page_size == 0u>> : public basic_sparse_set::template rebind_alloc> { using alloc_traits = std::allocator_traits; static_assert(std::is_same_v, "Invalid value type"); @@ -755,7 +755,7 @@ public: /*! @brief Base type. */ using base_type = underlying_type; /*! @brief Component traits. */ - using traits_type = component_traits; + using traits_type = component_traits; /*! @brief Allocator type. */ using allocator_type = Allocator; /*! @brief Type of the objects assigned to entities. */ diff --git a/test/entt/entity/component.cpp b/test/entt/entity/component.cpp index e39345025..5a4f63d41 100644 --- a/test/entt/entity/component.cpp +++ b/test/entt/entity/component.cpp @@ -29,6 +29,13 @@ struct entt::component_traits { static constexpr auto page_size = 8u; }; +template<> +struct entt::component_traits { + using type = traits_based; + static constexpr auto in_place_delete = true; + static constexpr auto page_size = 16u; +}; + TEST(Component, VoidType) { using traits_type = entt::component_traits; @@ -70,3 +77,10 @@ TEST(Component, TraitsBased) { static_assert(!traits_type::in_place_delete); static_assert(traits_type::page_size == 8u); } + +TEST(Component, TraitsBasedTagged) { + using traits_type = entt::component_traits; + + static_assert(traits_type::in_place_delete); + static_assert(traits_type::page_size == 16u); +}