Ver Fonte

doc: meta

Michele Caini há 3 anos atrás
pai
commit
3e29617da8
3 ficheiros alterados com 79 adições e 107 exclusões
  1. 0 3
      TODO
  2. 14 25
      docs/md/lib.md
  3. 65 79
      docs/md/meta.md

+ 0 - 3
TODO

@@ -11,9 +11,6 @@ DOC:
 * examples (and credits) from @alanjfs :)
 * update entity doc when the storage based model is in place
 
-TODO:
-* update doc (meta, lib)
-
 WIP:
 * get rid of observers, storage based views made them pointless - document alternatives
 * add storage getter for filters to views and groups

+ 14 - 25
docs/md/lib.md

@@ -50,40 +50,29 @@ However, what is offered should hopefully serve as a basis for all of them.
 
 The runtime reflection system deserves a special mention when it comes to using
 it across boundaries.<br/>
-Since it's linked already to a static context to which the visible components
-are attached and different contexts don't relate to each other, they must be
-_shared_ to allow the use of meta types across boundaries.
+Since it's linked already to a static context to which the elements are attached
+and different contexts don't relate to each other, they must be _shared_ to
+allow the use of meta types across boundaries.
 
-Sharing a context is trivial though. First of all, the local one must be
-acquired in the main space:
+Fortunately, sharing a context is also trivial to do. First of all, the local
+one is acquired in the main space:
 
 ```cpp
-entt::meta_ctx ctx{};
+auto handle = entt::locator<entt::meta_ctx>::handle();
 ```
 
-Then, it must passed to the receiving space that will set it as its global
-context, thus releasing the local one that remains available but is no longer
-referred to by the runtime reflection system:
+Then, it's passed to the receiving space that sets it as its default context,
+thus discarding or storing aside the local one:
 
 ```cpp
-entt::meta_ctx::bind(ctx);
+entt::locator<entt::meta_ctx>::reset(handle);
 ```
 
-From now on, both spaces will refer to the same context and on it will be
-attached the new visible meta types, no matter where they are created.<br/>
-A context can also be reset and then associated again locally as:
-
-```cpp
-entt::meta_ctx::bind(entt::meta_ctx{});
-```
-
-This is allowed because local and global contexts are separated. Therefore, it's
-always possible to make the local context the current one again.
-
-Before to release a context, all locally registered types should be reset to
-avoid dangling references. Otherwise, if a type is accessed from another space
-by name, there could be an attempt to address its parts that are no longer
-available.
+From now on, both spaces refer to the same context and on it are attached all
+new meta types, no matter where they are created.<br/>
+Note that resetting the main context doesn't also propagate changes across
+boundaries. In other words, resetting a context results in the decoupling of the
+two sides and therefore a divergence in the contents.
 
 ## Memory Management
 

+ 65 - 79
docs/md/meta.md

@@ -20,6 +20,7 @@
   * [Named constants and enums](#named-constants-and-enums)
   * [Properties and meta objects](#properties-and-meta-objects)
   * [Unregister types](#unregister-types)
+  * [Meta context](#meta-context)
 <!--
 @endcond TURN_OFF_DOXYGEN
 -->
@@ -43,7 +44,7 @@ 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 are numeric. It doesn't matter if they are generated at runtime, at
+long as they're numeric. It doesn't matter if they're generated at runtime, at
 compile-time or with custom functions.
 
 That being said, the examples in the following sections are all based on the
@@ -55,10 +56,10 @@ follows:
 auto factory = entt::meta<my_type>().type("reflected_type"_hs);
 ```
 
-For what it's worth, this is likely completely equivalent to:
+For what it's worth, this is completely equivalent to:
 
 ```cpp
-auto factory = entt::meta<my_type>().type(42);
+auto factory = entt::meta<my_type>().type(42u);
 ```
 
 Obviously, human-readable identifiers are more convenient to use and highly
@@ -76,18 +77,15 @@ type to reflect as a template parameter:
 auto factory = entt::meta<my_type>();
 ```
 
-This isn't enough to _export_ the given type and make it visible though.<br/>
 The returned value is a factory object to use to continue building the meta
-type. In order to make the type _visible_, users can assign it an identifier:
+type.
 
-```cpp
-auto factory = entt::meta<my_type>().type("reflected_type"_hs);
-```
-
-Or use the default one, that is, the built-in identifier for the given type:
+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:
 
 ```cpp
-auto factory = entt::meta<my_type>().type();
+auto factory = entt::meta<my_type>().type("reflected_type"_hs);
 ```
 
 Identifiers are important because users can retrieve meta types at runtime by
@@ -263,20 +261,20 @@ the reflected types at once. It returns an iterable object that can be used in a
 range-for loop:
 
 ```cpp
-for(auto type: entt::resolve()) {
+for(auto &&[id, type]: entt::resolve()) {
     // ...
 }
 ```
 
-In all cases, the returned value is an instance of `meta_type`. 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 of the underlying
-type.<br/>
+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
+of the underlying type.<br/>
 Refer to the inline documentation for all the details.
 
-The meta objects that compose a meta type are accessed in the following ways:
+Meta data members and functions are accessed by name among the other things:
 
-* _Meta data_. They are accessed by _name_:
+* Meta data members:
 
   ```cpp
   auto data = entt::resolve<my_type>().data("member"_hs);
@@ -288,7 +286,7 @@ The meta objects that compose a meta type are accessed in the following ways:
   know if it's a const or a static one), to get the meta type of the variable
   and to set or get the contained value.
 
-* _Meta functions_. They are accessed by _name_:
+* Meta function members:
 
   ```cpp
   auto func = entt::resolve<my_type>().func("member"_hs);
@@ -302,16 +300,7 @@ The meta objects that compose a meta type are accessed in the following ways:
   addition, a meta function object can be used to invoke the underlying function
   and then get the return value in the form of a `meta_any` object.
 
-* _Meta bases_. They are accessed through the _name_ of the base types:
-
-  ```cpp
-  auto base = entt::resolve<derived_type>().base("base"_hs);
-  ```
-
-  The returned type is `meta_type` and may be invalid if there is no meta base
-  object associated with the given identifier.
-
-All the objects thus obtained as well as the meta types can be explicitly
+All the meta objects thus obtained as well as the meta types can be explicitly
 converted to a boolean value to check if they are valid:
 
 ```cpp
@@ -320,16 +309,17 @@ if(auto func = entt::resolve<my_type>().func("member"_hs); func) {
 }
 ```
 
-Furthermore, all them are also returned by specific overloads that provide the
-caller with iterable ranges of top-level elements. As an example:
+Furthermore, all 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:
 
 ```cpp
-for(auto data: entt::resolve<my_type>().data()) {
+for(auto &&[id, type]: entt::resolve<my_type>().base()) {
     // ...
 }
 ```
 
-A meta type can be used to `construct` actual instances of the underlying
+A meta type can also be 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
@@ -366,6 +356,7 @@ particular:
 
 * `std::vector`, `std::array`, `std::deque` and `std::list` (but not
   `std::forward_list`) are supported as _sequence containers_.
+
 * `std::map`, `std::set` and their unordered counterparts are supported as
   _associative containers_.
 
@@ -905,7 +896,7 @@ Sometimes (for example, when it comes to creating an editor) it might be useful
 to attach properties to the meta objects created. Fortunately, this is possible
 for most of them.<br/>
 For the meta objects that support properties, the member functions of the
-factory used for registering them will return a decorated version of the factory
+factory used for registering them will return an extended version of the factory
 itself. The latter can be used to attach properties to the last created meta
 object.<br/>
 Apparently, it's more difficult to say than to do:
@@ -914,41 +905,19 @@ Apparently, it's more difficult to say than to do:
 entt::meta<my_type>().type("reflected_type"_hs).prop("tooltip"_hs, "message");
 ```
 
-Properties are always in the key/value form. There are no restrictions on the
-type of the key or value, as long as they are copy constructible objects.<br/>
-Multiple formats are supported when it comes to defining a property:
-
-* Properties as key/value pairs:
-
-  ```cpp
-  entt::meta<my_type>().type("reflected_type"_hs).prop("tooltip"_hs, "message");
-  ```
-
-* Properties as `std::pair`s:
-
-  ```cpp
-  entt::meta<my_type>().type("reflected_type"_hs).prop(std::make_pair("tooltip"_hs, "message"));
-  ```
-
-* Key only properties:
-
-  ```cpp
-  entt::meta<my_type>().type("reflected_type"_hs).prop(my_enum::key_only);
-  ```
-
-* Properties as `std::tuple`s:
+Properties are always in the key/value form. The key is a numeric identifier,
+mostly similar to the identifier used to register meta objects. There are no
+restrictions on the type of the value instead, as long as it's movable.<br/>
+Key only properties are also supported out of the box:
 
-  ```cpp
-  entt::meta<my_type>().type("reflected_type"_hs).prop(std::make_tuple(std::make_pair("tooltip"_hs, "message"), my_enum::key_only));
-  ```
-
-  A tuple contains one or more properties. All of them are treated individually.
+```cpp
+entt::meta<my_type>().type("reflected_type"_hs).prop(my_enum::key_only);
+```
 
-Note that it's not possible to invoke `prop` multiple times for the same meta
-object and trying to do that will result in a compilation error.<br/>
-However, the `props` function is available to associate several properties at
-once. In this case, properties in the key/value form aren't allowed, since they
-would be interpreted as two different properties rather than a single one.
+To attach multiple properties to a meta object, it's possible to invoke `prop`
+more than once.<br/>
+It's also possible to invoke `prop` at different times, as long as the factory
+is reset to the meta object of interest.
 
 The meta objects for which properties are supported are currently meta types,
 meta data and meta functions.<br/>
@@ -957,7 +926,7 @@ properties at once or to search a specific property by key:
 
 ```cpp
 // iterate all properties of a meta type
-for(auto prop: entt::resolve<my_type>().prop()) {
+for(auto &&[id, prop]: entt::resolve<my_type>().prop()) {
     // ...
 }
 
@@ -966,37 +935,54 @@ auto prop = entt::resolve<my_type>().prop("tooltip"_hs);
 ```
 
 Meta properties are objects having a fairly poor interface, all in all. They
-only provide the `key` and the `value` member functions to be used to retrieve
-the key and the value contained in the form of `meta_any` objects, respectively.
+only provide the `value` member function to retrieve the contained value in the
+form of a `meta_any` object.
 
 ## Unregister types
 
 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
-necessarily depend on it. Similarly, implicitly generated types (as an example,
-the meta types implicitly generated for function parameters when needed) aren't
-unregistered.<br/>
+necessarily depend on it.<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:
+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 if required:
+It's 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 argument and resets all searchable types (that is, all types that
-were assigned an unique identifier):
+doesn't accept arguments and resets all meta types at once:
 
 ```cpp
 entt::meta_reset();
 ```
 
-All types can be re-registered later with a completely different name and form.
+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
+_context_. This can be reached 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.
+However, users can replace an existing context with another at any time:
+
+```cpp
+entt::meta_context other{};
+auto &&context = entt::locator<entt::meta_context>::value_or();
+std::swap(context, other);
+```
+
+This can be useful for testing purposes or to define multiple contexts with
+different meta objects to be used as appropriate.