From e7e248b5260a63df46fc7993a5a85d1f2b265143 Mon Sep 17 00:00:00 2001 From: Michele Caini Date: Tue, 25 Feb 2025 12:31:07 +0100 Subject: [PATCH] doc: minor changes --- docs/md/config.md | 9 +- docs/md/container.md | 7 +- docs/md/core.md | 63 ++++++------ docs/md/entity.md | 121 +++++++++++----------- docs/md/faq.md | 20 ++-- docs/md/graph.md | 23 +++-- docs/md/lib.md | 25 +++-- docs/md/links.md | 7 +- docs/md/locator.md | 14 +-- docs/md/meta.md | 238 +++++++++++++++++++++---------------------- docs/md/poly.md | 13 +-- docs/md/process.md | 12 +-- docs/md/reference.md | 5 +- docs/md/resource.md | 21 ++-- docs/md/signal.md | 4 +- docs/md/unreal.md | 8 +- 16 files changed, 300 insertions(+), 290 deletions(-) diff --git a/docs/md/config.md b/docs/md/config.md index 02f82ef39..86a762742 100644 --- a/docs/md/config.md +++ b/docs/md/config.md @@ -22,8 +22,8 @@ respects. These variables are just one of the many ways to customize how it works.
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.
+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.
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. diff --git a/docs/md/container.md b/docs/md/container.md index 43aa0eaac..f08b27e07 100644 --- a/docs/md/container.md +++ b/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).
+It is really difficult to do better (although it is very easy to do worse, as +many examples available online demonstrate).
`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.
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.
+moment it is quite small and mainly aimed at satisfying some internal +needs.
For all containers and adaptors made available, full test coverage and stability over time is guaranteed as usual. diff --git a/docs/md/core.md b/docs/md/core.md index fc2305537..98ec7fd54 100644 --- a/docs/md/core.md +++ b/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.
+In this case, before proceeding with a comparison, it is verified that the +_type_ of the two objects is actually the same.
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.
-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.
-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; @@ -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.
+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.
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.
+dereferenced, it is not always straightforward to figure out what `value_type` +is and how to make it behave like a full-fledged pointer.
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.
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.
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.
-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 struct ignore_type {}; +template +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.
+ If it is not clear what it is, there is probably no need for this + utility.
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. diff --git a/docs/md/entity.md b/docs/md/entity.md index 88fdd0f41..d9ba26c25 100644 --- a/docs/md/entity.md +++ b/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.
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.
-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.
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.
+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.
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.
-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.
@@ -499,8 +499,8 @@ auto &storage = registry.storage("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.
-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_.
@@ -517,8 +517,8 @@ storage .on_destroy(); ``` -It goes without saying that it is possible to observe multiple events of the same -type or of different types with the same storage.
+It goes without saying that it is possible to observe multiple events of the +same type or of different types with the same storage.
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_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.
-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(); @@ -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.
+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.
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`).
+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`).
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).
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(); ``` -Because entity storage does not have a name, it cannot be retrieved via the opaque -`storage` function either.
+Because entity storage does not have a name, it cannot be retrieved via the +opaque `storage` function either.
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).
-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.
-This kind of views also allows getting the exact number of elements they are going -to return.
+This kind of views also allows getting the exact number of elements they are +going to return.
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()) { Moreover, the order of types when constructing a view does not matter. Neither does the order of views in a view pack.
-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(); @@ -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.
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.
+they do not expose a `get` member function and users should refer to the +registry that generated the view to access components.
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.
+Most of the _ECS_ available out there do not allow to create and destroy +entities and components during iterations, nor to have pointer stability.
`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().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.
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.
+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.
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.
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.
-As a result, such a view may misbehave over time if it is kept aside for a second -use.
+As a result, such a view may misbehave over time if it is kept aside for a +second use.
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. diff --git a/docs/md/faq.md b/docs/md/faq.md index bdcfe79f5..2b068ddae 100644 --- a/docs/md/faq.md +++ b/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.
-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.
@@ -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.
+likely that some classes you are working with are using standard containers +under the hood.
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.
+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.
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).
Regardless of the cause, `EnTT` offers a customization point that also serves as a solution in this case: diff --git a/docs/md/graph.md b/docs/md/graph.md index bf793b0fd..599dda712 100644 --- a/docs/md/graph.md +++ b/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.
+`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.
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.
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.
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.
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.
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.
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. diff --git a/docs/md/lib.md b/docs/md/lib.md index 634187545..c7e925c73 100644 --- a/docs/md/lib.md +++ b/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.
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.
+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.
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.
-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::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.
+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.
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.
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 diff --git a/docs/md/links.md b/docs/md/links.md index 7d9bf59ee..282f532a7 100644 --- a/docs/md/links.md +++ b/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.
@@ -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 diff --git a/docs/md/locator.md b/docs/md/locator.md index 2c6516480..67c4b2aec 100644 --- a/docs/md/locator.md +++ b/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.
+Usually, service locators are tightly bound to the services they expose. It is +hard to define a general purpose solution.
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.
+in a locator. Replacing it will not replace the element, even where a service +has been configured with a handle to the previous item.
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. diff --git a/docs/md/meta.md b/docs/md/meta.md index 3d7d48e1d..3a4029cc3 100644 --- a/docs/md/meta.md +++ b/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.
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.
-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.
+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 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`.
-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{}.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.
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{}.ctor().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.
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.
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{}.conv(); ``` -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).
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.
-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.
+Meta data members and functions are accessed by name: -* Meta-data members: +* Meta data members: ```cpp auto data = entt::resolve().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.
- 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.
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().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().base()) { @@ -293,22 +293,22 @@ for(auto &&[id, type]: entt::resolve().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.
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.
+they have no name, cannot be searched and would not have member functions to +expose anyway.
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.
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.
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.
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.
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.
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.
+* The `resize` member function allows resizing the wrapped container and returns + true in case of success.
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.
- 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.
- For example, it returns the meta-type of `int` for `std::set` while it - returns the meta-type of `std::pair` for +* The `value_type` member function returns the meta type of the elements.
+ For example, it returns the meta type of `int` for `std::set` while it + returns the meta type of `std::pair` for `std::map`. * 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.
- 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.
-To make the meta-system recognize a type as _pointer-like_, users can specialize +associated with their meta types.
+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.
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.
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 @@ -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.
-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>(); 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> { }; ``` -The reflection system does not verify the accuracy of the information nor infer a -correspondence between real types and meta-types.
+The reflection system does not verify the accuracy of the information nor infer +a correspondence between real types and meta types.
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(); ``` 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(); @@ -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.
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.
-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().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.
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.
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`.
- 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.
-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.
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{} entt::meta_factory{}.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().data("a_value"_hs).get({}).cast(); @@ -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{}.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.
-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.
-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.
+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.
+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{} @@ -878,7 +878,7 @@ entt::meta_factory{} .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{}.custom("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.
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.
-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{} @@ -912,7 +912,7 @@ entt::meta_factory{} .custom("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.
-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(); @@ -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.
-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{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}; ``` -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_.
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.
-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. diff --git a/docs/md/poly.md b/docs/md/poly.md index be7e93589..30daea986 100644 --- a/docs/md/poly.md +++ b/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.
-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 @@ -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()`.
@@ -342,9 +343,9 @@ entt::basic_poly 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.
+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.
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. diff --git a/docs/md/process.md b/docs/md/process.md index be02f917b..e7d54cd7e 100644 --- a/docs/md/process.md +++ b/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.
+Lambdas and functors cannot be used directly with a scheduler because they are +not properly defined processes with managed life cycles.
This class helps in filling the gap and turning lambdas and functors into full-featured processes usable by a scheduler. diff --git a/docs/md/reference.md b/docs/md/reference.md index 616a1b00b..041828582 100644 --- a/docs/md/reference.md +++ b/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.
+Below an incomplete list of similar projects that I have come across so +far.
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 diff --git a/docs/md/resource.md b/docs/md/resource.md index 12a9764af..4dc56e073 100644 --- a/docs/md/resource.md +++ b/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.
+Resources are not returned directly to the caller. Instead, they are wrapped in +a _resource handle_, an instance of the `entt::resource` class template.
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` (where `Type` is the actual resource type).
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.
-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.
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.
-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. diff --git a/docs/md/signal.md b/docs/md/signal.md index 63bc0efd0..43eb49baf 100644 --- a/docs/md/signal.md +++ b/docs/md/signal.md @@ -476,8 +476,8 @@ parameter for it but rather a different function: dispatcher.enqueue_hint("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 diff --git a/docs/md/unreal.md b/docs/md/unreal.md index 702268b50..094a9b4dd 100644 --- a/docs/md/unreal.md +++ b/docs/md/unreal.md @@ -37,8 +37,8 @@ this point, C++17 support should be in place.
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.
+Note that updating a *project* to C++17 does not necessarily mean that the IDE +in use will also start to recognize its syntax.
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`.
+To make this happen, create the folder `ThirdParty` under `Source` if it does +not exist already. Then, add an `EnTT` folder under `ThirdParty`.
Within the latter, create a new file `EnTT.Build.cs` with the following content: ```cs