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);
+}