Michele Caini vor 3 Jahren
Ursprung
Commit
498e02f154
1 geänderte Dateien mit 128 neuen und 153 gelöschten Zeilen
  1. 128 153
      docs/md/core.md

+ 128 - 153
docs/md/core.md

@@ -46,25 +46,24 @@
 # Introduction
 
 `EnTT` comes with a bunch of core functionalities mostly used by the other parts
-of the library itself.<br/>
-Hardly users will include these features in their code, but it's worth
-describing what `EnTT` offers so as not to reinvent the wheel in case of need.
+of the library.<br/>
+Many of these tools are also useful in everyday work. Therefore, it's worth
+describing them so as not to reinvent the wheel in case of need.
 
 # Any as in any type
 
-`EnTT` comes with its own `any` type. It may seem redundant considering that
-C++17 introduced `std::any`, but it is not (hopefully).<br/>
+`EnTT` offers its own `any` type. It may seem redundant considering that C++17
+introduced `std::any`, but it is not (hopefully).<br/>
 First of all, the _type_ returned by an `std::any` is a const reference to an
 `std::type_info`, an implementation defined class that's not something everyone
-wants to see in a software. Furthermore, there is no way to connect it with the
-type system of the library and therefore with its integrated RTTI support.<br/>
-Note that this class is largely used internally by the library itself.
+wants to see in a software. Furthermore, there is no way to bind it to the type
+system of the library and therefore with its integrated RTTI support.
 
-The API is very similar to that of its most famous counterpart, mainly because
-this class serves the same purpose of being an opaque container for any type of
-value.<br/>
-Instances of `any` also minimize the number of allocations by relying on a well
-known technique called _small buffer optimization_ and a fake vtable.
+The `any` API is very similar to that of its most famous counterpart, mainly
+because this class serves the same purpose of being an opaque container for any
+type of value.<br/>
+Instances also minimize the number of allocations by relying on a well known
+technique called _small buffer optimization_ and a fake vtable.
 
 Creating an object of the `any` type, whether empty or not, is trivial:
 
@@ -93,8 +92,8 @@ Furthermore, an instance of `any` isn't tied to an actual type. Therefore, the
 wrapper is reconfigured when it's assigned a new object of a type other than
 the one it contains.
 
-There exists also a way to directly assign a value to the variable contained by
-an `entt::any`, without necessarily replacing it. This is especially useful when
+There is also a way to directly assign a value to the variable contained by an
+`entt::any`, without necessarily replacing it. This is especially useful when
 the object is used in _aliasing mode_, as described below:
 
 ```cpp
@@ -108,15 +107,15 @@ any.assign(value);
 any.assign(std::move(value));
 ```
 
-The `any` class will also perform a check on the type information and whether or
-not the original type was copy or move assignable, as appropriate.<br/>
-In all cases, the `assign` function returns a boolean value to indicate the
-success or failure of the operation.
+The `any` class performs a check on the type information and whether or not the
+original type was copy or move assignable, as appropriate.<br/>
+In all cases, the `assign` function returns a boolean value that is true in case
+of success and false otherwise.
 
-When in doubt about the type of object contained, the `type` member function of
-`any` returns a const reference to the `type_info` associated with its element,
-or `type_id<void>()` if the container is empty. The type is also used internally
-when comparing two `any` objects:
+When in doubt about the type of object contained, the `type` member function
+returns a const reference to the `type_info` associated with its element, or
+`type_id<void>()` if the container is empty.<br/>
+The type is also used internally when comparing two `any` objects:
 
 ```cpp
 if(any == empty) { /* ... */ }
@@ -125,7 +124,7 @@ if(any == empty) { /* ... */ }
 In this case, before proceeding with a comparison, it's 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 on possible risks of a comparison.
+`type_info` works and the possible risks of a comparison.
 
 A particularly interesting feature of this class is that it can also be used as
 an opaque container for const and non-const references:
@@ -153,22 +152,19 @@ entt::any ref = other.as_ref();
 ```
 
 In this case, it doesn't matter if the original container actually holds an
-object or acts already as a reference for unmanaged elements, the new instance
-thus created won't create copies and will only serve as a reference for the
-original item.<br/>
-This means that, starting from the example above, both `ref` and `other` will
-point to the same object, whether it's initially contained in `other` or already
-an unmanaged element.
-
-As a side note, it's worth mentioning that, while everything works transparently
-when it comes to non-const references, there are some exceptions when it comes
-to const references.<br/>
+object or is as a reference for unmanaged elements already. The new instance
+thus created doesn't create copies and only serves as a reference for the
+original item.
+
+It's worth mentioning that, while everything works transparently when it comes
+to non-const references, there are some exceptions when it comes to const
+references.<br/>
 In particular, the `data` member function invoked on a non-const instance of
-`any` that wraps a const reference will return a null pointer in all cases.
+`any` that wraps a const reference returns a null pointer in all cases.
 
 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`, these won't raise exceptions
+The only difference is that, in the case of `EnTT`, they won't raise exceptions
 but will only trigger an assert in debug mode, otherwise resulting in undefined
 behavior in case of misuse in release mode.
 
@@ -188,31 +184,23 @@ using my_any = entt::basic_any<sizeof(double[4])>;
 This feature, in addition to allowing the choice of a size that best suits the
 needs of an application, also offers the possibility of forcing dynamic creation
 of objects during construction.<br/>
-In other terms, if the size is 0, `any` avoids the use of any optimization and
-always dynamically allocates objects (except for aliasing cases).
-
-Note that the size of the internal storage as well as the alignment requirements
-are directly part of the type and therefore contribute to define different types
-that won't be able to interoperate with each other.
+In other terms, if the size is 0, `any` suppresses the small buffer optimization
+and always dynamically allocates objects (except for aliasing cases).
 
 ## Alignment requirement
 
 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/>
-The `basic_any` class template inspects the alignment requirements in each case,
-even when not provided and may decide not to use the small buffer optimization
-in order to meet them.
-
-The alignment requirement is provided as an optional second parameter following
-the desired size for the internal storage:
+It's 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])>;
 ```
 
-Note that the alignment requirements as well as the size of the internal storage
-are directly part of the type and therefore contribute to define different types
-that won't be able to interoperate with each other.
+The `basic_any` class template inspects the alignment requirements in each case,
+even when not provided and may decide not to use the small buffer optimization
+in order to meet them.
 
 # Compressed pair
 
@@ -225,8 +213,8 @@ is more important than having some cool and probably useless feature.
 
 Although the API is very close to that of `std::pair` (apart from the fact that
 the template parameters are inferred from the constructor and therefore there is
-no` entt::make_compressed_pair`), the major difference is that `first` and
-`second` are functions for implementation needs:
+no `entt::make_compressed_pair`), the major difference is that `first` and
+`second` are functions for implementation requirements:
 
 ```cpp
 entt::compressed_pair pair{0, 3.};
@@ -239,16 +227,15 @@ intuition. At the end of the day, it's just a pair and nothing more.
 # Enum as bitmask
 
 Sometimes it's useful to be able to use enums as bitmasks. However, enum classes
-aren't really suitable for the purpose out of the box. Main problem is that they
-don't convert implicitly to their underlying type.<br/>
-All that remains is to make a choice between using old-fashioned enums (with all
-their problems that I don't want to discuss here) or writing _ugly_ code.
+aren't really suitable for the purpose. Main problem is that they don't convert
+implicitly to their underlying type.<br/>
+The choice is then between using old-fashioned enums (with all their problems
+that I don't want to discuss here) or writing _ugly_ code.
 
 Fortunately, there is also a third way: adding enough operators in the global
-scope to treat enum classes as bitmask transparently.<br/>
-The ultimate goal is to be able to write code like the following (or maybe
-something more meaningful, but this should give a grasp and remain simple at the
-same time):
+scope to treat enum classes as bitmasks transparently.<br/>
+The ultimate goal is to write code like the following (or maybe something more
+meaningful, but this should give a grasp and remain simple at the same time):
 
 ```cpp
 enum class my_flag {
@@ -261,11 +248,11 @@ const my_flag flags = my_flag::enabled;
 const bool is_enabled = !!(flags & my_flag::enabled);
 ```
 
-The problem with adding all operators to the global scope is that these will
-come into play even when not required, with the risk of introducing errors that
-are difficult to deal with.<br/>
+The problem with adding all operators to the global scope is that these come
+into play even when not required, with the risk of introducing errors that are
+difficult to deal with.<br/>
 However, C++ offers enough tools to get around this problem. In particular, the
-library requires users to register all enum classes for which bitmask support
+library requires users to register the enum classes for which bitmask support
 should be enabled:
 
 ```cpp
@@ -276,7 +263,7 @@ struct entt::enum_as_bitmask<my_flag>
 ```
 
 This is handy when dealing with enum classes defined by third party libraries
-and over which the users have no control. However, it's also verbose and can be
+and over which the user has no control. However, it's also verbose and can be
 avoided by adding a specific value to the enum class itself:
 
 ```cpp
@@ -289,23 +276,21 @@ enum class my_flag {
 ```
 
 In this case, there is no need to specialize the `enum_as_bitmask` traits, since
-`EnTT` will automatically detect the flag and enable the bitmask support.<br/>
-Once the enum class has been registered (in one way or the other) all the most
-common operators will be available, such as `&`, `|` but also `&=` and `|=`.
+`EnTT` automatically detects the flag and enables the bitmask support.<br/>
+Once the enum class is registered (in one way or the other), the most common
+operators such as `&`, `|` but also `&=` and `|=` are available for use.
+
 Refer to the official documentation for the full list of operators.
 
 # Hashed strings
 
-A hashed string is a zero overhead unique identifier. Users can use
-human-readable identifiers in the codebase while using their numeric
-counterparts at runtime, thus without affecting performance.<br/>
+Hashed strings are human-readable identifiers in the codebase that turn into
+numeric values at runtime, thus without affecting performance.<br/>
 The class has an implicit `constexpr` constructor that chews a bunch of
-characters. Once created, all what one can do with it is getting back the
-original string through the `data` member function or converting the instance
-into a number.<br/>
-The good part is that a hashed string can be used wherever a constant expression
-is required and no _string-to-number_ conversion will take place at runtime if
-used carefully.
+characters. Once created, one can get the original string by means of the `data`
+member function or convert the instance into a number.<br/>
+A hashed string is well suited wherever a constant expression is required. No
+_string-to-number_ conversion will take place at runtime if used carefully.
 
 Example of use:
 
@@ -318,19 +303,18 @@ auto resource = load(entt::hashed_string{"gui/background"});
 ```
 
 There is also a _user defined literal_ dedicated to hashed strings to make them
-more user-friendly:
+more _user-friendly_:
 
 ```cpp
 using namespace entt::literals;
 constexpr auto str = "text"_hs;
 ```
 
-To use it, remember that all user defined literals in `EnTT` are enclosed in the
-`entt::literals` namespace. Therefore, the entire namespace or selectively the
-literal of interest must be explicitly included before each use, a bit like
-`std::literals`.<br/>
-Finally, in case users need to create hashed strings at runtime, this class also
-offers the necessary functionalities:
+User defined literals in `EnTT` are enclosed in the `entt::literals` namespace.
+Therefore, the entire namespace or selectively the literal of interest must be
+explicitly included before each use, a bit like `std::literals`.<br/>
+The class also offers the necessary functionalities to create hashed strings at
+runtime:
 
 ```cpp
 std::string orig{"text"};
@@ -343,16 +327,14 @@ const auto hash = entt::hashed_string::value(orig.c_str());
 ```
 
 This possibility shouldn't be exploited in tight loops, since the computation
-takes place at runtime and no longer at compile-time and could therefore impact
+takes place at runtime and no longer at compile-time. It could therefore affect
 performance to some degrees.
 
 ## Wide characters
 
-The hashed string has a design that is close to that of an `std::basic_string`.
-It means that `hashed_string` is nothing more than an alias for
-`basic_hashed_string<char>`. For those who want to use the C++ type for wide
-character representation, there exists also the alias `hashed_wstring` for
-`basic_hashed_string<wchar_t>`.<br/>
+The `hashed_string` class is an alias  for `basic_hashed_string<char>`. To use
+the C++ type for wide character representations, there exists also the alias
+`hashed_wstring` for `basic_hashed_string<wchar_t>`.<br/>
 In this case, the user defined literal to use to create hashed strings on the
 fly is `_hws`:
 
@@ -360,16 +342,15 @@ fly is `_hws`:
 constexpr auto str = L"text"_hws;
 ```
 
-Note that the hash type of the `hashed_wstring` is the same of its counterpart.
+The hash type of `hashed_wstring` is the same as its counterpart.
 
 ## Conflicts
 
-The hashed string class uses internally FNV-1a to compute the numeric
-counterpart of a string. Because of the _pigeonhole principle_, conflicts are
-possible. This is a fact.<br/>
+The hashed string class uses FNV-1a internally to hash strings. Because of the
+_pigeonhole principle_, conflicts are possible. This is a fact.<br/>
 There is no silver bullet to solve the problem of conflicts when dealing with
-hashing functions. In this case, the best solution seemed to be to give up.
-That's all.<br/>
+hashing functions. In this case, the best solution is likely to give up. That's
+all.<br/>
 After all, human-readable unique identifiers aren't something strictly defined
 and over which users have not the control. Choosing a slightly different
 identifier is probably the best solution to make the conflict disappear in this
@@ -377,8 +358,8 @@ case.
 
 # Iterators
 
-Writing and working with iterators isn't always easy and more often than not
-leads to duplicated code.<br/>
+Writing and working with iterators isn't always easy. More often than not it
+also leads to duplicated code.<br/>
 `EnTT` tries to overcome this problem by offering some utilities designed to
 make this hard work easier.
 
@@ -431,7 +412,7 @@ user.
 ## Iterable adaptor
 
 Typically, a container class provides `begin` and `end` member functions (with
-their const counterparts) to be iterated by the user.<br/>
+their const counterparts) for iteration.<br/>
 However, it can happen that a class offers multiple iteration methods or allows
 users to iterate different sets of _elements_.
 
@@ -452,8 +433,8 @@ by returning an iterable object for the purpose.
 There are a handful of tools within `EnTT` to interact with memory in one way or
 another.<br/>
 Some are geared towards simplifying the implementation of (internal or external)
-allocator aware containers. Others, on the other hand, are designed to help the
-developer with everyday problems.
+allocator aware containers. Others are designed to help the developer with
+everyday problems.
 
 The former are very specific and for niche problems. These are tools designed to
 unwrap fancy or plain pointers (`to_address`) or to help forget the meaning of
@@ -481,7 +462,7 @@ modulus and for this reason preferred in many areas.
 
 A nasty thing in C++ (at least up to C++20) is the fact that shared pointers
 support allocators while unique pointers don't.<br/>
-There is a proposal at the moment that also shows among the other things how
+There is a proposal at the moment that also shows (among the other things) how
 this can be implemented without any compiler support.
 
 The `allocate_unique` function follows this proposal, making a virtue out of
@@ -498,13 +479,16 @@ the same feature.
 # Monostate
 
 The monostate pattern is often presented as an alternative to a singleton based
-configuration system. This is exactly its purpose in `EnTT`. Moreover, this
-implementation is thread safe by design (hopefully).<br/>
-Keys are represented by hashed strings, values are basic types like `int`s or
-`bool`s. Values of different types can be associated to each key, even more than
-one at a time. Because of this, users must pay attention to use the same type
-both during an assignment and when they try to read back their data. Otherwise,
-they will probably incur in unexpected results.
+configuration system.<br/>
+This is exactly its purpose in `EnTT`. Moreover, this implementation is thread
+safe by design (hopefully).
+
+Keys are integral values (easily obtained by hashed strings), values are basic
+types like `int`s or `bool`s. Values of different types can be associated with
+each key, even more than one at a time.<br/>
+Because of this, one should pay attention to use the same type both during an
+assignment and when trying to read back the data. Otherwise, there is the risk
+to incur in unexpected results.
 
 Example of use:
 
@@ -542,17 +526,10 @@ Basically, the whole system relies on a handful of classes. In particular:
   auto index = entt::type_index<a_type>::value();
   ```
 
-  The returned value isn't guaranteed to be stable across different runs.
+  The returned value isn't guaranteed to be stable across different runs.<br/>
   However, it can be very useful as index in associative and unordered
   associative containers or for positional accesses in a vector or an array.
   
-  So as not to conflict with the other tools available, the `family` class isn't
-  used to generate these indexes. Therefore, the numeric identifiers returned by
-  the two tools may differ.<br/>
-  On the other hand, this leaves users with full powers over the `family` class
-  and therefore the generation of custom runtime sequences of indices for their
-  own purposes, if necessary.
-  
   An external generator can also be used if needed. In fact, `type_index` can be
   specialized by type and is also _sfinae-friendly_ in order to allow more
   refined specializations such as:
@@ -566,7 +543,7 @@ Basically, the whole system relies on a handful of classes. In particular:
   };
   ```
   
-  Note that indexes **must** still be generated sequentially in this case.<br/>
+  Indexes **must** be sequentially generated in this case.<br/>
   The tool is widely used within `EnTT`. Generating indices not sequentially
   would break an assumption and would likely lead to undesired behaviors.
 
@@ -583,14 +560,14 @@ Basically, the whole system relies on a handful of classes. In particular:
   This function **can** use non-standard features of the language for its own
   purposes. This makes it possible to provide compile-time identifiers that
   remain stable across different runs.<br/>
-  In all cases, users can prevent the library from using these features by means
-  of the `ENTT_STANDARD_CPP` definition. In this case, there is no guarantee
-  that identifiers remain stable across executions. Moreover, they are generated
+  Users can prevent the library from using these features by means of the
+  `ENTT_STANDARD_CPP` definition. In this case, there is no guarantee that
+  identifiers remain stable across executions. Moreover, they are generated
   at runtime and are no longer a compile-time thing.
 
-  As for `type_index`, also `type_hash` is a _sfinae-friendly_ class that can be
-  specialized in order to customize its behavior globally or on a per-type or
-  per-traits basis.
+  As it happens with `type_index`, also `type_hash` is a _sfinae-friendly_ class
+  that can be specialized in order to customize its behavior globally or on a
+  per-type or per-traits basis.
 
 * The name associated with a given type:
 
@@ -598,10 +575,9 @@ Basically, the whole system relies on a handful of classes. In particular:
   auto name = entt::type_name<a_type>::value();
   ```
 
-  The name associated with a type is extracted from some information generally
-  made available by the compiler in use. Therefore, it may differ depending on
-  the compiler and may be empty in the event that this information isn't
-  available.<br/>
+  This value is extracted from some information generally made available by the
+  compiler in use. Therefore, it may differ depending on the compiler and may be
+  empty in the event that this information isn't available.<br/>
   For example, given the following class:
 
   ```cpp
@@ -612,21 +588,20 @@ Basically, the whole system relies on a handful of classes. In particular:
   when MSVC is in use.<br/>
   Most of the time the name is also retrieved at compile-time and is therefore
   always returned through an `std::string_view`. Users can easily access it and
-  modify it as needed, for example by removing the word `struct` to standardize
-  the result. `EnTT` won't do this for obvious reasons, since it requires
-  copying and creating a new string potentially at runtime.
+  modify it as needed, for example by removing the word `struct` to normalize
+  the result. `EnTT` doesn't do this for obvious reasons, since it would be
+  creating a new string at runtime otherwise.
 
   This function **can** use non-standard features of the language for its own
-  purposes. Users can prevent the library from using non-standard features by
-  means of the `ENTT_STANDARD_CPP` definition. In this case, the name will be
-  empty by default.
+  purposes. Users can prevent the library from using these features by means of
+  the `ENTT_STANDARD_CPP` definition. In this case, the name is just empty.
 
-  As for `type_index`, also `type_name` is a _sfinae-friendly_ class that can be
-  specialized in order to customize its behavior globally or on a per-type or
-  per-traits basis.
+  As it happens with `type_index`, also `type_name` is a _sfinae-friendly_ class
+  that can be specialized in order to customize its behavior globally or on a
+  per-type or per-traits basis.
 
 These are then combined into utilities that aim to offer an API that is somewhat
-similar to that offered by the language.
+similar to that made available by the standard library.
 
 ### Type info
 
@@ -708,8 +683,8 @@ In fact, although this is quite rare, it's not entirely excluded.
 
 Another case where two types are assigned the same identifier is when classes
 from different contexts (for example two or more libraries loaded at runtime)
-have the same fully qualified name. In this case, also `type_name` will return
-the same value for the two types.<br/>
+have the same fully qualified name. In this case, `type_name` returns the same
+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
@@ -739,9 +714,9 @@ offered by this module.
 
 ### Size of
 
-The standard operator `sizeof` complains when users provide it for example with
-function or incomplete types. On the other hand, it's guaranteed that its result
-is always nonzero, even if applied to an empty class type.<br/>
+The standard operator `sizeof` complains if users provide it with functions or
+incomplete types. On the other hand, it's guaranteed that its result is always
+non-zero, even if applied to an empty class type.<br/>
 This small class combines the two and offers an alternative to `sizeof` that
 works under all circumstances, returning zero if the type isn't supported:
 
@@ -777,8 +752,8 @@ A utility to easily transfer the constness of a type to another type:
 using type = entt::constness_as_t<dst_type, const src_type>;
 ```
 
-The trait is subject to the rules of the language. Therefore, for example,
-transferring constness between references won't give the desired effect.
+The trait is subject to the rules of the language. For example, _transferring_
+constness between references won't give the desired effect.
 
 ### Member class type
 
@@ -798,7 +773,7 @@ A utility to quickly find the n-th argument of a function, member function or
 data member (for blind operations on opaque types):
 
 ```cpp
-using type = entt::nt_argument_t<1u, &clazz::member>;
+using type = entt::nth_argument_t<1u, &clazz::member>;
 ```
 
 Disambiguation of overloaded functions is the responsibility of the user, should
@@ -825,8 +800,8 @@ registry.emplace<enemy_tag>(entity);
 
 ### Tag
 
-Since `id_type` is very important and widely used in `EnTT`, there is a more
-user-friendly shortcut for the creation of integral constants based on it.<br/>
+Type `id_type` is very important and widely used in `EnTT`. Therefore, there is
+a more user-friendly shortcut for the creation of constants based on it.<br/>
 This shortcut is the alias template `entt::tag`.
 
 If used in combination with hashed strings, it helps to use human-readable names
@@ -918,8 +893,8 @@ Perhaps a bit ugly to see in a codebase but it gets the job done at least.
 
 ## Runtime generator
 
-To generate sequential numeric identifiers at runtime, `EnTT` offers the
-`family` class template:
+The `family` class template helps to generate sequential numeric identifiers for
+types at runtime:
 
 ```cpp
 // defines a custom generator
@@ -936,8 +911,8 @@ numeric identifier for the given type.<br/>
 The generator is customizable, so as to get different _sequences_ for different
 purposes if needed.
 
-Please, note that identifiers aren't guaranteed to be stable across different
-runs. Indeed it mostly depends on the flow of execution.
+Identifiers aren't guaranteed to be stable across different runs. Indeed it
+mostly depends on the flow of execution.
 
 # Utilities