Michele Caini преди 1 година
родител
ревизия
e7e248b526
променени са 16 файла, в които са добавени 300 реда и са изтрити 290 реда
  1. 5 4
      docs/md/config.md
  2. 4 3
      docs/md/container.md
  3. 33 30
      docs/md/core.md
  4. 61 60
      docs/md/entity.md
  5. 10 10
      docs/md/faq.md
  6. 12 11
      docs/md/graph.md
  7. 12 13
      docs/md/lib.md
  8. 4 3
      docs/md/links.md
  9. 7 7
      docs/md/locator.md
  10. 119 119
      docs/md/meta.md
  11. 7 6
      docs/md/poly.md
  12. 6 6
      docs/md/process.md
  13. 3 2
      docs/md/reference.md
  14. 11 10
      docs/md/resource.md
  15. 2 2
      docs/md/signal.md
  16. 4 4
      docs/md/unreal.md

+ 5 - 4
docs/md/config.md

@@ -22,8 +22,8 @@ respects. These variables are just one of the many ways to customize how it
 works.<br/>
 In the vast majority of cases, users will have no interest in changing the
 default parameters. For all other cases, the list of possible configurations
-with which it is possible to adjust the behavior of the library at runtime can be
-found below.
+with which it is possible to adjust the behavior of the library at runtime can
+be found below.
 
 # Definitions
 
@@ -57,8 +57,9 @@ default type if necessary.
 
 ## ENTT_SPARSE_PAGE
 
-It is known that the ECS module of `EnTT` is based on _sparse sets_. What is less
-known perhaps is that the sparse arrays are paged to reduce memory usage.<br/>
+It is known that the ECS module of `EnTT` is based on _sparse sets_. What is
+less known perhaps is that the sparse arrays are paged to reduce memory
+usage.<br/>
 Default size of pages (that is, the number of elements they contain) is 4096 but
 users can adjust it if appropriate. In all cases, the chosen value **must** be a
 power of 2.

+ 4 - 3
docs/md/container.md

@@ -12,8 +12,8 @@
 # Introduction
 
 The standard C++ library offers a wide range of containers and adaptors already.
-It is really difficult to do better (although it is very easy to do worse, as many
-examples available online demonstrate).<br/>
+It is really difficult to do better (although it is very easy to do worse, as
+many examples available online demonstrate).<br/>
 `EnTT` does not try in any way to replace what is offered by the standard. Quite
 the opposite, given the widespread use that is made of standard containers.<br/>
 However, the library also tries to fill a gap in features and functionalities by
@@ -21,7 +21,8 @@ making available some containers and adaptors initially developed for internal
 use.
 
 This section of the library is likely to grow larger over time. However, for the
-moment it is quite small and mainly aimed at satisfying some internal needs.<br/>
+moment it is quite small and mainly aimed at satisfying some internal
+needs.<br/>
 For all containers and adaptors made available, full test coverage and stability
 over time is guaranteed as usual.
 

+ 33 - 30
docs/md/core.md

@@ -118,8 +118,8 @@ The type is also used internally when comparing two `any` objects:
 if(any == empty) { /* ... */ }
 ```
 
-In this case, before proceeding with a comparison, it is verified that the _type_
-of the two objects is actually the same.<br/>
+In this case, before proceeding with a comparison, it is verified that the
+_type_ of the two objects is actually the same.<br/>
 Refer to the `EnTT` type system documentation for more details about how
 `type_info` works and the possible risks of a comparison.
 
@@ -161,9 +161,9 @@ In particular, the `data` member function invoked on a non-const instance of
 
 To cast an instance of `any` to a type, the library offers a set of `any_cast`
 functions in all respects similar to their most famous counterparts.<br/>
-The only difference is that, in the case of `EnTT`, they will not raise exceptions
-but will only trigger an assert in debug mode, otherwise resulting in undefined
-behavior in case of misuse in release mode.
+The only difference is that, in the case of `EnTT`, they will not raise
+exceptions but will only trigger an assert in debug mode, otherwise resulting in
+undefined behavior in case of misuse in release mode.
 
 ## Small buffer optimization
 
@@ -188,8 +188,8 @@ and always dynamically allocates objects (except for aliasing cases).
 
 The alignment requirement is optional and by default the most stringent (the
 largest) for any object whose size is at most equal to the one provided.<br/>
-It is provided as an optional second parameter following the desired size for the
-internal storage:
+It is provided as an optional second parameter following the desired size for
+the internal storage:
 
 ```cpp
 using my_any = entt::basic_any<sizeof(double[4]), alignof(double[4])>;
@@ -234,14 +234,14 @@ entt::compressed_pair pair{0, 3.};
 pair.first() = 42;
 ```
 
-There is not much to describe then. It is recommended to rely on documentation and
-intuition. At the end of the day, it is just a pair and nothing more.
+There is not much to describe then. It is recommended to rely on documentation
+and intuition. At the end of the day, it is just a pair and nothing more.
 
 # Enum as bitmask
 
-Sometimes it is useful to be able to use enums as bitmasks. However, enum classes
-are not really suitable for the purpose. Main problem is that they do not convert
-implicitly to their underlying type.<br/>
+Sometimes it is useful to be able to use enums as bitmasks. However, enum
+classes are not really suitable for the purpose. Main problem is that they do
+not convert implicitly to their underlying type.<br/>
 The choice is then between using old-fashioned enums (with all their problems
 that I do not want to discuss here) or writing _ugly_ code.
 
@@ -379,8 +379,8 @@ make this hard work easier.
 ## Input iterator pointer
 
 When writing an input iterator that returns in-place constructed values if
-dereferenced, it is not always straightforward to figure out what `value_type` is
-and how to make it behave like a full-fledged pointer.<br/>
+dereferenced, it is not always straightforward to figure out what `value_type`
+is and how to make it behave like a full-fledged pointer.<br/>
 Conversely, it would be very useful to have an `operator->` available on the
 iterator itself that always works without too much complexity.
 
@@ -551,8 +551,8 @@ Basically, the whole system relies on a handful of classes. In particular:
   ```
 
   In general, the `value` function exposed by `type_hash` is also `constexpr`
-  but this is not guaranteed for all compilers and platforms (although it is valid
-  with the most well-known and popular ones).
+  but this is not guaranteed for all compilers and platforms (although it is
+  valid with the most well-known and popular ones).
 
   This function **can** use non-standard features of the language for its own
   purposes. This makes it possible to provide compile-time identifiers that
@@ -685,8 +685,9 @@ value for the two types.<br/>
 Fortunately, there are several easy ways to deal with this:
 
 * The most trivial one is to define the `ENTT_STANDARD_CPP` macro. Runtime
-  identifiers do not suffer from the same problem in fact. However, this solution
-  does not work well with a plugin system, where the libraries are not linked.
+  identifiers do not suffer from the same problem in fact. However, this
+  solution does not work well with a plugin system, where the libraries are not
+  linked.
 
 * Another possibility is to specialize the `type_name` class for one of the
   conflicting types, in order to assign it a custom identifier. This is probably
@@ -695,8 +696,8 @@ Fortunately, there are several easy ways to deal with this:
 * A fully customized identifier generation policy (based for example on enum
   classes or preprocessing steps) may represent yet another option.
 
-These are just some examples of possible approaches to the problem, but there are
-many others. As already mentioned above, since users have full control over
+These are just some examples of possible approaches to the problem, but there
+are many others. As already mentioned above, since users have full control over
 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.
@@ -840,9 +841,9 @@ lists. We therefore have `value_list_element[_v]` as well as
 
 Sometimes it is 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 embrace what modern C++ has to offer.
+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 embrace what modern C++ has to offer.
 
 ## Compile-time generator
 
@@ -872,12 +873,13 @@ 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
-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
-leave the other identifiers unchanged:
+stable across different runs. If used in a production environment where a type
+needs to be removed, a placeholder can help to leave the other identifiers the
+same:
 
 ```cpp
-template<typename> struct ignore_type {};
+template<typename>
+struct ignore_type {};
 
 using id = entt::ident<
     a_type_still_valid,
@@ -964,7 +966,8 @@ life of developers:
   callable object that supports multiple types at once.
 
 * `entt::y_combinator`: this is a C++ implementation of **the** _y-combinator_.
-  If it is not clear what it is, there is probably no need for this utility.<br/>
+  If it is not clear what it is, there is probably no need for this
+  utility.<br/>
   Below is a small example to show its use:
 
   ```cpp
@@ -979,5 +982,5 @@ life of developers:
   the language does not make it possible to do much better.
 
 This is a rundown of the (actually few) utilities made available by `EnTT`. The
-list will probably grow over time, but the size of each will remain rather small,
-as has been the case so far.
+list will probably grow over time, but the size of each will remain rather
+small, as has been the case so far.

+ 61 - 60
docs/md/entity.md

@@ -99,8 +99,8 @@ It does not attempt in any way to take over on the user codebase, nor to control
 its main loop or process scheduling.<br/>
 Unlike other more or less well known models, it also makes use of independent
 pools that are extended via _static mixins_. The built-in signal support is an
-example of this flexible design: defined as a mixin, it is easily disabled if not
-needed. Similarly, the storage class has a specialization that shows how
+example of this flexible design: defined as a mixin, it is easily disabled if
+not needed. Similarly, the storage class has a specialization that shows how
 everything is customizable down to the smallest detail.
 
 ## Pay per use
@@ -404,9 +404,9 @@ There are also some limitations on what a listener can and cannot do:
 
 Please, refer to the documentation of the signal class to know about all the
 features it offers.<br/>
-There are many useful but less known functionalities that are not described here,
-such as the connection objects or the possibility to attach listeners with a
-list of parameters that are shorter than that of the signal itself.
+There are many useful but less known functionalities that are not described
+here, such as the connection objects or the possibility to attach listeners with
+a list of parameters that is shorter than that of the signal itself.
 
 ### Entity lifecycle
 
@@ -421,9 +421,9 @@ Since entity storage is unique within a registry, if a _name_ is provided it is
 ignored and therefore discarded.<br/>
 As for the function signature, this is exactly the same as the components.
 
-Entities support all types of signals: construct, destroy, and update. The latter
-is perhaps ambiguous as an entity is not truly _updated_. Rather, its identifier
-is created and finally released.<br/>
+Entities support all types of signals: construct, destroy, and update. The
+latter is perhaps ambiguous as an entity is not truly _updated_. Rather, its
+identifier is created and finally released.<br/>
 Indeed, the update signal is meant to send _general notifications_ regarding an
 entity. It can be triggered via the `patch` function, as is the case with
 components:
@@ -443,8 +443,8 @@ making it difficult for the user to write component listeners.
 
 The destruction order of the storage classes and therefore the disconnection of
 the listeners is completely random.<br/>
-There are no guarantees today, and while the logic is easily discerned, it is not
-guaranteed that it will remain so in the future.
+There are no guarantees today, and while the logic is easily discerned, it is
+not guaranteed that it will remain so in the future.
 
 For example, a listener getting disconnected after a component is discarded as a
 result of pool destruction is most likely a recipe for problems.<br/>
@@ -499,8 +499,8 @@ auto &storage = registry.storage<entt::reactive>("observer"_hs);
 
 In the latter case, there is the advantage that, in the event of destruction of
 an entity, this storage is also automatically cleaned up.<br/>
-Also note that, unlike all other storage, these classes do not support signals by
-default (although they can be enabled if necessary).
+Also note that, unlike all other storage, these classes do not support signals
+by default (although they can be enabled if necessary).
 
 Once it has been created and associated with a registry, the reactive mixin
 needs to be informed about what it should _observe_.<br/>
@@ -517,8 +517,8 @@ storage
     .on_destroy<renderable>();
 ```
 
-It goes without saying that it is possible to observe multiple events of the same
-type or of different types with the same storage.<br/>
+It goes without saying that it is possible to observe multiple events of the
+same type or of different types with the same storage.<br/>
 For example, to know which entities have been assigned or updated a component of
 a certain type:
 
@@ -749,8 +749,8 @@ const auto entity = registry.create();
 const bool tombstone = (entity == entt::tombstone);
 ```
 
-Be aware that `entt::tombstone` and entity 0 are different. Likewise, a
-zero initialized entity is not the same as `entt::tombstone`. Therefore, although
+Be aware that `entt::tombstone` and entity 0 are different. Likewise, a zero
+initialized entity is not the same as `entt::tombstone`. Therefore, although
 `entt::entity{}` is in some sense an alias for entity 0, none of them are used
 to create tombstones.
 
@@ -894,8 +894,8 @@ clazz instance;
 organizer.emplace(+[](const void *, entt::registry &) { /* ... */ }, &instance);
 ```
 
-In all cases, it is also possible to associate a name with the task when creating
-it. For example:
+In all cases, it is also possible to associate a name with the task when
+creating it. For example:
 
 ```cpp
 organizer.emplace<&free_function>("func");
@@ -911,8 +911,8 @@ constant reference to it, it is considered a read-only access. Otherwise, it is
 considered as read-write access. All functions have the registry among their
 resources.
 
-When registering a function, users can also require resources that are not in the
-list of parameters of the function itself. These are declared as template
+When registering a function, users can also require resources that are not in
+the list of parameters of the function itself. These are declared as template
 parameters:
 
 ```cpp
@@ -1015,8 +1015,8 @@ registry.ctx().erase<my_type>("my_variable"_hs);
 A context variable must be both default constructible and movable. If the
 supplied type does not match that of the variable when using a _name_, the
 operation fails.<br/>
-For all users who want to use the context but do not want to create elements, the
-`contains` and `find` functions are also available:
+For all users who want to use the context but do not want to create elements,
+the `contains` and `find` functions are also available:
 
 ```cpp
 const bool contains = registry.ctx().contains<my_type>();
@@ -1280,8 +1280,9 @@ a well known library for serialization as an archive. It uses
 [`Cereal C++`](https://uscilab.github.io/cereal/) under the hood, mainly
 because I wanted to learn how it works at the time I was writing the code.
 
-The code **is not** production-ready and it is not neither the only nor (probably)
-the best way to do it. However, feel free to use it at your own risk.<br/>
+The code **is not** production-ready and it is not neither the only nor
+(probably) the best way to do it. However, feel free to use it at your own
+risk.<br/>
 The basic idea is to store everything in a group of queues in memory, then bring
 everything back to the registry with different loaders.
 
@@ -1337,9 +1338,9 @@ performance and memory usage. However, this also has consequences that are worth
 mentioning.
 
 When an empty type is detected, it is not instantiated by default. Therefore,
-only the entities to which it is assigned are made available. There does not exist
-a way to _get_ empty types from a storage or a registry. Views and groups never
-return their instances too (for example, during a call to `each`).<br/>
+only the entities to which it is assigned are made available. There does not
+exist a way to _get_ empty types from a storage or a registry. Views and groups
+never return their instances too (for example, during a call to `each`).<br/>
 On the other hand, iterations are faster because only the entities to which the
 type is assigned are considered. Moreover, less memory is used, mainly because
 there does not exist any instance of the component, no matter how many entities
@@ -1362,8 +1363,8 @@ empty types when their optimization is enabled. Pagination is disabled as well
 as pointer stability (as not necessary).<br/>
 However, this should be preferred to using a simple sparse set. In particular,
 a void storage offers all those feature normally offered by other storage types.
-Therefore, it is a perfectly valid pool for use with views and groups or within a
-registry.
+Therefore, it is a perfectly valid pool for use with views and groups or within
+a registry.
 
 ## Entity storage
 
@@ -1418,8 +1419,8 @@ equivalent to the following:
 auto &storage = registry.storage<entt::entity>();
 ```
 
-Because entity storage does not have a name, it cannot be retrieved via the opaque
-`storage` function either.<br/>
+Because entity storage does not have a name, it cannot be retrieved via the
+opaque `storage` function either.<br/>
 It would make no sense to try anyway, given that the type of the registry and
 therefore its entity type are known regardless.
 
@@ -1507,16 +1508,16 @@ struct transform {
 
 Furthermore, it is quite common for a group of elements to be created close in
 time and therefore fallback into adjacent positions, thus favoring locality even
-on random accesses. Locality that is not sacrificed over time given the stability
-of storage positions, with undoubted performance advantages.
+on random accesses. Locality that is not sacrificed over time given the
+stability of storage positions, with undoubted performance advantages.
 
 # Meet the runtime
 
 `EnTT` takes advantage of what the language offers at compile-time. However,
 this can have its downsides (well known to those familiar with type erasure
 techniques).<br/>
-To fill the gap, the library also provides a bunch of utilities and features that
-are invaluable to handle types and pools at runtime.
+To fill the gap, the library also provides a bunch of utilities and features
+that are invaluable to handle types and pools at runtime.
 
 ## A base class to rule them all
 
@@ -1665,8 +1666,8 @@ different APIs.
 Single type views are specialized to give a performance boost in all cases.
 There is nothing as fast as a single type view. They just walk through packed
 (actually paged) arrays of elements and return them directly.<br/>
-This kind of views also allows getting the exact number of elements they are going
-to return.<br/>
+This kind of views also allows getting the exact number of elements they are
+going to return.<br/>
 Refer to the inline documentation for all the details.
 
 Multi type views iterate entities that have at least all the given components.
@@ -1871,8 +1872,8 @@ for(auto entity: registry.view<positon, velocity>()) {
 
 Moreover, the order of types when constructing a view does not matter. Neither
 does the order of views in a view pack.<br/>
-However, it is possible to _enforce_ iteration of a view by given component order
-by means of the `use` function:
+However, it is possible to _enforce_ iteration of a view by given component
+order by means of the `use` function:
 
 ```cpp
 auto view = registry.view<position, velocity>();
@@ -1904,8 +1905,8 @@ Multi type views iterate entities that have at least all the given components.
 During construction, they look at the number of elements available in each pool
 and use the smallest set in order to speed up iterations.<br/>
 They offer more or less the same functionalities of a multi type view. However,
-they do not expose a `get` member function and users should refer to the registry
-that generated the view to access components.<br/>
+they do not expose a `get` member function and users should refer to the
+registry that generated the view to access components.<br/>
 Refer to the inline documentation for all the details.
 
 Runtime views are pretty cheap to construct and should not be stored aside in
@@ -2196,8 +2197,8 @@ identifiers.
 
 ## What is allowed and what is not
 
-Most of the _ECS_ available out there do not allow to create and destroy entities
-and components during iterations, nor to have pointer stability.<br/>
+Most of the _ECS_ available out there do not allow to create and destroy
+entities and components during iterations, nor to have pointer stability.<br/>
 `EnTT` partially solves the problem with a few limitations:
 
 * Creating entities and components is allowed during iterations in most cases
@@ -2230,16 +2231,16 @@ registry.view<position>().each([&](const auto entity, auto &pos) {
 });
 ```
 
-The `each` member function will not break (because iterators remain valid) nor will
-any reference be invalidated. Instead, more attention should be paid to the
+The `each` member function will not break (because iterators remain valid) nor
+will any reference be invalidated. Instead, more attention should be paid to the
 destruction of entities or the removal of components.<br/>
 Use a common range-for loop and get components directly from the view or move
 the deletion of entities and components at the end of the function to avoid
 dangling pointers.
 
 For all types that do not offer stable pointers, iterators are also invalidated
-and the behavior is undefined if an entity is modified or destroyed and it is not
-the one currently returned by the iterator nor a newly created one.<br/>
+and the behavior is undefined if an entity is modified or destroyed and it is
+not the one currently returned by the iterator nor a newly created one.<br/>
 To work around it, possible approaches are:
 
 * Store aside the entities and the components to be removed and perform the
@@ -2261,8 +2262,8 @@ nature and the scope of the groups, it is not something in which it will happen
 to come across probably, but it is good to know it anyway.
 
 First of all, it must be said that creating components while iterating a group
-is not a problem at all and is done freely as it happens with the views. The same
-applies to the destruction of components and entities, for which the rules
+is not a problem at all and is done freely as it happens with the views. The
+same applies to the destruction of components and entities, for which the rules
 mentioned above apply.
 
 The additional limitation arises instead when a given component that is owned by
@@ -2293,13 +2294,13 @@ groups or as free types with multi type views and groups in general.
 
 # Multithreading
 
-In general, the entire registry is not thread safe as it is. Thread safety is not
-something that users should want out of the box for several reasons. Just to
+In general, the entire registry is not thread safe as it is. Thread safety is
+not something that users should want out of the box for several reasons. Just to
 mention one of them: performance.<br/>
 Views, groups and consequently the approach adopted by `EnTT` are the great
 exception to the rule. It is true that views, groups and iterators in general
-are not thread safe by themselves. Because of this users should not try to iterate
-a set of components and modify the same set concurrently. However:
+are not thread safe by themselves. Because of this users should not try to
+iterate a set of components and modify the same set concurrently. However:
 
 * As long as a thread iterates the entities that have the component `X` or
   assign and removes that component from a set of entities, another thread can
@@ -2316,9 +2317,9 @@ a set of components and modify the same set concurrently. However:
 
 This kind of entity-component systems can be used in single-threaded
 applications as well as along with async stuff or multiple threads. Moreover,
-typical thread based models for _ECS_ do not require a fully thread-safe registry
-to work. Actually, users can reach the goal with the registry as it is while
-working with most of the common models.
+typical thread based models for _ECS_ do not require a fully thread-safe
+registry to work. Actually, users can reach the goal with the registry as it is
+while working with most of the common models.
 
 Because of the few reasons mentioned above and many others not mentioned, users
 are completely responsible for synchronization whether required. On the other
@@ -2378,8 +2379,8 @@ registry.
 Returned views are always valid and behave as expected in the context of the
 caller. However, they may contain dangling references to non-existing storage
 when created from a const registry.<br/>
-As a result, such a view may misbehave over time if it is kept aside for a second
-use.<br/>
+As a result, such a view may misbehave over time if it is kept aside for a
+second use.<br/>
 Therefore, if the general advice is to create views when necessary and discard
 them immediately afterwards, this becomes almost a rule when it comes to views
 generated from a const registry.
@@ -2400,5 +2401,5 @@ things could be forgotten, others could have been omitted on purpose to reduce
 the size of this file. Unfortunately, some parts may even be outdated and still
 to be updated.
 
-For further information, it is recommended to refer to the documentation included
-in the code itself or join the official channels to ask a question.
+For further information, it is recommended to refer to the documentation
+included in the code itself or join the official channels to ask a question.

+ 10 - 10
docs/md/faq.md

@@ -16,8 +16,8 @@
 
 This is a constantly updated section where I am trying to put the answers to the
 most frequently asked questions.<br/>
-If you do not find your answer here, there are two cases: nobody has done it yet, 
-or this section needs updating. In both cases, you can
+If you do not find your answer here, there are two cases: nobody has done it
+yet, or this section needs updating. In both cases, you can
 [open a new issue](https://github.com/skypjack/entt/issues/new) or enter either
 the [gitter channel](https://gitter.im/skypjack/entt) or the
 [discord server](https://discord.gg/5BjPWBd) to ask for help.<br/>
@@ -30,8 +30,8 @@ part of the documentation.
 
 `EnTT` is an experimental project that I also use to keep me up-to-date with the
 latest revision of the language and the standard library. For this reason, it is
-likely that some classes you are working with are using standard containers under
-the hood.<br/>
+likely that some classes you are working with are using standard containers
+under the hood.<br/>
 Unfortunately, it is known that the standard containers are not particularly
 performing in debugging (the reasons for this go beyond this document) and are
 even less so on Windows, apparently. Fortunately, this can also be mitigated a
@@ -119,9 +119,9 @@ more details.
 ## The standard and the non-copyable types
 
 `EnTT` uses internally the trait `std::is_copy_constructible_v` to check if a
-component is actually copyable. However, this trait does not really check whether
-a type is actually copyable. Instead, it just checks that a suitable copy
-constructor and copy operator exist.<br/>
+component is actually copyable. However, this trait does not really check
+whether a type is actually copyable. Instead, it just checks that a suitable
+copy constructor and copy operator exist.<br/>
 This can lead to surprising results due to some idiosyncrasies of the standard.
 
 For example, `std::vector` defines a copy constructor that is conditionally
@@ -184,9 +184,9 @@ owned by the entity that is destroyed.
 
 ## Duplicate storage for the same component
 
-It is rare, but you can see double sometimes, especially when it comes to storage.
-This can be caused by a conflict in the hash assigned to the various component
-types (one of a kind) or by bugs in your compiler
+It is rare, but you can see double sometimes, especially when it comes to
+storage. This can be caused by a conflict in the hash assigned to the various
+component types (one of a kind) or by bugs in your compiler
 ([more common](https://github.com/skypjack/entt/issues/1063) apparently).<br/>
 Regardless of the cause, `EnTT` offers a customization point that also serves as
 a solution in this case:

+ 12 - 11
docs/md/graph.md

@@ -14,8 +14,9 @@
 
 # Introduction
 
-`EnTT` does not aim to offer everything one needs to work with graphs. Therefore,
-anyone looking for this in the _graph_ submodule will be disappointed.<br/>
+`EnTT` does not aim to offer everything one needs to work with graphs.
+Therefore, anyone looking for this in the _graph_ submodule will be
+disappointed.<br/>
 Quite the opposite is true though. This submodule is minimal and contains only
 the data structures and algorithms strictly necessary for the development of
 some tools such as the _flow builder_.
@@ -182,8 +183,8 @@ user wants to rely on that.<br/>
 However, being an integral value, it leaves the user full freedom to rely on his
 own tools if necessary.
 
-Once a task is associated with the flow builder, it has also assigned read-only or
-read-write resources as appropriate:
+Once a task is associated with the flow builder, it has also assigned read-only
+or read-write resources as appropriate:
 
 ```cpp
 builder
@@ -249,7 +250,7 @@ What happens here is that the resource first _sees_ a read-only access request
 from the first task, then a read-only request from the second task and finally
 a read-write request from the first task.<br/>
 Although this definition would probably be counted as an error, the resulting
-graph may be unexpected. This, in fact, consists of a single edge outgoing from
+graph may be unexpected. In fact, this consists of a single edge outgoing from
 the second task and directed to the first task.<br/>
 To intuitively understand what happens, it is enough to think of the fact that a
 task never has an edge pointing to itself.
@@ -279,15 +280,15 @@ otherwise inaccessible.
 
 ## Fake resources and order of execution
 
-The flow builder does not offer the ability to specify when a task should execute
+The flow builder does not offer the ability to specify when a task should run
 before or after another task.<br/>
 In fact, the order of _registration_ on the resources also determines the order
 in which the tasks are processed during the generation of the execution graph.
 
 However, there is a way to _force_ the execution order of two processes.<br/>
 Briefly, since accessing a resource in opposite modes requires sequential rather
-than parallel scheduling, it is possible to make use of fake resources to rule on
-the execution order:
+than parallel scheduling, it is possible to make use of fake resources to rule
+on the execution order:
 
 ```cpp
 builder
@@ -361,6 +362,6 @@ for(auto &&vertex: graph) {
 }
 ```
 
-Then it is possible to instantiate an execution graph by means of other functions
-such as `out_edges` to retrieve the children of a given task or `edges` to get
-the identifiers.
+Then it is possible to instantiate an execution graph by means of other
+functions such as `out_edges` to retrieve the children of a given task or
+`edges` to get the identifiers.

+ 12 - 13
docs/md/lib.md

@@ -20,14 +20,12 @@ Fortunately, nowadays `EnTT` works smoothly across boundaries.
 Many classes in `EnTT` make extensive use of type erasure for their purposes.
 This raises the need to identify objects whose type has been erased.<br/>
 The `type_hash` class template is how identifiers are generated and thus made
-available to the rest of the library.
-In general, this class arouses little interest.
-The only exception is when a conflict between identifiers occurs
-(definitely uncommon though) or when the default solution proposed by `EnTT`
-is not suitable for the user's purposes.<br/>
+available to the rest of the library. In general, this class arouses little
+interest. The only exception is when a conflict between identifiers occurs
+(definitely uncommon though) or when the default solution proposed by `EnTT` is
+not suitable for the user's purposes.<br/>
 The section dedicated to `type_info` contains all the details to get around the
-issue in a concise and elegant way.
-Please refer to the specific documentation.
+issue in a concise and elegant way. Please refer to the specific documentation.
 
 When working with linked libraries, compile definitions `ENTT_API_EXPORT` and
 `ENTT_API_IMPORT` are to import or export symbols, so as to make everything work
@@ -44,9 +42,9 @@ 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 is linked already to a static context to which the elements are attached
-and different contexts do not relate to each other, they must be _shared_ to
-allow the use of meta types across boundaries.
+Since it is linked already to a static context to which the elements are
+attached and different contexts do not relate to each other, they must be
+_shared_ to allow the use of meta types across boundaries.
 
 Fortunately, sharing a context is also trivial to do. First of all, the local
 one is acquired in the main space:
@@ -62,8 +60,8 @@ thus discarding or storing aside the local one:
 entt::locator<entt::meta_ctx>::reset(handle);
 ```
 
-From now on, both spaces refer to the same context and to it are all
-new meta-types attached, no matter where they are created.<br/>
+From now on, both spaces refer to the same context and to it are all new meta
+types attached, no matter where they are created.<br/>
 Note that _replacing_ the main context does not also propagate changes across
 boundaries. In other words, replacing a context results in the decoupling of the
 two sides and therefore a divergence in the contents.
@@ -83,7 +81,8 @@ is unknown to the former, a dedicated pool is created within the registry on
 first use.<br/>
 As one can guess, this pool is instantiated on a different side of the boundary
 from the `registry`. Therefore, the instance is now managing memory from
-different spaces, and this can quickly lead to crashes if not properly addressed.
+different spaces, and this can quickly lead to crashes if not properly
+addressed.
 
 To overcome the risk, it is recommended to use well-defined interfaces that make
 fundamental types pass through the boundaries, isolating the instances of the

+ 4 - 3
docs/md/links.md

@@ -14,8 +14,8 @@
 `EnTT` is widely used in private and commercial applications. I cannot even
 mention most of them because of some signatures I put on some documents time
 ago. Fortunately, there are also people who took the time to implement open
-source projects based on `EnTT` and did not hold back when it came to documenting
-them.
+source projects based on `EnTT` and did not hold back when it came to
+documenting them.
 
 Below an incomplete list of games, applications and articles that can be used as
 a reference.<br/>
@@ -97,7 +97,8 @@ I hope the following lists can grow much more in the future.
     by Quake.
   * [Destroid](https://github.com/tyrannicaltoucan/destroid): _one-bazillionth_
     arcade game about shooting dirty rocks in space, inspired by Asteroids.
-  * [Wanderer](https://github.com/albin-johansson/wanderer): a 2D exploration-based indie game.
+  * [Wanderer](https://github.com/albin-johansson/wanderer): a 2D
+    exploration-based indie game.
   * [Spelunky® Classic remake](https://github.com/dbeef/spelunky-psp): a truly
     multiplatform experience with a rewrite from scratch.
   * [CubbyTower](https://github.com/utilForever/CubbyTower): a simple tower

+ 7 - 7
docs/md/locator.md

@@ -8,8 +8,8 @@
 
 # Introduction
 
-Usually, service locators are tightly bound to the services they expose.
-It is hard to define a general purpose solution.<br/>
+Usually, service locators are tightly bound to the services they expose. It is
+hard to define a general purpose solution.<br/>
 This tiny class tries to fill the gap and gets rid of the burden of defining a
 different specific locator for each application.
 
@@ -74,9 +74,9 @@ and use them with other locators. Of course, all a user will get is to have an
 uninitialized service elsewhere as well.
 
 Note that exporting a service allows users to _share_ the object currently set
-in a locator. Replacing it will not replace the element, even where a service has
-been configured with a handle to the previous item.<br/>
+in a locator. Replacing it will not replace the element, even where a service
+has been configured with a handle to the previous item.<br/>
 In other words, if an audio service is replaced with a null object to silence an
-application and the original service was shared, this operation will not propagate
-to the other locators. Therefore, a module that shares the ownership of the
-original audio service is still able to emit sounds.
+application and the original service was shared, this operation will not
+propagate to the other locators. Therefore, a module that shares the ownership
+of the original audio service is still able to emit sounds.

+ 119 - 119
docs/md/meta.md

@@ -29,19 +29,19 @@ looked for a third-party library that met my needs on the subject, but I always
 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 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
+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 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 are numeric. It does not matter if they are generated at runtime, at
-compile-time or with custom functions.
+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 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
@@ -74,20 +74,20 @@ 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 is 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 do not want
-to also make the type _searchable_. In this case, it is sufficient not to invoke
-`type`.
+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 is
 generally used to create the following:
@@ -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,15 +177,15 @@ 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
@@ -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 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:
+its id). These 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/>
+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 is 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:
@@ -270,11 +270,11 @@ Meta-data members and functions are accessed by name:
   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 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
+  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,9 +283,9 @@ if(auto func = entt::resolve<my_type>().func("member"_hs); func) {
 }
 ```
 
-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:
+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:
 
 ```cpp
 for(auto &&[id, type]: entt::resolve<my_type>().base()) {
@@ -293,22 +293,22 @@ for(auto &&[id, type]: entt::resolve<my_type>().base()) {
 }
 ```
 
-Meta-types 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 have no name, cannot be searched and would not have member functions to expose
-anyway.<br/>
+they have no name, cannot be searched and would not have member functions to
+expose anyway.<br/>
 Similarly, conversion functions are not directly accessible. They are used
-internally by `meta_any` and the meta-objects when needed.
+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
@@ -316,7 +316,7 @@ Refer to the inline documentation for further details.
 The runtime reflection system also supports containers of all types.<br/>
 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
@@ -334,10 +334,10 @@ particular:
 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
@@ -358,24 +358,24 @@ 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 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
+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 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
+sufficient to assign a container for which a specialization of the _traits_
 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 resizing the wrapped container and
-  returns true in case of success.<br/>
+* The `resize` member function allows resizing the wrapped container and returns
+  true in case of success.<br/>
   For example, it is not possible to resize fixed size containers.
 
 * The `clear` member function allows clearing the wrapped container and returns
@@ -398,8 +398,8 @@ 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 do not offer an indirection operator
-  on purpose.
+  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
   accepts a meta iterator and the element to insert:
@@ -456,15 +456,15 @@ 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
@@ -490,8 +490,8 @@ differences in behavior in the case of key-only containers. In particular:
   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 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 do not offer an indirection operator
-  on purpose.
+  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
   is therefore returned by copy, the value (if any) is wrapped by an instance of
@@ -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, the key and the value to insert:
 
   ```cpp
   auto last = view.end();
@@ -519,8 +519,8 @@ 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 is not at least
-  convertible to the required type.
+  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
   argument, the key of the element to return:
@@ -537,11 +537,11 @@ Container support is minimal but likely sufficient to satisfy all needs.
 
 ## Pointer-like types
 
-As with containers, it is 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:
 
@@ -553,25 +553,25 @@ 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 is
+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 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
+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
@@ -580,8 +580,8 @@ 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 do not offer an `operator*`. In particular:
 
-* It is possible to exploit a solution based on ADL lookup by offering a function
-  (also a template one) named `dereference_meta_pointer_like`:
+* It is possible to exploit a solution based on ADL lookup by implementing a
+  function (also a template one) named `dereference_meta_pointer_like`:
 
   ```cpp
   template<typename Type>
@@ -608,24 +608,24 @@ 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
+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
+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 is 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);
 }
 ```
@@ -657,8 +657,8 @@ struct entt::meta_template_traits<function_type<Ret(Args...)>> {
 };
 ```
 
-The reflection system does not 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>();
@@ -715,21 +715,21 @@ 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 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
@@ -770,10 +770,10 @@ There are a few alternatives available at the moment:
   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
@@ -810,8 +810,8 @@ obvious corner cases that can in turn be solved with the use of policies.
 
 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 is 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 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
-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:
+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 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:
 
 ```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");
@@ -901,10 +901,10 @@ 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 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
@@ -930,8 +930,8 @@ 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 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>();
@@ -944,7 +944,7 @@ entt::meta_reset("my_type"_hs);
 ```
 
 Finally, there exists a non-template overload of the `meta_reset` function that
-does not 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,7 +954,7 @@ 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
@@ -971,12 +971,12 @@ std::swap(context, other);
 ```
 
 This is useful for testing purposes or to define multiple context objects with
-different meta-types to use as appropriate.
+different meta types to use as appropriate.
 
 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 is not 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,7 +992,7 @@ 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,
+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
@@ -1002,8 +1002,8 @@ entt::meta_type type = entt::resolve(context, "reflected_type"_hs)
 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 is no longer necessary
-to pass the context around as the meta-type takes the information with it and
+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 is 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.

+ 7 - 6
docs/md/poly.md

@@ -253,8 +253,8 @@ in appending the new functions to the previous list.
 
 As for a defined concept instead, the list of types is _extended_ in a similar
 way to what is shown for the implementation of the above concept.<br/>
-To do this, it is useful to declare a function that allows to convert a _concept_
-into its underlying `type_list` object:
+To do this, it is useful to declare a function that allows to convert a
+_concept_ into its underlying `type_list` object:
 
 ```cpp
 template<typename... Type>
@@ -320,7 +320,8 @@ drawable other = instance.as_ref();
 ```
 
 In both cases, although the interface of the `poly` object does not change, it
-does not construct any element or take care of destroying the referenced objects.
+does not construct any element or take care of destroying the referenced
+objects.
 
 Note also how the underlying concept is accessed via a call to `operator->` and
 not directly as `instance.draw()`.<br/>
@@ -342,9 +343,9 @@ entt::basic_poly<Drawable, sizeof(double[4]), alignof(double[4])>
 
 The default size is `sizeof(double[2])`, which seems like a good compromise
 between a buffer that is too large and one unable to hold anything larger than
-an integer. The alignment requirement is optional, and by default such that it is
-the most stringent (the largest) for any object whose size is at most equal to
-the one provided.<br/>
+an integer. The alignment requirement is optional, and by default such that it
+is the most stringent (the largest) for any object whose size is at most equal
+to the one provided.<br/>
 It is worth noting that providing a size of 0 (which is an accepted value in all
 respects) will force the system to dynamically allocate the contained objects in
 all cases.

+ 6 - 6
docs/md/process.md

@@ -22,8 +22,8 @@ CRTP idiom. Moreover, derived classes specify what the intended type for elapsed
 times is.
 
 A process should expose publicly the following member functions whether needed
-(note that it is not required to define a function unless the derived class wants
-to _override_ the default behavior):
+(note that it is not required to define a function unless the derived class
+wants to _override_ the default behavior):
 
 * `void update(Delta, void *);`
 
@@ -36,8 +36,8 @@ to _override_ the default behavior):
 * `void init();`
 
   This is invoked when the process joins the running queue of a scheduler. It
-  happens usually as soon as the process is attached to the scheduler if it is a
-  top level one, otherwise when it replaces its parent if it is a _continuation_.
+  happens usually when the process is attached to the scheduler if it is a top
+  level one, or when it replaces its parent if it is a _continuation_.
 
 * `void succeeded();`
 
@@ -87,8 +87,8 @@ private:
 
 ## Adaptor
 
-Lambdas and functors cannot be used directly with a scheduler because they are not
-properly defined processes with managed life cycles.<br/>
+Lambdas and functors cannot be used directly with a scheduler because they are
+not properly defined processes with managed life cycles.<br/>
 This class helps in filling the gap and turning lambdas and functors into
 full-featured processes usable by a scheduler.
 

+ 3 - 2
docs/md/reference.md

@@ -19,7 +19,8 @@ I hope the following lists can grow much more in the future.
 
 # Similar projects
 
-Below an incomplete list of similar projects that I have come across so far.<br/>
+Below an incomplete list of similar projects that I have come across so
+far.<br/>
 If some terms or designs are not clear, I recommend referring to the
 [_ECS Back and Forth_](https://skypjack.github.io/tags/#ecs) series for all the
 details.
@@ -56,7 +57,7 @@ details.
   * [Massive ECS](https://github.com/nilpunch/massive): sparse set based ECS
     featuring rollbacks.
   * [Svelto.ECS](https://github.com/sebas77/Svelto.ECS): a very interesting
-    platform-agnostic- and table-based ECS framework.
+    platform-agnostic and table-based ECS framework.
 
 * Go:
   * [gecs](https://github.com/tutumagi/gecs): a sparse sets based ECS inspired 

+ 11 - 10
docs/md/resource.md

@@ -31,7 +31,8 @@ The _resource_ is an image, an audio, a video or any other type:
 struct my_resource { const int value; };
 ```
 
-The _loader_ is a callable type, the aim of which is to load a specific resource:
+The _loader_ is a callable type, the aim of which is to load a specific
+resource:
 
 ```cpp
 struct my_loader final {
@@ -68,8 +69,8 @@ discarded when a player leaves it.
 
 ## Resource handle
 
-Resources are not returned directly to the caller. Instead, they are wrapped in a
-_resource handle_, an instance of the `entt::resource` class template.<br/>
+Resources are not returned directly to the caller. Instead, they are wrapped in
+a _resource handle_, an instance of the `entt::resource` class template.<br/>
 For those who know the _flyweight design pattern_ already, that is exactly what
 it is. To all others, this is the time to brush up on some notions instead.
 
@@ -98,8 +99,8 @@ When using the default handle, it expects a resource type which is convertible
 to or suitable for constructing an `std::shared_ptr<Type>` (where `Type` is the
 actual resource type).<br/>
 In other terms, the loader should return shared pointers to the given resource
-type. However, this is not mandatory. Users can easily get around this constraint
-by specializing both the handle and the loader.
+type. However, this is not mandatory. Users can easily get around this
+constraint by specializing both the handle and the loader.
 
 A cache forwards all its arguments to the loader if required. This means that
 loaders can also support tag dispatching to offer different loading policies:
@@ -158,9 +159,9 @@ functions (such as `contains` or `erase`).
 Set aside the part of the API that this class _shares_ with a map, it also adds
 something on top of it in order to address the most common requirements of a
 resource cache.<br/>
-In particular, it does not have an `emplace` member function which is replaced by
-`load` and `force_load` instead (where the former loads a new resource only if
-not present while the second triggers a forced loading in any case):
+In particular, it does not have an `emplace` member function which is replaced
+by `load` and `force_load` instead (where the former loads a new resource only
+if not present while the second triggers a forced loading in any case):
 
 ```cpp
 auto ret = cache.load("resource/id"_hs);
@@ -181,5 +182,5 @@ operators return resource handles rather than instances of the mapped type.<br/>
 Since the cache has no control over the loader and a resource is not required to
 also be convertible to bool, these handles can be invalid. This usually means an
 error in the user logic, but it may also be an _expected_ event.<br/>
-It is therefore recommended to verify handles validity with a check in debug (for
-example, when loading) or an appropriate logic in retail.
+It is therefore recommended to verify handles validity with a check in debug
+(for example, when loading) or an appropriate logic in retail.

+ 2 - 2
docs/md/signal.md

@@ -476,8 +476,8 @@ parameter for it but rather a different function:
 dispatcher.enqueue_hint<an_event>("custom"_hs, 42);
 ```
 
-This is mainly due to the template argument deduction rules, and unfortunately, 
-there is no real (elegant) way to avoid it.
+This is mainly due to the template argument deduction rules, and there is no
+real (elegant) way to avoid it.
 
 # Event emitter
 

+ 4 - 4
docs/md/unreal.md

@@ -37,8 +37,8 @@ this point, C++17 support should be in place.<br/>
 Try to compile the project to ensure it works as expected before following
 further steps.
 
-Note that updating a *project* to C++17 does not necessarily mean that the IDE in
-use will also start to recognize its syntax.<br/>
+Note that updating a *project* to C++17 does not necessarily mean that the IDE
+in use will also start to recognize its syntax.<br/>
 If the plan is to use C++17 in the project too, check the specific instructions
 for the IDE in use.
 
@@ -62,8 +62,8 @@ Source
       \---entt (GitHub repository content inside)
 ```
 
-To make this happen, create the folder `ThirdParty` under `Source` if it does not
-exist already. Then, add an `EnTT` folder under `ThirdParty`.<br/>
+To make this happen, create the folder `ThirdParty` under `Source` if it does
+not exist already. Then, add an `EnTT` folder under `ThirdParty`.<br/>
 Within the latter, create a new file `EnTT.Build.cs` with the following content:
 
 ```cs