component_traits: support specializations based on entity type
This commit is contained in:
2
TODO
2
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:
|
||||
|
||||
@@ -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.<br/>
|
||||
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.<br/>
|
||||
Plus, it's _sfinae-friendly_ and also supports feature-based specialization:
|
||||
|
||||
```cpp
|
||||
template<typename Type>
|
||||
struct entt::component_traits<Type, std::enable_if_t<Type::never_instantiate_me, entt::entity>> {
|
||||
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.<br/>
|
||||
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.<br/>
|
||||
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
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <cstddef>
|
||||
#include <type_traits>
|
||||
#include "../config/config.h"
|
||||
#include "fwd.hpp"
|
||||
|
||||
namespace entt {
|
||||
|
||||
@@ -45,7 +46,7 @@ struct page_size<Type, std::enable_if_t<std::is_convertible_v<decltype(Type::pag
|
||||
* @brief Common way to access various properties of components.
|
||||
* @tparam Type Type of component.
|
||||
*/
|
||||
template<typename Type, typename = void>
|
||||
template<typename Type, typename>
|
||||
struct component_traits {
|
||||
static_assert(std::is_same_v<std::decay_t<Type>, Type>, "Unsupported type");
|
||||
|
||||
|
||||
@@ -11,6 +11,9 @@ namespace entt {
|
||||
/*! @brief Default entity identifier. */
|
||||
enum class entity : id_type {};
|
||||
|
||||
template<typename, typename = entity>
|
||||
struct component_traits;
|
||||
|
||||
template<typename Entity = entity, typename = std::allocator<Entity>>
|
||||
class basic_sparse_set;
|
||||
|
||||
|
||||
@@ -380,7 +380,7 @@ public:
|
||||
/*! @brief Base type. */
|
||||
using base_type = underlying_type;
|
||||
/*! @brief Component traits. */
|
||||
using traits_type = component_traits<Type>;
|
||||
using traits_type = component_traits<Type, Entity>;
|
||||
/*! @brief Allocator type. */
|
||||
using allocator_type = Allocator;
|
||||
/*! @brief Type of the objects assigned to entities. */
|
||||
@@ -745,7 +745,7 @@ private:
|
||||
|
||||
/*! @copydoc basic_storage */
|
||||
template<typename Type, typename Entity, typename Allocator>
|
||||
class basic_storage<Type, Entity, Allocator, std::enable_if_t<component_traits<Type>::page_size == 0u>>
|
||||
class basic_storage<Type, Entity, Allocator, std::enable_if_t<component_traits<Type, Entity>::page_size == 0u>>
|
||||
: public basic_sparse_set<Entity, typename std::allocator_traits<Allocator>::template rebind_alloc<Entity>> {
|
||||
using alloc_traits = std::allocator_traits<Allocator>;
|
||||
static_assert(std::is_same_v<typename alloc_traits::value_type, Type>, "Invalid value type");
|
||||
@@ -755,7 +755,7 @@ public:
|
||||
/*! @brief Base type. */
|
||||
using base_type = underlying_type;
|
||||
/*! @brief Component traits. */
|
||||
using traits_type = component_traits<Type>;
|
||||
using traits_type = component_traits<Type, Entity>;
|
||||
/*! @brief Allocator type. */
|
||||
using allocator_type = Allocator;
|
||||
/*! @brief Type of the objects assigned to entities. */
|
||||
|
||||
@@ -29,6 +29,13 @@ struct entt::component_traits<traits_based> {
|
||||
static constexpr auto page_size = 8u;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct entt::component_traits<traits_based, void> {
|
||||
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<void>;
|
||||
|
||||
@@ -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<traits_based, void>;
|
||||
|
||||
static_assert(traits_type::in_place_delete);
|
||||
static_assert(traits_type::page_size == 16u);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user