|
|
@@ -6,17 +6,20 @@
|
|
|
# Table of Contents
|
|
|
|
|
|
* [Introduction](#introduction)
|
|
|
-* [Compile-time identifiers](#compile-time-identifiers)
|
|
|
-* [Runtime identifiers](#runtime-identifiers)
|
|
|
+* [Unique sequential identifiers](#unique-sequential-identifiers)
|
|
|
+ * [Compile-time generator](#compile-time-generator)
|
|
|
+ * [Runtime generator](#runtime-generator)
|
|
|
* [Hashed strings](#hashed-strings)
|
|
|
* [Wide characters](wide-characters)
|
|
|
* [Conflicts](#conflicts)
|
|
|
* [Monostate](#monostate)
|
|
|
* [Type info](#type-info)
|
|
|
- * [Almost unique identifiers](#almost-unique-identifiers)
|
|
|
+ * [Type identifier](#type-identifier)
|
|
|
+ * [Almost unique identifiers](#almost-unique-identifiers)
|
|
|
+ * [Type index](#type-index)
|
|
|
* [Traits](#traits)
|
|
|
* [Member class type](#member-class-type)
|
|
|
- * [Tags](#tags)
|
|
|
+ * [Integral constant](#integral-constant)
|
|
|
<!--
|
|
|
@endcond TURN_OFF_DOXYGEN
|
|
|
-->
|
|
|
@@ -28,19 +31,20 @@ of the library itself.<br/>
|
|
|
Hardly users will include these features in their code, but it's worth
|
|
|
describing what `EnTT` offers so as not to reinvent the wheel in case of need.
|
|
|
|
|
|
-# Compile-time identifiers
|
|
|
+# Unique sequential identifiers
|
|
|
|
|
|
-Sometimes it's useful to be able to give unique identifiers to types at
|
|
|
-compile-time.<br/>
|
|
|
-There are plenty of different solutions out there and I could have used one of
|
|
|
-them. However, I decided to spend my time to define a compact and versatile tool
|
|
|
+Sometimes it's useful to be able to give unique, sequential numeric identifiers
|
|
|
+to types either at compile-time or runtime.<br/>
|
|
|
+There are plenty of different solutions for this out there and I could have used
|
|
|
+one of them. However, I decided to spend my time to define a couple of tools
|
|
|
that fully embraces what the modern C++ has to offer.
|
|
|
|
|
|
-The _result of my efforts_ is the `identifier` class template:
|
|
|
+## Compile-time generator
|
|
|
|
|
|
-```cpp
|
|
|
-#include <ident.hpp>
|
|
|
+To generate sequential numeric identifiers at compile-time, `EnTT` offers the
|
|
|
+`identifier` class template:
|
|
|
|
|
|
+```cpp
|
|
|
// defines the identifiers for the given types
|
|
|
using id = entt::identifier<a_type, another_type>;
|
|
|
|
|
|
@@ -58,14 +62,14 @@ default:
|
|
|
}
|
|
|
```
|
|
|
|
|
|
-This is all what the class template has to offer: a `type` inline variable that
|
|
|
-contains a numerical identifier for the given type. It can be used in any
|
|
|
-context where constant expressions are required.
|
|
|
+This is all what this class template has to offer: a `type` inline variable that
|
|
|
+contains a numeric identifier for the given type. It can be used in any context
|
|
|
+where constant expressions are required.
|
|
|
|
|
|
-As long as the list remains unchanged, identifiers are also guaranteed to be the
|
|
|
-same for every run. In case they have been used in a production environment and
|
|
|
-a type has to be removed, one can just use a placeholder to left the other
|
|
|
-identifiers unchanged:
|
|
|
+As long as the list remains unchanged, identifiers are also guaranteed to be
|
|
|
+stable across different runs. In case they have been used in a production
|
|
|
+environment and a type has to be removed, one can just use a placeholder to left
|
|
|
+the other identifiers unchanged:
|
|
|
|
|
|
```cpp
|
|
|
template<typename> struct ignore_type {};
|
|
|
@@ -77,35 +81,30 @@ using id = entt::identifier<
|
|
|
>;
|
|
|
```
|
|
|
|
|
|
-A bit ugly to see, but it works at least.
|
|
|
-
|
|
|
-# Runtime identifiers
|
|
|
+Perhaps a bit ugly to see in a codebase but it gets the job done at least.
|
|
|
|
|
|
-Sometimes it's useful to be able to give unique identifiers to types at
|
|
|
-runtime.<br/>
|
|
|
-There are plenty of different solutions out there and I could have used one of
|
|
|
-them. In fact, I adapted the most common one to my requirements and used it
|
|
|
-extensively within the entire library.
|
|
|
+## Runtime generator
|
|
|
|
|
|
-It's the `family` class. Here is an example of use directly from the
|
|
|
-entity-component system:
|
|
|
+To generate sequential numeric identifiers at runtime, `EnTT` offers the
|
|
|
+`family` class template:
|
|
|
|
|
|
```cpp
|
|
|
-using component_family = entt::family<struct internal_registry_component_family>;
|
|
|
+// defines a custom generator
|
|
|
+using id = entt::family<struct my_tag>;
|
|
|
|
|
|
// ...
|
|
|
|
|
|
-template<typename Component>
|
|
|
-component_type component() const noexcept {
|
|
|
- return component_family::type<Component>;
|
|
|
-}
|
|
|
+const auto a_type_id = id::type<a_type>;
|
|
|
+const auto another_type_id = id::type<another_type>;
|
|
|
```
|
|
|
|
|
|
This is all what a _family_ has to offer: a `type` inline variable that contains
|
|
|
-a numerical identifier for the given type.
|
|
|
+a numeric identifier for the given type.<br/>
|
|
|
+The generator is customizable, so as to get different _sequences_ for different
|
|
|
+purposes if needed.
|
|
|
|
|
|
-Please, note that identifiers aren't guaranteed to be the same for every run.
|
|
|
-Indeed it mostly depends on the flow of execution.
|
|
|
+Please, note that identifiers aren't guaranteed to be stable across different
|
|
|
+runs. Indeed it mostly depends on the flow of execution.
|
|
|
|
|
|
# Hashed strings
|
|
|
|
|
|
@@ -192,8 +191,14 @@ const int i = entt::monostate<entt::hashed_string{"mykey"}>{};
|
|
|
|
|
|
The `type_info` class template is meant to provide some basic information about
|
|
|
types of all kinds.<br/>
|
|
|
-Currently, the only information available is the numeric identifier associated
|
|
|
-with a given type:
|
|
|
+It's not a drop-in replacement for `std::type_info` but can provide similar
|
|
|
+information which are not implementation defined. Therefore, they can sometimes
|
|
|
+be even more reliable than those obtained otherwise.
|
|
|
+
|
|
|
+## Type identifier
|
|
|
+
|
|
|
+One of the available information is the numeric identifier associated with a
|
|
|
+given type:
|
|
|
|
|
|
```cpp
|
|
|
auto id = entt::type_info<my_type>::id();
|
|
|
@@ -201,10 +206,10 @@ auto id = entt::type_info<my_type>::id();
|
|
|
|
|
|
In general, the `id` function is also `constexpr` but this isn't guaranteed for
|
|
|
all compilers and platforms (although it's valid with the most well-known and
|
|
|
-popular compilers).<br/>
|
|
|
+popular ones).<br/>
|
|
|
This function **can** use non-standard features of the language for its own
|
|
|
purposes. This allows it to provide compile-time identifiers that remain stable
|
|
|
-between different runs. However, it's possible to force the use of standard
|
|
|
+across different runs. However, it's possible to force the use of standard
|
|
|
features only by defining the macro `ENTT_STANDARD_CPP`. In this case, there is
|
|
|
no guarantee that the identifiers are stable across executions though. Moreover,
|
|
|
identifiers are generated at runtime and are no longer a compile-time thing.
|
|
|
@@ -224,10 +229,10 @@ struct entt::type_info<Type, std::void_d<decltype(Type::custom_id())>> {
|
|
|
|
|
|
Note that this class template and its specializations are widely used within
|
|
|
`EnTT`. It also plays a very important role in making `EnTT` work transparently
|
|
|
-across boundaries.<br/>
|
|
|
+across boundaries in many cases.<br/>
|
|
|
Please refer to the dedicated section for more details.
|
|
|
|
|
|
-## Almost unique identifiers
|
|
|
+### Almost unique identifiers
|
|
|
|
|
|
Since the default non-standard, compile-time implementation makes use of hashed
|
|
|
strings, it may happen that two types are assigned the same numeric
|
|
|
@@ -237,14 +242,13 @@ In fact, although this is quite rare, it's not entirely excluded.
|
|
|
Another case where two types are assigned the same identifier is when classes
|
|
|
from different contexts (for example two or more libraries loaded at runtime)
|
|
|
have the same fully qualified name.<br/>
|
|
|
-Since the default model is based on the name of the classes, if the types belong
|
|
|
-to the same namespace then their identifiers _could_ be identical (they won't
|
|
|
-necessarily be the same though).
|
|
|
+If the types have the same name and belong to the same namespace then their
|
|
|
+identifiers _could_ be identical (they won't necessarily be the same though).
|
|
|
|
|
|
Fortunately, there are several easy ways to deal with this:
|
|
|
|
|
|
-* The most trivial one is to define the `ENTT_STANDARD_CPP` macro. Note that
|
|
|
- runtime identifiers don't suffer from the sam problem. However, this solution
|
|
|
+* The most trivial one is to define the `ENTT_STANDARD_CPP` macro. Runtime
|
|
|
+ identifiers don't suffer from the same problem in fact. However, this solution
|
|
|
doesn't work well with a plugin system, where the libraries aren't linked.
|
|
|
|
|
|
* Another possibility is to specialize the `type_info` class for one of the
|
|
|
@@ -260,6 +264,27 @@ their types, this problem is in any case easy to solve and should not worry too
|
|
|
much.<br/>
|
|
|
In all likelihood, it will never happen to run into a conflict anyway.
|
|
|
|
|
|
+## Type index
|
|
|
+
|
|
|
+Types in `EnTT` are assigned also unique, sequential _indexes_ generated at
|
|
|
+runtime:
|
|
|
+
|
|
|
+```cpp
|
|
|
+auto index = entt::type_info<my_type>::index();
|
|
|
+```
|
|
|
+
|
|
|
+This value may differ from the numeric identifier of a type and isn't guaranteed
|
|
|
+to be stable across different runs. However, it can be very useful as index in
|
|
|
+associative and unordered associative containers or for positional accesses in a
|
|
|
+vector or an array.
|
|
|
+
|
|
|
+So as not to conflict with the other tools available, the `family` class isn't
|
|
|
+used to generate these indexes. Therefore, the numeric identifiers returned by
|
|
|
+the two tools may differ.<br/>
|
|
|
+On the other hand, this leaves users with full powers over the `family` class
|
|
|
+and therefore the generation of custom runtime sequences of indices for their
|
|
|
+own purposes, if necessary.
|
|
|
+
|
|
|
# Traits
|
|
|
|
|
|
This section contains a handful of utilities and traits not present in the
|
|
|
@@ -277,20 +302,21 @@ template<typename Member>
|
|
|
using clazz = entt::member_class_t<Member>;
|
|
|
```
|
|
|
|
|
|
-## Tags
|
|
|
+## Integral constant
|
|
|
|
|
|
-Since in `EnTT` the type identified by `ENTT_ID_TYPE` is very important and
|
|
|
-widely used, there is a more user-friendly shortcut for the creation of integral
|
|
|
-constants based on it.<br/>
|
|
|
-This shortcut is the alias template `entt::tag`.
|
|
|
-
|
|
|
-If used in combination with hashed strings, it helps to use human-readable names
|
|
|
-where types would be required otherwise. As an example:
|
|
|
+Since `std::integral_constant` may be annoying because of its form that requires
|
|
|
+to specify both a type and a value of that type, there is a more user-friendly
|
|
|
+shortcut for the creation of integral constants.<br/>
|
|
|
+This shortcut is the alias template `entt::integral_constant`:
|
|
|
|
|
|
```cpp
|
|
|
-registry.assign<entt::tag<"enemy"_hs>>(entity);
|
|
|
+constexpr auto constant = entt::integral_constant<42>;
|
|
|
```
|
|
|
|
|
|
-However, this isn't the only permitted use. Literally any value convertible to
|
|
|
-`ENTT_ID_TYPE` is a good candidate, such as the named constants of an unscoped
|
|
|
-enum.
|
|
|
+Among the other uses, when combined with a hashed string it helps to define tags
|
|
|
+as human-readable _names_ where actual types would be required otherwise:
|
|
|
+
|
|
|
+```cpp
|
|
|
+constexpr auto enemy_tag = entt::integral_constant<"enemy"_hs>;
|
|
|
+registry.emplace<enemy_tag>(entity);
|
|
|
+```
|