meta: updated doc

This commit is contained in:
Michele Caini
2021-03-09 12:10:55 +01:00
parent 62e12ee0aa
commit 2832767daa

View File

@@ -23,11 +23,11 @@
# Introduction
Reflection (or rather, its lack) is a trending topic in the C++ world and, in
the specific case of `EnTT`, a tool that can unlock a lot of other features. I
Reflection (or rather, its lack) is a trending topic in the C++ world and a tool
that can unlock a lot of interesting feature in the specific case of `EnTT`. I
looked for a third-party library that met my needs on the subject, but I always
came across some details that I didn't like: macros, being intrusive, too many
allocations. In one word: unsatisfactory.<br/>
allocations, and so on.<br/>
I finally decided to write a built-in, non-intrusive and macro-free runtime
reflection system for `EnTT`. Maybe I didn't do better than others or maybe yes,
time will tell me, but at least I can model this tool around the library to
@@ -45,7 +45,7 @@ compile-time or with custom functions.
That being said, the examples in the following sections are all based on the
`hashed_string` class as provided by this library. Therefore, where an
identifier is required, it's likely that a user defined literal is used as
identifier is required, it's likely that an user defined literal is used as
follows:
```cpp
@@ -94,8 +94,8 @@ features to a reflected type so that the reflection system can use it correctly
under the hood, but they don't want to also make the type _searchable_. In this
case, it's sufficient not to invoke `type`.
A factory is such that all its member functions returns the factory itself or
a decorated version of it. This object can be used to add the following:
A factory is such that all its member functions return the factory itself or a
decorated version of it. This object can be used to add the following:
* _Constructors_. Actual constructors can be assigned to a reflected type by
specifying their list of arguments. Free functions (namely, factories) can be
@@ -136,7 +136,7 @@ a decorated version of it. This object can be used to add the following:
The function requires as an argument the identifier to give to the meta data
once created. Users can then access meta data at runtime by searching for them
by _name_.<br/>
Data members can also be defined by means of a _setter_ and _getter_. Setters
Data members can also be defined by means of a setter and getter pair. Setters
and getters can be either free functions, class members or a mix of them, as
long as they respect the required signatures. This approach is also convenient
to create a read-only variable from a non-const data member:
@@ -162,7 +162,9 @@ a decorated version of it. This object can be used to add the following:
The function requires as an argument the identifier to give to the meta
function once created. Users can then access meta functions at runtime by
searching for them by _name_.
searching for them by _name_.<br/>
Overloading of meta functions is supported. Overloaded functions are resolved
at runtime by the reflection system according to the types of the arguments.
* _Base classes_. A base class is such that the underlying type is actually
derived from it. In this case, the reflection system tracks the relationship
@@ -216,10 +218,9 @@ entt::meta_any empty{};
entt::meta_any other{std::in_place_type<void>};
```
While `any` treats both objects as empty, `meta_any` treats objects initialized
with `void` as if they were _valid_ ones. This allows to differentiate between
failed function calls and function calls that are successful but return
nothing.<br/>
While `any` considers both as empty, `meta_any` treats objects initialized with
`void` as if they were _valid_ ones. This allows to differentiate between failed
function calls and function calls that are successful but return nothing.<br/>
Finally, the member functions `try_cast`, `cast` and `allow_cast` are used to
cast the underlying object to a given type (either a reference or a value type)
or to _convert_ a `meta_any` in such a way that a cast becomes viable for the
@@ -229,9 +230,9 @@ resulting object. There is in fact no `any_cast` equivalent for `meta_any`.
Once the web of reflected types has been constructed, it's a matter of using it
at runtime where required.<br/>
All this has the great merit that, unlike the vast majority of the things
present in this library and closely linked to the compile-time, the reflection
system stands in fact as a non-intrusive tool for the runtime.
All this has the great merit that the reflection system stands in fact as a
non-intrusive tool for the runtime, unlike the vast majority of the things
offered by this library and closely linked to the compile-time.
To search for a reflected type there are a few options:
@@ -239,10 +240,10 @@ To search for a reflected type there are a few options:
// direct access to a reflected type
auto by_type = entt::resolve<my_type>();
// lookup of a reflected type by identifier
// look up a reflected type by identifier
auto by_id = entt::resolve("reflected_type"_hs);
// lookup of a reflected type by type info
// look up a reflected type by type info
auto by_type_id = entt::resolve(entt::type_id<my_type>());
```
@@ -353,14 +354,14 @@ read the inline documentation to get the best out of this powerful tool.
## Container support
The meta module supports containers of all types out of the box.<br/>
The runtime reflection system also supports containers of all types.<br/>
Moreover, _containers_ doesn't necessarily mean those offered by the C++
standard library. In fact, user defined data structures can also work with the
meta system in many cases.
To make a container be recognized by the meta module, users are required to
provide specializations for either the `meta_sequence_container_traits` class or
the `meta_associative_container_traits` class, according with the actual _type_
To make a container be recognized as such by the meta system, users are required
to provide specializations for either the `meta_sequence_container_traits` class
or the `meta_associative_container_traits` class, according with the actual type
of the container.<br/>
`EnTT` already exports the specializations for some common classes. In
particular:
@@ -582,15 +583,14 @@ differences in behavior in the case of key-only containers. In particular:
elements. Modifying the returned object will then directly modify the element
inside the container.
Container support is deliberately minimal but theoretically sufficient to
satisfy all needs.
Container support is minimal but likely sufficient to satisfy all needs.
## Pointer-like types
As with containers, it's also possible to communicate to the meta system which
types to consider _pointers_. This will allow to dereference instances of
`meta_any`, obtaining light _references_ to the pointed objects that are also
correctly associated with their meta types.<br/>
`meta_any`, thus obtaining light _references_ to the pointed objects that are
also correctly associated with their meta types.<br/>
To make the meta system recognize a type as _pointer-like_, users can specialize
the `is_meta_pointer_like` class. `EnTT` already exports the specializations for
some common classes. In particular:
@@ -601,7 +601,7 @@ some common classes. In particular:
It's important to include the header file `pointer.hpp` to make these
specializations available to the compiler when needed.<br/>
The same file also contains many examples for the users that are interested in
making their own containers available to the meta system.
making their own pointer-like types available to the meta system.
When a type is recognized as a pointer-like one by the meta system, it's
possible to dereference the instances of `meta_any` that contain these objects.
@@ -665,8 +665,8 @@ meta type or the default constructor.<br/>
For example, in the case of primitive types like `int` or `char`, but not just
them.
For this reason and only for default constructible types, a default constructor
is automatically defined and associated with their meta types, whether they are
For this reason and only for default constructible types, default constructors
are automatically defined and associated with their meta types, whether they are
explicitly or implicitly generated.<br/>
Therefore, it won't be necessary to do this in order to construct an integer
from its meta type:
@@ -875,10 +875,10 @@ the key and the value contained in the form of `meta_any` objects, respectively.
A type registered with the reflection system can also be unregistered. This
means unregistering all its data members, member functions, conversion functions
and so on. However, the base classes won't be unregistered, since they don't
and so on. However, base classes aren't unregistered as well, since they don't
necessarily depend on it. Similarly, implicitly generated types (as an example,
the meta types implicitly generated for function parameters when needed) won't
be unregistered.<br/>
the meta types implicitly generated for function parameters when needed) aren't
unregistered.<br/>
Roughly speaking, unregistering a type means disconnecting all associated meta
objects from it and making its identifier no longer visible. The underlying node
will remain available though, as if it were implicitly generated: