|
|
@@ -26,33 +26,33 @@
|
|
|
Reflection (or rather, its lack) is a trending topic in the C++ world and a tool
|
|
|
that can unlock a lot of interesting features 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
|
|
|
+came across some details that I did not like: macros, being intrusive, too many
|
|
|
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,
|
|
|
+reflection system for `EnTT`. Maybe I did not do better than others or maybe yes,
|
|
|
time will tell me, but at least I can model this tool around the library to
|
|
|
which it belongs and not the opposite.
|
|
|
|
|
|
# Names and identifiers
|
|
|
|
|
|
-The meta system doesn't force users to rely on the tools provided by the library
|
|
|
+The meta system does not force users to rely on the tools provided by the library
|
|
|
when it comes to working with names and identifiers. It does this by offering an
|
|
|
API that works with opaque identifiers that may or may not be generated by means
|
|
|
of a hashed string.<br/>
|
|
|
-This means that users can assign any type of identifier to the meta objects, as
|
|
|
-long as they're numeric. It doesn't matter if they're generated at runtime, at
|
|
|
+This means that users can assign any type of identifier to the meta-objects, as
|
|
|
+long as they are numeric. It does not matter if they are generated at runtime, at
|
|
|
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 is likely that a user defined literal is used as
|
|
|
follows:
|
|
|
|
|
|
```cpp
|
|
|
entt::meta_factory<my_type>{}.type("reflected_type"_hs);
|
|
|
```
|
|
|
|
|
|
-For what it's worth, this is completely equivalent to:
|
|
|
+For what it is worth, this is completely equivalent to:
|
|
|
|
|
|
```cpp
|
|
|
entt::meta_factory<my_type>{}.type(42u);
|
|
|
@@ -74,25 +74,25 @@ entt::meta_factory<my_type> factory{};
|
|
|
The returned value is a _factory object_ to use to continue building the meta
|
|
|
type.
|
|
|
|
|
|
-By default, a meta type is associated with the identifier returned by the
|
|
|
+By default, a meta-type is associated with the identifier returned by the
|
|
|
runtime type identification system built-in in `EnTT`.<br/>
|
|
|
-However, it's also possible to assign custom identifiers to meta types:
|
|
|
+However, it is also possible to assign custom identifiers to meta-types:
|
|
|
|
|
|
```cpp
|
|
|
entt::meta_factory<my_type>{}.type("reflected_type"_hs);
|
|
|
```
|
|
|
|
|
|
-Identifiers are used to _retrieve_ meta types at runtime by _name_ other than by
|
|
|
+Identifiers are used to _retrieve_ meta-types at runtime by _name_ other than by
|
|
|
type.<br/>
|
|
|
However, users can be interested in adding features to a reflected type so that
|
|
|
-the reflection system can use it correctly under the hood, while they don't want
|
|
|
-to also make the type _searchable_. In this case, it's sufficient not to invoke
|
|
|
+the reflection system can use it correctly under the hood, while they do not want
|
|
|
+to also make the type _searchable_. In this case, it is sufficient not to invoke
|
|
|
`type`.
|
|
|
|
|
|
-A factory is such that all its member functions return the factory itself. It's
|
|
|
+A factory is such that all its member functions return the factory itself. It is
|
|
|
generally used to create the following:
|
|
|
|
|
|
-* _Constructors_. A constructors is assigned to a reflected type by specifying
|
|
|
+* _Constructors_. A constructor is assigned to a reflected type by specifying
|
|
|
its _list of arguments_. Free functions are also accepted if the return type
|
|
|
is the expected one. From a client perspective, nothing changes between a free
|
|
|
function or an actual constructor:
|
|
|
@@ -101,7 +101,7 @@ generally used to create the following:
|
|
|
entt::meta_factory<my_type>{}.ctor<int, char>().ctor<&factory>();
|
|
|
```
|
|
|
|
|
|
- Meta default constructors are implicitly generated, if possible.
|
|
|
+ Meta-default constructors are implicitly generated, if possible.
|
|
|
|
|
|
* _Destructors_. Both free functions and member functions are valid destructors:
|
|
|
|
|
|
@@ -114,7 +114,7 @@ generally used to create the following:
|
|
|
A function should neither delete nor explicitly invoke the destructor of a
|
|
|
given instance.
|
|
|
|
|
|
-* _Data members_. Meta data members are actual data members of the underlying
|
|
|
+* _Data members_. Meta-data members are actual data members of the underlying
|
|
|
type but also static and global variables or constants of any kind. From the
|
|
|
point of view of the client, all the variables associated with the reflected
|
|
|
type appear as if they were part of the type itself:
|
|
|
@@ -126,7 +126,7 @@ generally used to create the following:
|
|
|
.data<&global_variable>("global"_hs);
|
|
|
```
|
|
|
|
|
|
- The `data` function requires the identifier to use for the meta data member.
|
|
|
+ The `data` function requires the identifier to use for the meta-data member.
|
|
|
Users can then access it by _name_ at runtime.<br/>
|
|
|
Data members are also defined by means of a setter and getter pair. These are
|
|
|
either free functions, class members or a mix of them. This approach is also
|
|
|
@@ -154,7 +154,7 @@ generally used to create the following:
|
|
|
.func<&free_function>("free"_hs);
|
|
|
```
|
|
|
|
|
|
- The `func` function requires the identifier to use for the meta data function.
|
|
|
+ The `func` function requires the identifier to use for the meta-data function.
|
|
|
Users can then access it by _name_ at runtime.<br/>
|
|
|
Overloading of meta functions is supported. Overloaded functions are resolved
|
|
|
at runtime by the reflection system according to the types of the arguments.
|
|
|
@@ -177,21 +177,21 @@ generally used to create the following:
|
|
|
entt::meta_factory<double>{}.conv<int>();
|
|
|
```
|
|
|
|
|
|
-This is everything users need to create meta types. Refer to the inline
|
|
|
-documentation for further details.
|
|
|
+This is everything users need to create meta-types.
|
|
|
+Refer to the inline documentation for further details.
|
|
|
|
|
|
## Any to the rescue
|
|
|
|
|
|
The reflection system offers a kind of _extended version_ of the `entt::any`
|
|
|
class (see the core module for more details).<br/>
|
|
|
The purpose is to add some feature on top of those already present, so as to
|
|
|
-integrate it with the meta type system without having to duplicate the code.
|
|
|
+integrate it with the meta-type system without having to duplicate the code.
|
|
|
|
|
|
The API is very similar to that of the `any` type. The class `meta_any` _wraps_
|
|
|
many of the feature to infer a meta node, before forwarding some or all of the
|
|
|
arguments to the underlying storage.<br/>
|
|
|
Among the few relevant differences, `meta_any` adds support for containers and
|
|
|
-pointer-like types, while `any` doesn't.<br/>
|
|
|
+pointer-like types, while `any` does not.<br/>
|
|
|
Similar to `any`, this class is also used to create _aliases_ for unmanaged
|
|
|
objects either with `forward_as_meta` or using the `std::in_place_type<T &>`
|
|
|
disambiguation tag, as well as from an existing object by means of the `as_ref`
|
|
|
@@ -206,7 +206,7 @@ entt::meta_any other{std::in_place_type<void>};
|
|
|
```
|
|
|
|
|
|
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
|
|
|
+`void` as if they were _valid_ ones. This allows differentiating between failed
|
|
|
function calls and function calls that are successful but return nothing.
|
|
|
|
|
|
Finally, the member functions `try_cast`, `cast` and `allow_cast` are used to
|
|
|
@@ -217,7 +217,7 @@ There is in fact no `any_cast` equivalent for `meta_any`.
|
|
|
|
|
|
## Enjoy the runtime
|
|
|
|
|
|
-Once the web of reflected types is constructed, it's a matter of using it at
|
|
|
+Once the web of reflected types is constructed, it is a matter of using it at
|
|
|
runtime where required.<br/>
|
|
|
There are a few options to search for a reflected type:
|
|
|
|
|
|
@@ -243,21 +243,21 @@ for(auto &&[id, type]: entt::resolve()) {
|
|
|
```
|
|
|
|
|
|
In all cases, the returned value is an instance of `meta_type` (possibly with
|
|
|
-its id). This kind of objects offer an API to know their _runtime identifiers_,
|
|
|
-to iterate all the meta objects associated with them and even to build instances
|
|
|
+its id). This kind of objects offers an API to know their _runtime identifiers_,
|
|
|
+to iterate all the meta-objects associated with them and even to build instances
|
|
|
of the underlying type.<br/>
|
|
|
-Meta data members and functions are accessed by name:
|
|
|
+Meta-data members and functions are accessed by name:
|
|
|
|
|
|
-* Meta data members:
|
|
|
+* Meta-data members:
|
|
|
|
|
|
```cpp
|
|
|
auto data = entt::resolve<my_type>().data("member"_hs);
|
|
|
```
|
|
|
|
|
|
- The returned type is `meta_data` and may be invalid if there is no meta data
|
|
|
+ The returned type is `meta_data` and may be invalid if there is no meta-data
|
|
|
object associated with the given identifier.<br/>
|
|
|
- A meta data object offers an API to query the underlying type (for example, to
|
|
|
- know if it's a const or a static one), to get the meta type of the variable
|
|
|
+ A meta-data object offers an API to query the underlying type (for example, to
|
|
|
+ know if it is a const or a static one), to get the meta-type of the variable
|
|
|
and to set or get the contained value.
|
|
|
|
|
|
* Meta function members:
|
|
|
@@ -269,12 +269,12 @@ Meta data members and functions are accessed by name:
|
|
|
The returned type is `meta_func` and may be invalid if there is no meta
|
|
|
function object associated with the given identifier.<br/>
|
|
|
A meta function object offers an API to query the underlying type (for
|
|
|
- example, to know if it's a const or a static function), to know the number of
|
|
|
- arguments, the meta return type and the meta types of the parameters. In
|
|
|
+ example, to know if it is a const or a static function), to know the number of
|
|
|
+ arguments, the meta return type and the meta-types of the parameters. In
|
|
|
addition, a meta function object is used to invoke the underlying function and
|
|
|
then get the return value in the form of a `meta_any` object.
|
|
|
|
|
|
-All the meta objects thus obtained as well as the meta types explicitly convert
|
|
|
+All the meta-objects thus obtained as well as the meta-types explicitly convert
|
|
|
to a boolean value to check for validity:
|
|
|
|
|
|
```cpp
|
|
|
@@ -283,7 +283,7 @@ if(auto func = entt::resolve<my_type>().func("member"_hs); func) {
|
|
|
}
|
|
|
```
|
|
|
|
|
|
-Furthermore, all them (and a few more, like meta basis) are returned by a bunch
|
|
|
+Furthermore, all of them (and a few more, like meta-basis) are returned by a bunch
|
|
|
of overloads that provide the caller with iterable ranges of top-level elements.
|
|
|
As an example:
|
|
|
|
|
|
@@ -293,30 +293,30 @@ for(auto &&[id, type]: entt::resolve<my_type>().base()) {
|
|
|
}
|
|
|
```
|
|
|
|
|
|
-Meta type are also used to `construct` actual instances of the underlying
|
|
|
+Meta-types are also used to `construct` actual instances of the underlying
|
|
|
type.<br/>
|
|
|
In particular, the `construct` member function accepts a variable number of
|
|
|
arguments and searches for a match. It then returns a `meta_any` object that may
|
|
|
or may not be initialized, depending on whether a suitable constructor was found
|
|
|
or not.
|
|
|
|
|
|
-There is no object that wraps the destructor of a meta type nor a `destroy`
|
|
|
+There is no object that wraps the destructor of a meta-type nor a `destroy`
|
|
|
member function in its API. Destructors are invoked implicitly by `meta_any`
|
|
|
behind the scenes and users have not to deal with them explicitly. Furthermore,
|
|
|
-they've no name, cannot be searched and wouldn't have member functions to expose
|
|
|
+they have no name, cannot be searched and would not have member functions to expose
|
|
|
anyway.<br/>
|
|
|
-Similarly, conversion functions aren't directly accessible. They're used
|
|
|
-internally by `meta_any` and the meta objects when needed.
|
|
|
+Similarly, conversion functions are not directly accessible. They are used
|
|
|
+internally by `meta_any` and the meta-objects when needed.
|
|
|
|
|
|
-Meta types and meta objects in general contain much more than what was said.
|
|
|
+Meta-types and meta-objects in general contain much more than what was said.
|
|
|
Refer to the inline documentation for further details.
|
|
|
|
|
|
## Container support
|
|
|
|
|
|
The runtime reflection system also supports containers of all types.<br/>
|
|
|
-Moreover, _containers_ doesn't necessarily mean those offered by the C++
|
|
|
+Moreover, _containers_ does not 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.
|
|
|
+meta-system in many cases.
|
|
|
|
|
|
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
|
|
|
@@ -331,13 +331,13 @@ particular:
|
|
|
* `std::map`, `std::set` and their unordered counterparts are supported as
|
|
|
_associative containers_.
|
|
|
|
|
|
-It's important to include the header file `container.hpp` to make these
|
|
|
+It is important to include the header file `container.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 containers available to the meta-system.
|
|
|
|
|
|
When a specialization of the `meta_sequence_container_traits` class exists, the
|
|
|
-meta system treats the wrapped type as a sequence container. In a similar way,
|
|
|
+meta-system treats the wrapped type as a sequence container. In a similar way,
|
|
|
a type is treated as an associative container if a specialization of the
|
|
|
`meta_associative_container_traits` class is found for it.<br/>
|
|
|
Proxy objects are returned by dedicated members of the `meta_any` class. The
|
|
|
@@ -357,34 +357,34 @@ if(any.type().is_sequence_container()) {
|
|
|
|
|
|
The method to use to get a proxy object for associative containers is
|
|
|
`as_associative_container` instead.<br/>
|
|
|
-It's not necessary to perform a double check actually. Instead, it's enough to
|
|
|
-query the meta type or verify that the proxy object is valid. In fact, proxies
|
|
|
+It is not necessary to perform a double check actually. Instead, it is enough to
|
|
|
+query the meta-type or verify that the proxy object is valid. In fact, proxies
|
|
|
are contextually convertible to bool to check for validity. For example, invalid
|
|
|
-proxies are returned when the wrapped object isn't a container.<br/>
|
|
|
-In all cases, users aren't expected to _reflect_ containers explicitly. It's
|
|
|
-sufficient to assign a container for which a specialization of the traits
|
|
|
+proxies are returned when the wrapped object is not a container.<br/>
|
|
|
+In all cases, users are not expected to _reflect_ containers explicitly. It is
|
|
|
+sufficient to assign a container for which a specialization of the trait
|
|
|
classes exists to a `meta_any` object to be able to get its proxy object.
|
|
|
|
|
|
The interface of the `meta_sequence_container` proxy object is the same for all
|
|
|
types of sequence containers, although the available features differ from case
|
|
|
to case. In particular:
|
|
|
|
|
|
-* The `value_type` member function returns the meta type of the elements.
|
|
|
+* The `value_type` member function returns the meta-type of the elements.
|
|
|
|
|
|
* The `size` member function returns the number of elements in the container as
|
|
|
an unsigned integer value.
|
|
|
|
|
|
-* The `resize` member function allows to resize the wrapped container and
|
|
|
+* The `resize` member function allows resizing the wrapped container and
|
|
|
returns true in case of success.<br/>
|
|
|
- For example, it's not possible to resize fixed size containers.
|
|
|
+ For example, it is not possible to resize fixed size containers.
|
|
|
|
|
|
-* The `clear` member function allows to clear the wrapped container and returns
|
|
|
+* The `clear` member function allows clearing the wrapped container and returns
|
|
|
true in case of success.<br/>
|
|
|
- For example, it's not possible to clear fixed size containers.
|
|
|
+ For example, it is not possible to clear fixed size containers.
|
|
|
|
|
|
-* The `reserve` member function allows to increase the capacity of the wrapped
|
|
|
+* The `reserve` member function allows increasing the capacity of the wrapped
|
|
|
container and returns true in case of success.<br/>
|
|
|
- For example, it's not possible to increase capacity of fixed size containers.
|
|
|
+ For example, it is not possible to increase capacity of fixed size containers.
|
|
|
|
|
|
* The `begin` and `end` member functions return opaque iterators that is used to
|
|
|
iterate the container directly:
|
|
|
@@ -398,7 +398,7 @@ to case. In particular:
|
|
|
In all cases, given an underlying container of type `C`, the returned element
|
|
|
contains an object of type `C::value_type` which therefore depends on the
|
|
|
actual container.<br/>
|
|
|
- All meta iterators are input iterators and don't offer an indirection operator
|
|
|
+ All meta iterators are input iterators and do not offer an indirection operator
|
|
|
on purpose.
|
|
|
|
|
|
* The `insert` member function is used to add elements to the container. It
|
|
|
@@ -413,7 +413,7 @@ to case. In particular:
|
|
|
This function returns a meta iterator pointing to the inserted element and a
|
|
|
boolean value to indicate whether the operation was successful or not. A call
|
|
|
to `insert` may silently fail in case of fixed size containers or whether the
|
|
|
- arguments aren't at least convertible to the required types.<br/>
|
|
|
+ arguments are not at least convertible to the required types.<br/>
|
|
|
Since meta iterators are contextually convertible to bool, users can rely on
|
|
|
them to know if the operation failed on the actual container or upstream, for
|
|
|
example due to an argument conversion problem.
|
|
|
@@ -456,26 +456,26 @@ differences in behavior in the case of key-only containers. In particular:
|
|
|
* The `key_only` member function returns true if the wrapped container is a
|
|
|
key-only one.
|
|
|
|
|
|
-* The `key_type` member function returns the meta type of the keys.
|
|
|
+* The `key_type` member function returns the meta-type of the keys.
|
|
|
|
|
|
-* The `mapped_type` member function returns an invalid meta type for key-only
|
|
|
- containers and the meta type of the mapped values for all other types of
|
|
|
+* The `mapped_type` member function returns an invalid meta-type for key-only
|
|
|
+ containers and the meta-type of the mapped values for all other types of
|
|
|
containers.
|
|
|
|
|
|
-* The `value_type` member function returns the meta type of the elements.<br/>
|
|
|
- For example, it returns the meta type of `int` for `std::set<int>` while it
|
|
|
- returns the meta type of `std::pair<const int, char>` for
|
|
|
+* The `value_type` member function returns the meta-type of the elements.<br/>
|
|
|
+ For example, it returns the meta-type of `int` for `std::set<int>` while it
|
|
|
+ returns the meta-type of `std::pair<const int, char>` for
|
|
|
`std::map<int, char>`.
|
|
|
|
|
|
* The `size` member function returns the number of elements in the container as
|
|
|
an unsigned integer value.
|
|
|
|
|
|
-* The `clear` member function allows to clear the wrapped container and returns
|
|
|
+* The `clear` member function allows clearing the wrapped container and returns
|
|
|
true in case of success.
|
|
|
|
|
|
-* The `reserve` member function allows to increase the capacity of the wrapped
|
|
|
+* The `reserve` member function allows increasing the capacity of the wrapped
|
|
|
container and returns true in case of success.<br/>
|
|
|
- For example, it's not possible to increase capacity of standard maps.
|
|
|
+ For example, it is not possible to increase capacity of standard maps.
|
|
|
|
|
|
* The `begin` and `end` member functions return opaque iterators that are used
|
|
|
to iterate the container directly:
|
|
|
@@ -488,9 +488,9 @@ differences in behavior in the case of key-only containers. In particular:
|
|
|
|
|
|
In all cases, given an underlying container of type `C`, the returned element
|
|
|
is a key-value pair where the key has type `C::key_type` and the value has
|
|
|
- type `C::mapped_type`. Since key-only containers don't have a mapped type,
|
|
|
+ type `C::mapped_type`. Since key-only containers do not have a mapped type,
|
|
|
their _value_ is nothing more than an invalid `meta_any` object.<br/>
|
|
|
- All meta iterators are input iterators and don't offer an indirection operator
|
|
|
+ All meta iterators are input iterators and do not offer an indirection operator
|
|
|
on purpose.
|
|
|
|
|
|
While the accessed key is usually constant in the associative containers and
|
|
|
@@ -499,7 +499,7 @@ differences in behavior in the case of key-only containers. In particular:
|
|
|
modifies the element inside the container.
|
|
|
|
|
|
* The `insert` member function is used to add elements to a container. It gets
|
|
|
- two arguments, respectively the key and the value to insert:
|
|
|
+ two arguments, respectively, the key and the value to insert:
|
|
|
|
|
|
```cpp
|
|
|
auto last = view.end();
|
|
|
@@ -508,7 +508,7 @@ differences in behavior in the case of key-only containers. In particular:
|
|
|
```
|
|
|
|
|
|
This function returns a boolean value to indicate whether the operation was
|
|
|
- successful or not. A call to `insert` may fail when the arguments aren't at
|
|
|
+ successful or not. A call to `insert` may fail when the arguments are not at
|
|
|
least convertible to the required types.
|
|
|
|
|
|
* The `erase` member function is used to remove elements from a container. It
|
|
|
@@ -519,7 +519,7 @@ differences in behavior in the case of key-only containers. In particular:
|
|
|
```
|
|
|
|
|
|
This function returns a boolean value to indicate whether the operation was
|
|
|
- successful or not. A call to `erase` may fail when the argument isn't at least
|
|
|
+ successful or not. A call to `erase` may fail when the argument is not at least
|
|
|
convertible to the required type.
|
|
|
|
|
|
* The `operator[]` is used to access elements in a container. It gets a single
|
|
|
@@ -537,50 +537,50 @@ Container support is minimal but likely sufficient to satisfy all needs.
|
|
|
|
|
|
## Pointer-like types
|
|
|
|
|
|
-As with containers, it's also possible to _tell_ to the meta system which types
|
|
|
+As with containers, it is also possible to _tell_ to the meta-system which types
|
|
|
are _pointers_. This makes it possible to dereference instances of `meta_any`,
|
|
|
thus obtaining light _references_ to 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
|
|
|
+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:
|
|
|
|
|
|
* All types of raw pointers.
|
|
|
* `std::unique_ptr` and `std::shared_ptr`.
|
|
|
|
|
|
-It's important to include the header file `pointer.hpp` to make these
|
|
|
+It is 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 pointer-like types available to the meta system.
|
|
|
|
|
|
-When a type is recognized as a pointer-like one by the meta system, it's
|
|
|
+When a type is recognized as a pointer-like one by the meta-system, it is
|
|
|
possible to dereference the instances of `meta_any` that contain these objects.
|
|
|
The following is a deliberately verbose example to show how to use this feature:
|
|
|
|
|
|
```cpp
|
|
|
int value = 42;
|
|
|
-// meta type equivalent to that of int *
|
|
|
+// meta-type equivalent to that of int *
|
|
|
entt::meta_any any{&value};
|
|
|
|
|
|
if(any.type().is_pointer_like()) {
|
|
|
- // meta type equivalent to that of int
|
|
|
+ // meta-type equivalent to that of int
|
|
|
if(entt::meta_any ref = *any; ref) {
|
|
|
// ...
|
|
|
}
|
|
|
}
|
|
|
```
|
|
|
|
|
|
-It's not necessary to perform a double check. Instead, it's enough to query the
|
|
|
-meta type or verify that the returned object is valid. For example, invalid
|
|
|
-instances are returned when the wrapped object isn't a pointer-like type.<br/>
|
|
|
+It is not necessary to perform a double check. Instead, it is enough to query the
|
|
|
+meta-type or verify that the returned object is valid. For example, invalid
|
|
|
+instances are returned when the wrapped object is not a pointer-like type.<br/>
|
|
|
Dereferencing a pointer-like object returns an instance of `meta_any` which
|
|
|
_refers_ to the pointed object. Modifying it means modifying the pointed object
|
|
|
directly (unless the returned element is const).
|
|
|
|
|
|
In general, _dereferencing_ a pointer-like type boils down to a `*ptr`. However,
|
|
|
-`EnTT` also supports classes that don't offer an `operator*`. In particular:
|
|
|
+`EnTT` also supports classes that do not offer an `operator*`. In particular:
|
|
|
|
|
|
-* It's possible to exploit a solution based on ADL lookup by offering a function
|
|
|
+* It is possible to exploit a solution based on ADL lookup by offering a function
|
|
|
(also a template one) named `dereference_meta_pointer_like`:
|
|
|
|
|
|
```cpp
|
|
|
@@ -590,7 +590,7 @@ In general, _dereferencing_ a pointer-like type boils down to a `*ptr`. However,
|
|
|
}
|
|
|
```
|
|
|
|
|
|
-* When not in control of the type's namespace, it's possible to inject into the
|
|
|
+* When not in control of the type's namespace, it is possible to inject into the
|
|
|
`entt` namespace a specialization of the `adl_meta_pointer_like` class
|
|
|
template to bypass the adl lookup as a whole:
|
|
|
|
|
|
@@ -608,29 +608,29 @@ of the pointed type, no user intervention is required.
|
|
|
|
|
|
## Template information
|
|
|
|
|
|
-Meta types also provide a minimal set of information about the _nature_ of the
|
|
|
-original type in case it's a class template.<br/>
|
|
|
-By default, this works out of the box and requires no user action. However, it's
|
|
|
+Meta-types also provide a minimal set of information about the _nature_ of the
|
|
|
+original type in case it is a class template.<br/>
|
|
|
+By default, this works out of the box and requires no user action. However, it is
|
|
|
important to include the header file `template.hpp` to make this information
|
|
|
available to the compiler when needed.
|
|
|
|
|
|
-Meta template information are easily found:
|
|
|
+Meta-template information is easily found:
|
|
|
|
|
|
```cpp
|
|
|
// this method returns true if the type is recognized as a class template specialization
|
|
|
if(auto type = entt::resolve<std::shared_ptr<my_type>>(); type.is_template_specialization()) {
|
|
|
- // meta type of the class template conveniently wrapped by entt::meta_class_template_tag
|
|
|
+ // meta-type of the class template conveniently wrapped by entt::meta_class_template_tag
|
|
|
auto class_type = type.template_type();
|
|
|
|
|
|
// number of template arguments
|
|
|
std::size_t arity = type.template_arity();
|
|
|
|
|
|
- // meta type of the i-th argument
|
|
|
+ // meta-type of the i-th argument
|
|
|
auto arg_type = type.template_arg(0u);
|
|
|
}
|
|
|
```
|
|
|
|
|
|
-Typically, when template information for a type are required, what the library
|
|
|
+Typically, when template information for a type is required, what the library
|
|
|
provides is sufficient. However, there are some cases where a user may want more
|
|
|
details or a different set of information.<br/>
|
|
|
Consider the case of a class template that is meant to wrap function types:
|
|
|
@@ -657,8 +657,8 @@ struct entt::meta_template_traits<function_type<Ret(Args...)>> {
|
|
|
};
|
|
|
```
|
|
|
|
|
|
-The reflection system doesn't verify the accuracy of the information nor infer a
|
|
|
-correspondence between real types and meta types.<br/>
|
|
|
+The reflection system does not verify the accuracy of the information nor infer a
|
|
|
+correspondence between real types and meta-types.<br/>
|
|
|
Therefore, the specialization is used as is and the information it contains is
|
|
|
associated with the appropriate type when required.
|
|
|
|
|
|
@@ -698,7 +698,7 @@ double value = any.cast<double>();
|
|
|
```
|
|
|
|
|
|
With no need for registration, the conversion takes place automatically under
|
|
|
-the hood. The same goes for a call to `allow_cast` involving a meta type:
|
|
|
+the hood. The same goes for a call to `allow_cast` involving a meta-type:
|
|
|
|
|
|
```cpp
|
|
|
entt::meta_type type = entt::resolve<int>();
|
|
|
@@ -709,27 +709,27 @@ int value = any.cast<int>();
|
|
|
|
|
|
This makes working with arithmetic types and scoped or unscoped enums as easy as
|
|
|
it is in C++.<br/>
|
|
|
-It's still possible to set up conversion functions manually and these are always
|
|
|
-preferred over the automatic ones.
|
|
|
+It is still possible to set up conversion functions manually, and these are
|
|
|
+always preferred over the automatic ones.
|
|
|
|
|
|
## Implicitly generated default constructor
|
|
|
|
|
|
Creating objects of default constructible types through the reflection system
|
|
|
-while not having to explicitly register the meta type or its default constructor
|
|
|
+while not having to explicitly register the meta-type or its default constructor
|
|
|
is also possible.<br/>
|
|
|
For example, in the case of primitive types like `int` or `char`, but not just
|
|
|
them.
|
|
|
|
|
|
For default constructible types only, default constructors are automatically
|
|
|
-defined and associated with their meta types, whether they are explicitly or
|
|
|
+defined and associated with their meta-types, whether they are explicitly or
|
|
|
implicitly generated.<br/>
|
|
|
-Therefore, this is all is needed to construct an integer from its meta type:
|
|
|
+Therefore, this is all needed to construct an integer from its meta-type:
|
|
|
|
|
|
```cpp
|
|
|
entt::resolve<int>().construct();
|
|
|
```
|
|
|
|
|
|
-Where the meta type is for example the one returned from a meta container,
|
|
|
+Where the meta-type is, for example, the one returned from a meta-container,
|
|
|
useful for building keys without knowing or having to register the actual types.
|
|
|
|
|
|
In all cases, when users register default constructors, they are preferred both
|
|
|
@@ -737,7 +737,7 @@ during searches and when the `construct` member function is invoked.
|
|
|
|
|
|
## From void to any
|
|
|
|
|
|
-Sometimes all a user has is an opaque pointer to an object of a known meta type.
|
|
|
+Sometimes all a user has is an opaque pointer to an object of a known meta-type.
|
|
|
It would be handy in this case to be able to construct a `meta_any` element from
|
|
|
it.<br/>
|
|
|
For this purpose, the `meta_type` class offers a `from_void` member function
|
|
|
@@ -747,7 +747,7 @@ designed to convert an opaque pointer into a `meta_any`:
|
|
|
entt::meta_any any = entt::resolve(id).from_void(element);
|
|
|
```
|
|
|
|
|
|
-Unfortunately, it's not possible to do a check on the actual type. Therefore,
|
|
|
+Unfortunately, it is not possible to do a check on the actual type. Therefore,
|
|
|
this call can be considered as a _static cast_ with all its _problems_.<br/>
|
|
|
On the other hand, the ability to construct a `meta_any` from an opaque pointer
|
|
|
opens the door to some pretty interesting uses that are worth exploring.
|
|
|
@@ -760,20 +760,20 @@ Their purpose is to require slightly different behavior than the default in some
|
|
|
specific cases. For example, when reading a given data member, its value is
|
|
|
returned wrapped in a `meta_any` object which, by default, makes a copy of it.
|
|
|
For large objects or if the caller wants to access the original instance, this
|
|
|
-behavior isn't desirable. Policies are there to offer a solution to this and
|
|
|
+behavior is not desirable. Policies are there to offer a solution to this and
|
|
|
other problems.
|
|
|
|
|
|
There are a few alternatives available at the moment:
|
|
|
|
|
|
* The _as-is_ policy, associated with the type `entt::as_is_t`.<br/>
|
|
|
This is the default policy. In general, it should never be used explicitly,
|
|
|
- since it's implicitly selected if no other policy is specified.<br/>
|
|
|
+ since it is implicitly selected if no other policy is specified.<br/>
|
|
|
In this case, the return values of the functions as well as the properties
|
|
|
exposed as data members are always returned by copy in a dedicated wrapper and
|
|
|
- therefore associated with their original meta types.
|
|
|
+ therefore associated with their original meta-types.
|
|
|
|
|
|
* The _as-void_ policy, associated with the type `entt::as_void_t`.<br/>
|
|
|
- Its purpose is to discard the return value of a meta object, whatever it is,
|
|
|
+ Its purpose is to discard the return value of a meta-object, whatever it is,
|
|
|
thus making it appear as if its type were `void`:
|
|
|
|
|
|
```cpp
|
|
|
@@ -783,7 +783,7 @@ There are a few alternatives available at the moment:
|
|
|
If the use with functions is obvious, perhaps less so is use with constructors
|
|
|
and data members. In the first case, the returned wrapper is always empty even
|
|
|
though the constructor is still invoked. In the second case, the property
|
|
|
- isn't accessible for reading instead.
|
|
|
+ is not accessible for reading instead.
|
|
|
|
|
|
* The _as-ref_ and _as-cref_ policies, associated with the types
|
|
|
`entt::as_ref_t` and `entt::as_cref_t`.<br/>
|
|
|
@@ -803,15 +803,15 @@ There are a few alternatives available at the moment:
|
|
|
`as_ref_t` _adapts_ to the constness of the passed object and to that of the
|
|
|
return type if any.
|
|
|
|
|
|
-Some uses are rather trivial, but it's useful to note that there are some less
|
|
|
+Some uses are rather trivial, but it is useful to note that there are some less
|
|
|
obvious corner cases that can in turn be solved with the use of policies.
|
|
|
|
|
|
## Named constants and enums
|
|
|
|
|
|
As mentioned, the `data` member function is used to reflect constants of any
|
|
|
type.<br/>
|
|
|
-This allows users to create meta types for enums that work exactly like any
|
|
|
-other meta type built from a class. Similarly, arithmetic types are _enriched_
|
|
|
+This allows users to create meta-types for enums that work exactly like any
|
|
|
+other meta-type built from a class. Similarly, arithmetic types are _enriched_
|
|
|
with constants of special meaning where required.<br/>
|
|
|
All values thus exported appear to users as if they were constant data members
|
|
|
of the reflected types. This avoids the need to _export_ what is the difference
|
|
|
@@ -827,8 +827,8 @@ entt::meta_factory<my_enum>{}
|
|
|
entt::meta_factory<int>{}.data<2048>("max_int"_hs);
|
|
|
```
|
|
|
|
|
|
-Accessing them is trivial as well. It's a matter of doing the following, as with
|
|
|
-any other data member of a meta type:
|
|
|
+Accessing them is trivial as well. It is a matter of doing the following, as with
|
|
|
+any other data member of a meta-type:
|
|
|
|
|
|
```cpp
|
|
|
auto value = entt::resolve<my_enum>().data("a_value"_hs).get({}).cast<my_enum>();
|
|
|
@@ -841,7 +841,7 @@ object optimization performed by the `meta_any` class.
|
|
|
## User defined data
|
|
|
|
|
|
Sometimes (for example, when it comes to creating an editor) it might be useful
|
|
|
-to attach _traits_ or arbitrary _custom data_ to the meta objects created.
|
|
|
+to attach _traits_ or arbitrary _custom data_ to the meta-objects created.
|
|
|
|
|
|
The main difference between them is that:
|
|
|
|
|
|
@@ -852,7 +852,7 @@ The main difference between them is that:
|
|
|
* Custom data are stored in a generic quick access area reserved for the user
|
|
|
and which the library will never use under any circumstances.
|
|
|
|
|
|
-In all cases, this support is currently available only for meta types, meta data
|
|
|
+In all cases, this support is currently available only for meta-types, meta-data
|
|
|
and meta functions.
|
|
|
|
|
|
### Traits
|
|
|
@@ -863,14 +863,14 @@ User-defined traits are set via a meta factory:
|
|
|
entt::meta_factory<my_type>{}.traits(my_traits::required | my_traits::hidden);
|
|
|
```
|
|
|
|
|
|
-In the example above, `EnTT` bitmask enum support is used but any integral value
|
|
|
-is fine, as long as it doesn't exceed 16 bits.<br/>
|
|
|
-It's not possible to assign traits at different times. Therefore, multiple calls
|
|
|
+In the example above, `EnTT` bitmask enum support is used, but any integral value
|
|
|
+is fine, as long as it does not exceed 16 bits.<br/>
|
|
|
+It is not possible to assign traits at different times. Therefore, multiple calls
|
|
|
to the `traits` function overwrite previous values. However, traits can be read
|
|
|
-from meta objects and used to update existing data with a factory, effectively
|
|
|
+from meta-objects and used to update existing data with a factory, effectively
|
|
|
extending them as needed.<br/>
|
|
|
-Likewise, users can also set traits on meta objects later if needed, as long as
|
|
|
-the factory is reset to the meta object of interest:
|
|
|
+Likewise, users can also set traits on meta-objects later if needed, as long as
|
|
|
+the factory is reset to the meta-object of interest:
|
|
|
|
|
|
```cpp
|
|
|
entt::meta_factory<my_type>{}
|
|
|
@@ -878,7 +878,7 @@ entt::meta_factory<my_type>{}
|
|
|
.traits(my_traits::internal);
|
|
|
```
|
|
|
|
|
|
-Once created, all meta objects offer a member function named `traits` to get the
|
|
|
+Once created, all meta-objects offer a member function named `traits` to get the
|
|
|
currently set value:
|
|
|
|
|
|
```cpp
|
|
|
@@ -891,7 +891,7 @@ correctly.
|
|
|
|
|
|
### Custom data
|
|
|
|
|
|
-Custom arbitrary data are set via a meta factory:
|
|
|
+Custom arbitrary data are set via a meta-factory:
|
|
|
|
|
|
```cpp
|
|
|
entt::meta_factory<my_type>{}.custom<type_data>("name");
|
|
|
@@ -899,12 +899,12 @@ entt::meta_factory<my_type>{}.custom<type_data>("name");
|
|
|
|
|
|
The way to do this is by specifying the data type to the `custom` function and
|
|
|
passing the necessary arguments to construct it correctly.<br/>
|
|
|
-It's not possible to assign custom data at different times. Therefore, multiple
|
|
|
+It is not possible to assign custom data at different times. Therefore, multiple
|
|
|
calls to the `custom` function overwrite previous values. However, this value
|
|
|
-can be read from meta objects and used to update existing data with a factory,
|
|
|
+can be read from meta-objects and used to update existing data with a factory,
|
|
|
effectively updating them as needed.<br/>
|
|
|
-Likewise, users can also set custom data on meta objects later if needed, as
|
|
|
-long as the factory is reset to the meta object of interest:
|
|
|
+Likewise, users can also set custom data on meta-objects later if needed, as
|
|
|
+long as the factory is reset to the meta-object of interest:
|
|
|
|
|
|
```cpp
|
|
|
entt::meta_factory<my_type>{}
|
|
|
@@ -912,7 +912,7 @@ entt::meta_factory<my_type>{}
|
|
|
.custom<function_data>("tooltip");
|
|
|
```
|
|
|
|
|
|
-Once created, all meta objects offer a member function named `custom` to get the
|
|
|
+Once created, all meta-objects offer a member function named `custom` to get the
|
|
|
currently set value as a reference or as a pointer to an element:
|
|
|
|
|
|
```cpp
|
|
|
@@ -928,23 +928,23 @@ null pointer is returned to inform the user of the failed attempt.
|
|
|
|
|
|
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, base classes aren't unregistered as well, since they don't
|
|
|
+and so on. However, base classes are not unregistered as well, since they do not
|
|
|
necessarily depend on it.<br/>
|
|
|
-Roughly speaking, unregistering a type means disconnecting all associated meta
|
|
|
-objects from it and making its identifier no longer available:
|
|
|
+Roughly speaking, unregistering a type means disconnecting all associated
|
|
|
+meta-objects from it and making its identifier no longer available:
|
|
|
|
|
|
```cpp
|
|
|
entt::meta_reset<my_type>();
|
|
|
```
|
|
|
|
|
|
-It's also possible to reset types by their unique identifiers:
|
|
|
+It is also possible to reset types by their unique identifiers:
|
|
|
|
|
|
```cpp
|
|
|
entt::meta_reset("my_type"_hs);
|
|
|
```
|
|
|
|
|
|
Finally, there exists a non-template overload of the `meta_reset` function that
|
|
|
-doesn't accept arguments and resets all meta types at once:
|
|
|
+does not accept arguments and resets all meta-types at once:
|
|
|
|
|
|
```cpp
|
|
|
entt::meta_reset();
|
|
|
@@ -954,14 +954,14 @@ A type can be re-registered later with a completely different name and form.
|
|
|
|
|
|
## Meta context
|
|
|
|
|
|
-All meta types and their parts are created at runtime and stored in a default
|
|
|
+All meta-types and their parts are created at runtime and stored in a default
|
|
|
_context_. This is obtained via a service locator as:
|
|
|
|
|
|
```cpp
|
|
|
auto &&context = entt::locator<entt::meta_context>::value_or();
|
|
|
```
|
|
|
|
|
|
-By itself, a context is an opaque object that the user cannot do much with.
|
|
|
+By itself, a context is an opaque object that the user can do little with.
|
|
|
However, users can replace an existing context with another at any time:
|
|
|
|
|
|
```cpp
|
|
|
@@ -971,12 +971,12 @@ std::swap(context, other);
|
|
|
```
|
|
|
|
|
|
This is useful for testing purposes or to define multiple context objects with
|
|
|
-different meta type to use as appropriate.
|
|
|
+different meta-types to use as appropriate.
|
|
|
|
|
|
-If _replacing_ the default context isn't enough, `EnTT` also offers the ability
|
|
|
+If _replacing_ the default context is not enough, `EnTT` also offers the ability
|
|
|
to use multiple and externally managed contexts with the runtime reflection
|
|
|
system.<br/>
|
|
|
-For example, to create new meta types within a context other than the default
|
|
|
+For example, to create new meta-types within a context other than the default
|
|
|
one, simply pass it as an argument to the `meta_factory` constructor:
|
|
|
|
|
|
```cpp
|
|
|
@@ -984,7 +984,7 @@ entt::meta_ctx context{};
|
|
|
entt::meta_factory<my_type>{context}.type("reflected_type"_hs);
|
|
|
```
|
|
|
|
|
|
-By doing so, the new meta type isn't available in the default context but is
|
|
|
+By doing so, the new meta-type is not available in the default context but is
|
|
|
usable by passing around the new context when needed, such as when creating a
|
|
|
new `meta_any` object:
|
|
|
|
|
|
@@ -992,18 +992,18 @@ new `meta_any` object:
|
|
|
entt::meta_any any{context, std::in_place_type<my_type>};
|
|
|
```
|
|
|
|
|
|
-Similarly, to search for meta types in a context other than the default one,
|
|
|
-it's necessary to pass it to the `resolve` function:
|
|
|
+Similarly, to search for meta-types in a context other than the default one,
|
|
|
+it is necessary to pass it to the `resolve` function:
|
|
|
|
|
|
```cpp
|
|
|
entt::meta_type type = entt::resolve(context, "reflected_type"_hs)
|
|
|
```
|
|
|
|
|
|
-More generally, when using externally managed contexts, it's always required to
|
|
|
+More generally, when using externally managed contexts, it is always required to
|
|
|
provide the system with the context to use, at least at the _entry point_.<br/>
|
|
|
-For example, once the `meta_type` instant is obtained, it's no longer necessary
|
|
|
-to pass the context around as the meta type takes the information with it and
|
|
|
+For example, once the `meta_type` instant is obtained, it is no longer necessary
|
|
|
+to pass the context around as the meta-type takes the information with it and
|
|
|
eventually propagates it to all its parts.<br/>
|
|
|
-On the other hand, it's necessary to instruct the library on where meta types
|
|
|
+On the other hand, it is necessary to instruct the library on where meta-types
|
|
|
are to be fetched when `meta_any`s and `meta_handle`s are constructed, a factory
|
|
|
-created or a meta type resolved.
|
|
|
+created or a meta-type resolved.
|