Browse Source

EnTT v3 (draft)

Michele Caini 7 years ago
parent
commit
d81cb7f866
63 changed files with 2583 additions and 4039 deletions
  1. 4 22
      .travis.yml
  2. 2 2
      CMakeLists.txt
  3. 19 16
      README.md
  4. 1 6
      TODO
  5. 22 22
      docs/core.md
  6. 143 261
      docs/entity.md
  7. 11 11
      docs/locator.md
  8. 7 7
      docs/process.md
  9. 19 19
      docs/resource.md
  10. 8 10
      docs/shared.md
  11. 52 42
      docs/signal.md
  12. 3 3
      src/entt/core/algorithm.hpp
  13. 6 17
      src/entt/core/family.hpp
  14. 26 10
      src/entt/core/hashed_string.hpp
  15. 9 48
      src/entt/core/ident.hpp
  16. 5 11
      src/entt/core/monostate.hpp
  17. 14 82
      src/entt/entity/actor.hpp
  18. 0 230
      src/entt/entity/attachee.hpp
  19. 10 10
      src/entt/entity/entity.hpp
  20. 15 18
      src/entt/entity/helper.hpp
  21. 61 94
      src/entt/entity/prototype.hpp
  22. 123 501
      src/entt/entity/registry.hpp
  23. 108 238
      src/entt/entity/snapshot.hpp
  24. 87 111
      src/entt/entity/sparse_set.hpp
  25. 0 23
      src/entt/entity/utility.hpp
  26. 209 245
      src/entt/entity/view.hpp
  27. 0 2
      src/entt/entt.hpp
  28. 4 8
      src/entt/locator/locator.hpp
  29. 47 45
      src/entt/process/process.hpp
  30. 37 38
      src/entt/process/scheduler.hpp
  31. 12 12
      src/entt/resource/cache.hpp
  32. 8 8
      src/entt/resource/handle.hpp
  33. 7 7
      src/entt/resource/loader.hpp
  34. 67 33
      src/entt/signal/delegate.hpp
  35. 17 20
      src/entt/signal/dispatcher.hpp
  36. 51 51
      src/entt/signal/emitter.hpp
  37. 69 110
      src/entt/signal/sigh.hpp
  38. 0 1
      test/CMakeLists.txt
  39. 342 370
      test/benchmark/benchmark.cpp
  40. 3 3
      test/entt/core/algorithm.cpp
  41. 12 12
      test/entt/core/family.cpp
  42. 16 13
      test/entt/core/hashed_string.cpp
  43. 15 15
      test/entt/core/ident.cpp
  44. 10 10
      test/entt/core/monostate.cpp
  45. 20 46
      test/entt/entity/actor.cpp
  46. 0 69
      test/entt/entity/attachee.cpp
  47. 2 5
      test/entt/entity/entity.cpp
  48. 2 2
      test/entt/entity/helper.cpp
  49. 11 11
      test/entt/entity/prototype.cpp
  50. 122 258
      test/entt/entity/registry.cpp
  51. 119 198
      test/entt/entity/snapshot.cpp
  52. 66 66
      test/entt/entity/sparse_set.cpp
  53. 68 68
      test/entt/entity/view.cpp
  54. 23 25
      test/entt/locator/locator.cpp
  55. 46 46
      test/entt/process/process.cpp
  56. 33 33
      test/entt/process/scheduler.cpp
  57. 25 25
      test/entt/resource/resource.cpp
  58. 35 21
      test/entt/signal/delegate.cpp
  59. 17 17
      test/entt/signal/dispatcher.cpp
  60. 40 40
      test/entt/signal/emitter.cpp
  61. 72 72
      test/entt/signal/sigh.cpp
  62. 139 158
      test/mod/mod.cpp
  63. 62 62
      test/snapshot/snapshot.cpp

+ 4 - 22
.travis.yml

@@ -4,13 +4,6 @@ sudo: false
 
 matrix:
   include:
-  - os: linux
-    compiler: gcc
-    addons:
-      apt:
-        sources: ['ubuntu-toolchain-r-test']
-        packages: ['g++-6']
-    env: COMPILER=g++-6
   - os: linux
     compiler: gcc
     addons:
@@ -22,22 +15,11 @@ matrix:
     compiler: clang
     addons:
       apt:
-        sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-trusty-4.0']
-        packages: ['clang-4.0', 'libstdc++-4.9-dev']
-    env: COMPILER=clang++-4.0
-  - os: linux
-    compiler: clang
-    addons:
-      apt:
-        sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-trusty-5.0']
-        packages: ['clang-5.0', 'libstdc++-4.9-dev']
-    env: COMPILER=clang++-5.0
-  - os: osx
-    osx_image: xcode8.3
-    compiler: clang
-    env: COMPILER=clang++
+        sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-trusty-6.0']
+        packages: ['clang-6.0', 'g++-7']
+    env: COMPILER=clang++-6.0
   - os: osx
-    osx_image: xcode9.4
+    osx_image: xcode10
     compiler: clang
     env: COMPILER=clang++
   - os: linux

+ 2 - 2
CMakeLists.txt

@@ -16,7 +16,7 @@ endif()
 # Project configuration
 #
 
-project(EnTT VERSION 2.7.3)
+project(EnTT VERSION 3.0.0)
 
 include(GNUInstallDirs)
 
@@ -100,7 +100,7 @@ if(HAS_LIBCPP)
     target_compile_options(EnTT BEFORE INTERFACE -stdlib=libc++)
 endif()
 
-target_compile_features(EnTT INTERFACE cxx_std_14)
+target_compile_features(EnTT INTERFACE cxx_std_17)
 
 #
 # Install EnTT

+ 19 - 16
README.md

@@ -86,50 +86,50 @@ been sufficiently tested so far.
 #include <entt/entt.hpp>
 #include <cstdint>
 
-struct Position {
+struct position {
     float x;
     float y;
 };
 
-struct Velocity {
+struct velocity {
     float dx;
     float dy;
 };
 
-void update(entt::DefaultRegistry &registry) {
-    auto view = registry.view<Position, Velocity>();
+void update(entt::registry &registry) {
+    auto view = registry.view<position, velocity>();
 
     for(auto entity: view) {
         // gets only the components that are going to be used ...
 
-        auto &velocity = view.get<Velocity>(entity);
+        auto &vel = view.get<velocity>(entity);
 
-        velocity.dx = 0.;
-        velocity.dy = 0.;
+        vel.dx = 0.;
+        vel.dy = 0.;
 
         // ...
     }
 }
 
-void update(std::uint64_t dt, entt::DefaultRegistry &registry) {
-    registry.view<Position, Velocity>().each([dt](auto entity, auto &position, auto &velocity) {
+void update(std::uint64_t dt, entt::registry &registry) {
+    registry.view<position, velocity>().each([dt](const auto, auto &pos, auto &vel) {
         // gets all the components of the view at once ...
 
-        position.x += velocity.dx * dt;
-        position.y += velocity.dy * dt;
+        pos.x += vel.dx * dt;
+        pos.y += vel.dy * dt;
 
         // ...
     });
 }
 
 int main() {
-    entt::DefaultRegistry registry;
+    entt::registry registry;
     std::uint64_t dt = 16;
 
     for(auto i = 0; i < 10; ++i) {
         auto entity = registry.create();
-        registry.assign<Position>(entity, i * 1.f, i * 1.f);
-        if(i % 2 == 0) { registry.assign<Velocity>(entity, i * .1f, i * .1f); }
+        registry.assign<position>(entity, i * 1.f, i * 1.f);
+        if(i % 2 == 0) { registry.assign<velocity>(entity, i * .1f, i * .1f); }
     }
 
     update(dt, registry);
@@ -209,13 +209,15 @@ open an issue to discuss your idea.
 ## Requirements
 
 To be able to use `EnTT`, users must provide a full-featured compiler that
-supports at least C++14.<br/>
+supports at least C++17.<br/>
 The requirements below are mandatory to compile the tests and to extract the
 documentation:
 
 * CMake version 3.2 or later.
 * Doxygen version 1.8 or later.
 
+If you are looking for a C++14 version of `EnTT`, check out the git tag `cpp14`.
+
 ## Library
 
 `EnTT` is a header-only library. This means that including the `entt.hpp` header
@@ -351,7 +353,8 @@ I can't promise that each and every contribution will be accepted, but I can
 assure that I'll do my best to take them all seriously.
 
 If you decide to participate, please see the guidelines for
-[contributing](docs/CONTRIBUTING.md) before to create issues or pull requests.<br/>
+[contributing](docs/CONTRIBUTING.md) before to create issues or pull
+requests.<br/>
 Take also a look at the
 [contributors list](https://github.com/skypjack/entt/blob/master/AUTHORS) to
 know who has participated so far.

+ 1 - 6
TODO

@@ -9,10 +9,5 @@
 * optimize for empty components, it would be a mid improvement in terms of memory usage
 * can we do more for shared libraries? who knows... see #144
 * work stealing job system (see #100)
-* make view copyable/moveable
 * reflection system (maybe)
-* C++17. That's all.
-* AOB
-* lower case names (?)
-* tag_t and the others, create constexpr var
-* use delegate within sink, it reduces the boilerplate in C++14, it shrinks the API of sink in C++17
+* composable looper so as to pack erased systems, compose runners at different rates and run them at once in the loop

+ 22 - 22
docs/core.md

@@ -30,21 +30,21 @@ There are plenty of different solutions out there and I could have used one of
 them. However, I decided to spend my time to define a compact and versatile tool
 that fully embraces what the modern C++ has to offer.
 
-The _result of my efforts_ is the `Identifier` class template:
+The _result of my efforts_ is the `identifier` class template:
 
 ```cpp
 #include <ident.hpp>
 
 // defines the identifiers for the given types
-using ID = entt::Identifier<AType, AnotherType>;
+using id = entt::identifier<a_type, another_type>;
 
 // ...
 
-switch(aTypeIdentifier) {
-case ID::get<AType>():
+switch(a_type_identifier) {
+case id::type<a_type>:
     // ...
     break;
-case ID::get<AnotherType>():
+case id::type<another_type>:
     // ...
     break;
 default:
@@ -52,8 +52,8 @@ default:
 }
 ```
 
-This is all what the class template has to offer: a static `get` member function
-that returns a numerical identifier for the given type. It can be used in any
+This is all what the class template has to offer: a `type` inline variable that
+contains a numerical 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 the
@@ -62,12 +62,12 @@ a type has to be removed, one can just use a placeholder to left the other
 identifiers unchanged:
 
 ```cpp
-template<typename> struct IgnoreType {};
+template<typename> struct ignore_type {};
 
-using ID = entt::Identifier<
-    ATypeStillValid,
-    IgnoreType<ATypeNoLongerValid>,
-    AnotherTypeStillValid
+using id = entt::identifier<
+    a_type_still_valid,
+    ignore_type<a_type_no_longer_valid>,
+    another_type_still_valid
 >;
 ```
 
@@ -81,21 +81,21 @@ There are plenty of different solutions out there and I could have used one of
 them. In fact, I adapted the most common one to my requirements and used it
 extensively within the entire library.
 
-It's the `Family` class. Here is an example of use directly from the
+It's the `family` class. Here is an example of use directly from the
 entity-component system:
 
 ```cpp
-using component_family = entt::Family<struct InternalRegistryComponentFamily>;
+using component_family = entt::family<struct internal_registry_component_family>;
 
 // ...
 
 template<typename Component>
 component_type component() const noexcept {
-    return component_family::type<Component>();
+    return component_family::type<Component>;
 }
 ```
 
-This is all what a _family_ has to offer: a `type` member function that returns
+This is all what a _family_ has to offer: a `type` inline variable that contains
 a numerical identifier for the given type.
 
 Please, note that identifiers aren't guaranteed to be the same for every run.
@@ -116,11 +116,11 @@ used carefully.
 Example of use:
 
 ```cpp
-auto load(entt::HashedString::hash_type resource) {
+auto load(entt::hashed_string::hash_type resource) {
     // uses the numeric representation of the resource to load and return it
 }
 
-auto resource = load(entt::HashedString{"gui/background"});
+auto resource = load(entt::hashed_string{"gui/background"});
 ```
 
 There is also a _user defined literal_ dedicated to hashed strings to make them
@@ -157,11 +157,11 @@ they will probably incur in unexpected results.
 Example of use:
 
 ```cpp
-entt::Monostate<entt::HashedString{"mykey"}>{} = true;
-entt::Monostate<"mykey"_hs>{} = 42;
+entt::monostate<entt::hashed_string{"mykey"}>{} = true;
+entt::monostate<"mykey"_hs>{} = 42;
 
 // ...
 
-const bool b = entt::Monostate<"mykey"_hs>{};
-const int i = entt::Monostate<entt::HashedString{"mykey"}>{};
+const bool b = entt::monostate<"mykey"_hs>{};
+const int i = entt::monostate<entt::hashed_string{"mykey"}>{};
 ```

+ 143 - 261
docs/entity.md

@@ -11,9 +11,7 @@
   * [Pay per use](#pay-per-use)
 * [Vademecum](#vademecum)
 * [The Registry, the Entity and the Component](#the-registry-the-entity-and-the-component)
-  * [Single instance components](#single-instance-components)
   * [Observe changes](#observe-changes)
-    * [Who let the tags out?](#who-let-the-tags-out)
   * [Runtime components](#runtime-components)
     * [A journey through a plugin](#a-journey-through-a-plugin)
   * [Sorting: is it possible?](#sorting-is-it-possible)
@@ -57,13 +55,13 @@ specify the component set at compile-time.<br/>
 This is why users can instantiate the core class simply like:
 
 ```cpp
-entt::DefaultRegistry registry;
+entt::registry registry;
 ```
 
 In place of its more annoying and error-prone counterpart:
 
 ```cpp
-entt::DefaultRegistry<Comp0, Comp1, ..., CompN> registry;
+entt::registry<comp_0, comp_1, ..., comp_n> registry;
 ```
 
 ## Pay per use
@@ -88,15 +86,15 @@ many others besides me.
 
 # Vademecum
 
-The `Registry` to store, the views to iterate. That's all.
+The registry to store, the views to iterate. That's all.
 
 An entity (the _E_ of an _ECS_) is an opaque identifier that users should just
 use as-is and store around if needed. Do not try to inspect an entity
 identifier, its format can change in future and a registry offers all the
 functionalities to query them out-of-the-box. The underlying type of an entity
 (either `std::uint16_t`, `std::uint32_t` or `std::uint64_t`) can be specified
-when defining a registry (actually the `DefaultRegistry` is nothing more than a
-`Registry` where the type of the entities is `std::uint32_t`).<br/>
+when defining a registry (actually `registry` is nothing more than an _alias_
+for `registry<std::uint32_t>`).<br/>
 Components (the _C_ of an _ECS_) should be plain old data structures or more
 complex and movable data structures with a proper constructor. Actually, the
 sole requirement of a component type is that it must be both move constructible
@@ -104,7 +102,7 @@ and move assignable. They are list initialized by using the parameters provided
 to construct the component itself. No need to register components or their types
 neither with the registry nor with the entity-component system at all.<br/>
 Systems (the _S_ of an _ECS_) are just plain functions, functors, lambdas or
-whatever users want. They can accept a `Registry` or a view of any type and use
+whatever users want. They can accept a `registry` or a view of any type and use
 them the way they prefer. No need to register systems or their types neither
 with the registry nor with the entity-component system at all.
 
@@ -117,10 +115,9 @@ describe below. For more details, please refer to the inline documentation.
 
 A registry can store and manage entities, as well as create views to iterate the
 underlying data structures.<br/>
-`Registry` is a class template that lets users decide what's the preferred type
-to represent an entity. Because `std::uint32_t` is large enough for almost all
-the cases, there exists also an alias named `DefaultRegistry` for
-`Registry<std::uint32_t>`.
+The class template `registry` lets users decide what's the preferred type to
+represent an entity. Because `std::uint32_t` is large enough for almost all the
+cases, `registry` is also an _alias_ for `registry<std::uint32_t>`.
 
 Entities are represented by _entity identifiers_. An entity identifier is an
 opaque type that users should not inspect or modify in any way. It carries
@@ -137,14 +134,11 @@ registry.destroy(entity);
 ```
 
 Entities can also be destroyed _by type_, that is by specifying the types of the
-tags or components that identify them:
+components that identify them:
 
 ```cpp
-// destroys the entity that owns the given tag, if any
-registry.destroy<MyTag>(entt::tag_t{});
-
 // destroys the entities that own the given components, if any
-registry.destroy<AComponent, AnotherComponent>();
+registry.destroy<a_component, another_component>();
 ```
 
 When an entity is destroyed, the registry can freely reuse it internally with a
@@ -174,26 +168,26 @@ entity the given component. It accepts a variable number of arguments to
 construct the component itself if present:
 
 ```cpp
-registry.assign<Position>(entity, 0., 0.);
+registry.assign<position>(entity, 0., 0.);
 
 // ...
 
-Velocity &velocity = registry.assign<Velocity>(entity);
-velocity.dx = 0.;
-velocity.dy = 0.;
+auto &velocity = registry.assign<velocity>(entity);
+vel.dx = 0.;
+vel.dy = 0.;
 ```
 
 If an entity already has the given component, the `replace` member function
 template can be used to replace it:
 
 ```cpp
-registry.replace<Position>(entity, 0., 0.);
+registry.replace<position>(entity, 0., 0.);
 
 // ...
 
-Velocity &velocity = registry.replace<Velocity>(entity);
-velocity.dx = 0.;
-velocity.dy = 0.;
+auto &velocity = registry.replace<velocity>(entity);
+vel.dx = 0.;
+vel.dy = 0.;
 ```
 
 In case users want to assign a component to an entity, but it's unknown whether
@@ -202,23 +196,23 @@ the entity already has it or not, `accommodate` does the work in a single call
 has to check if the entity already has the given component or not):
 
 ```cpp
-registry.accommodate<Position>(entity, 0., 0.);
+registry.accommodate<position>(entity, 0., 0.);
 
 // ...
 
-Velocity &velocity = registry.accommodate<Velocity>(entity);
-velocity.dx = 0.;
-velocity.dy = 0.;
+auto &velocity = registry.accommodate<velocity>(entity);
+vel.dx = 0.;
+vel.dy = 0.;
 ```
 
 Note that `accommodate` is a slightly faster alternative for the following
 `if/else` statement and nothing more:
 
 ```cpp
-if(registry.has<Comp>(entity)) {
-    registry.replace<Comp>(entity, arg1, argN);
+if(registry.has<comp>(entity)) {
+    registry.replace<comp>(entity, arg1, argN);
 } else {
-    registry.assign<Comp>(entity, arg1, argN);
+    registry.assign<comp>(entity, arg1, argN);
 }
 ```
 
@@ -226,7 +220,7 @@ As already shown, if in doubt about whether or not an entity has one or more
 components, the `has` member function template may be useful:
 
 ```cpp
-bool b = registry.has<Position, Velocity>(entity);
+bool b = registry.has<position, velocity>(entity);
 ```
 
 On the other side, if the goal is to delete a single component, the `remove`
@@ -234,7 +228,7 @@ member function template is the way to go when it's certain that the entity owns
 a copy of the component:
 
 ```cpp
-registry.remove<Position>(entity);
+registry.remove<position>(entity);
 ```
 
 Otherwise consider to use the `reset` member function. It behaves similarly to
@@ -243,7 +237,7 @@ price to pay for this). In particular it removes the component if and only if it
 exists, otherwise it returns safely to the caller:
 
 ```cpp
-registry.reset<Position>(entity);
+registry.reset<position>(entity);
 ```
 
 There exist also two other _versions_ of the `reset` member function:
@@ -252,7 +246,7 @@ There exist also two other _versions_ of the `reset` member function:
   each entity that has it:
 
   ```cpp
-  registry.reset<Position>();
+  registry.reset<position>();
   ```
 
 * If neither the entity nor the component are specified, all the entities still
@@ -268,92 +262,17 @@ Finally, references to components can be retrieved simply by doing this:
 const auto &cregistry = registry;
 
 // const and non-const reference
-const Position &position = cregistry.get<Position>(entity);
-Position &position = registry.get<Position>(entity);
+const auto &crenderable = cregistry.get<renderable>(entity);
+auto &renderable = registry.get<renderable>(entity);
 
 // const and non-const references
-std::tuple<const Position &, const Velocity &> tup = cregistry.get<Position, Velocity>(entity);
-std::tuple<Position &, Velocity &> tup = registry.get<Position, Velocity>(entity);
+const auto &[cpos, cvel] = cregistry.get<position, velocity>(entity);
+auto &[pos, vel] = registry.get<position, velocity>(entity);
 ```
 
 The `get` member function template gives direct access to the component of an
 entity stored in the underlying data structures of the registry.
 
-## Single instance components
-
-In those cases where all what is needed is a single instance component, tags are
-the right tool to achieve the purpose.<br/>
-Tags undergo the same requirements of components. They can be either plain old
-data structures or more complex and movable data structures with a proper
-constructor.<br/>
-Actually, the same type can be used both as a tag and as a component and the
-registry will not complain about it. It is up to users to properly manage their
-own types. In some cases, the tag `tag_t` must also be used in order to
-disambiguate overloads of member functions.
-
-Attaching tags to entities and removing them is trivial:
-
-```cpp
-auto player = registry.create();
-auto camera = registry.create();
-
-// attaches a default-initialized tag to an entity
-registry.assign<PlayingCharacter>(entt::tag_t{}, player);
-
-// attaches a tag to an entity and initializes it
-registry.assign<Camera>(entt::tag_t{}, camera, player);
-
-// removes tags from their owners
-registry.remove<PlayingCharacter>();
-registry.remove<Camera>();
-```
-
-In case a tag already has an owner, its content can be updated by means of the
-`replace` member function template and the ownership of the tag can be
-transferred to another entity using the `move` member function template:
-
-```
-// replaces the content of the given tag
-Point &point = registry.replace<Point>(entt::tag_t{}, 1.f, 1.f);
-
-// transfers the ownership of the tag to another entity
-entity_type prev = registry.move<Point>(next);
-```
-
-If in doubt about whether or not a tag already has an owner, the `has` member
-function template may be useful:
-
-```cpp
-bool b = registry.has<PlayingCharacter>();
-```
-
-References to tags can be retrieved simply by doing this:
-
-```cpp
-const auto &cregistry = registry;
-
-// either a non-const reference ...
-PlayingCharacter &player = registry.get<PlayingCharacter>();
-
-// ... or a const one
-const Camera &camera = cregistry.get<Camera>();
-```
-
-The `get` member function template gives direct access to the tag as stored in
-the underlying data structures of the registry.
-
-As shown above, in almost all the cases the entity identifier isn't required.
-Since a single instance component can have only one associated entity, it
-doesn't make much sense to mention it explicitly.<br/>
-To find out who the owner is, just do the following:
-
-```cpp
-auto player = registry.attachee<PlayingCharacter>();
-```
-
-Note that iterating tags isn't possible for obvious reasons. Tags give direct
-access to single entities and nothing more.
-
 ## Observe changes
 
 Because of how the registry works internally, it stores a couple of signal
@@ -367,25 +286,26 @@ notified on the creation of a component, use the `construction` member function:
 
 ```cpp
 // connects a free function
-registry.construction<Position>().connect<&MyFreeFunction>();
+registry.construction<position>().connect<&my_free_function>();
 
 // connects a member function
-registry.construction<Position>().connect<MyClass, &MyClass::member>(&instance);
+registry.construction<position>().connect<&my_class::member>(&instance);
 
 // disconnects a free function
-registry.construction<Position>().disconnect<&MyFreeFunction>();
+registry.construction<position>().disconnect<&my_free_function>();
 
 // disconnects a member function
-registry.construction<Position>().disconnect<MyClass, &MyClass::member>(&instance);
+registry.construction<position>().disconnect<&my_class::member>(&instance);
 ```
 
 To be notified when components are destroyed, use the `destruction` member
 function instead.
 
-The function type of a listener is the same in both cases:
+The function type of a listener is the same in both cases and should be
+equivalent to:
 
 ```cpp
-void(Registry<Entity> &, Entity);
+void(registry<Entity> &, Entity);
 ```
 
 In other terms, a listener is provided with the registry that triggered the
@@ -400,9 +320,9 @@ particular:
 
 * Connecting and disconnecting other functions from within the body of a
   listener should be avoided. It can lead to undefined behavior in some cases.
-* Assigning and removing components and tags from within the body of a listener
-  that observes the destruction of instances of a given type should be avoided.
-  It can lead to undefined behavior in some cases. This type of listeners is
+* Assigning and removing components from within the body of a listener that
+  observes the destruction of instances of a given type should be avoided. It
+  can lead to undefined behavior in some cases. This type of listeners is
   intended to provide users with an easy way to perform cleanup and nothing
   more.
 
@@ -417,28 +337,6 @@ should be kept to a minimum, if possible. Note also that the greater the number
 of listeners, the greater the performance hit when components are created or
 destroyed.
 
-### Who let the tags out?
-
-As an extension, signals are also provided with tags. Although they are not
-strictly required internally, it makes sense that a user expects signal support
-even when it comes to tags actually.<br/>
-Signals for tags undergo exactly the same requirements of those introduced for
-components. Also the function type for a listener is the same and it's invoked
-with the same guarantees discussed above.
-
-To get the sinks for a tag just use tag `tag_t` to disambiguate overloads of
-member functions as in the following example:
-
-```cpp
-registry.construction<MyTag>(entt::tag_t{}).connect<&MyFreeFunction>();
-registry.destruction<MyTag>(entt::tag_t{}).connect<MyClass, &MyClass::member>(&instance);
-```
-
-Listeners for tags and components are managed separately and do not influence
-each other in any case. Therefore, note that the greater the number of listeners
-for a type, the greater the performance hit when a tag of the given type is
-created or destroyed.
-
 ## Runtime components
 
 Defining components at runtime is useful to support plugin systems and mods in
@@ -456,13 +354,10 @@ to work with the type system.
 In `EnTT`, identifiers are easily accessible:
 
 ```cpp
-entt::DefaultRegistry registry;
-
-// standard component identifier
-auto ctype = registry.type<Position>();
+entt::registry registry;
 
-// single instance component identifier
-auto ttype = registry.type<PlayingCharacter>(entt::tag_t{});
+// component identifier
+auto type = registry.type<position>();
 ```
 
 Once the identifiers are made available, almost everything becomes pretty
@@ -499,7 +394,7 @@ In fact, there are two functions that respond to slightly different needs:
 * Components can be sorted directly:
 
   ```cpp
-  registry.sort<Renderable>([](const auto &lhs, const auto &rhs) {
+  registry.sort<renderable>([](const auto &lhs, const auto &rhs) {
       return lhs.z < rhs.z;
 
   });
@@ -515,25 +410,24 @@ In fact, there are two functions that respond to slightly different needs:
 * Components can be sorted according to the order imposed by another component:
 
   ```cpp
-  registry.sort<Movement, Physics>();
+  registry.sort<movement, physics>();
   ```
 
-  In this case, instances of `Movement` are arranged in memory so that cache
+  In this case, instances of `movement` are arranged in memory so that cache
   misses are minimized when the two components are iterated together.
 
 ## Snapshot: complete vs continuous
 
-The `Registry` class offers basic support to serialization.<br/>
-It doesn't convert components and tags to bytes directly, there wasn't the need
-of another tool for serialization out there. Instead, it accepts an opaque
-object with a suitable interface (namely an _archive_) to serialize its internal
-data structures and restore them later. The way types and instances are
-converted to a bunch of bytes is completely in charge to the archive and thus to
-final users.
+The `registry` class offers basic support to serialization.<br/>
+It doesn't convert components to bytes directly, there wasn't the need of
+another tool for serialization out there. Instead, it accepts an opaque object
+with a suitable interface (namely an _archive_) to serialize its internal data
+structures and restore them later. The way types and instances are converted to
+a bunch of bytes is completely in charge to the archive and thus to final users.
 
 The goal of the serialization part is to allow users to make both a dump of the
-entire registry or a narrower snapshot, that is to select only the components
-and the tags in which they are interested.<br/>
+entire registry or a narrower snapshot, that is to select only the components in
+which they are interested.<br/>
 Intuitively, the use cases are different. As an example, the first approach is
 suitable for local save/restore functionalities while the latter is suitable for
 creating client-server applications and for transferring somehow parts of the
@@ -546,13 +440,12 @@ parts of it.
 Example of use:
 
 ```cpp
-OutputArchive output;
+output_archive output;
 
 registry.snapshot()
     .entities(output)
     .destroyed(output)
-    .component<AComponent, AnotherComponent>(output)
-    .tag<MyTag>(output);
+    .component<a_component, another_component>(output);
 ```
 
 It isn't necessary to invoke all these functions each and every time. What
@@ -589,17 +482,14 @@ shouldn't be serialized for some reasons.<br/>
 As an example:
 
 ```cpp
-const auto view = registry.view<Serialize>();
-OutputArchive output;
+const auto view = registry.view<serialize>();
+output_archive output;
 
-registry.snapshot()
-    .component<AComponent, AnotherComponent>(output, view.cbegin(), view.cend());
+registry.snapshot().component<a_component, another_component>(output, view.cbegin(), view.cend());
 ```
 
-The `tag` member function is similar to the previous one, apart from the fact
-that it works with tags and not with components.<br/>
-Note also that both `component` and `tag` store items along with entities. It
-means that they work properly without a call to the `entities` member function.
+Note that `component` stores items along with entities. It means that it works
+properly without a call to the `entities` member function.
 
 Once a snapshot is created, there exist mainly two _ways_ to load it: as a whole
 and in a kind of _continuous mode_.<br/>
@@ -610,19 +500,18 @@ The following sections describe both loaders and archives in details.
 A snapshot loader requires that the destination registry be empty and loads all
 the data at once while keeping intact the identifiers that the entities
 originally had.<br/>
-To do that, the registry offers a member function named `restore` that returns a
+To do that, the registry offers a member function named `loader` that returns a
 temporary object properly initialized to _restore_ a snapshot.
 
 Example of use:
 
 ```cpp
-InputArchive input;
+input_archive input;
 
-registry.restore()
+registry.loader()
     .entities(input)
     .destroyed(input)
-    .component<AComponent, AnotherComponent>(input)
-    .tag<MyTag>(input)
+    .component<a_component, another_component>(input)
     .orphans();
 ```
 
@@ -636,15 +525,14 @@ the versions that the entities originally had at the source.
 
 The `component` member function restores all and only the components specified
 and assigns them to the right entities. Note that the template parameter list
-must be exactly the same used during the serialization. The same applies to the
-`tag` member function.
+must be exactly the same used during the serialization.
 
-The `orphans` member function literally destroys those entities that have
-neither components nor tags. It's usually useless if the snapshot is a full dump
-of the source. However, in case all the entities are serialized but only few
-components and tags are saved, it could happen that some of the entities have
-neither components nor tags once restored. The best users can do to deal with
-them is to destroy those entities and thus update their versions.
+The `orphans` member function literally destroys those entities that have no
+components attached. It's usually useless if the snapshot is a full dump of the
+source. However, in case all the entities are serialized but only few components
+are saved, it could happen that some of the entities have no components once
+restored. The best users can do to deal with them is to destroy those entities
+and thus update their versions.
 
 ### Continuous loader
 
@@ -655,8 +543,8 @@ destination one step at a time.<br/>
 Identifiers that entities originally had are not transferred to the target.
 Instead, the loader maps remote identifiers to local ones while restoring a
 snapshot. Because of that, this kind of loader offers a way to update
-automatically identifiers that are part of components or tags (as an example, as
-data members or gathered in a container).<br/>
+automatically identifiers that are part of components (as an example, as data
+members or gathered in a container).<br/>
 Another difference with the snapshot loader is that the continuous loader does
 not need to work with the private data structures of a registry. Furthermore, it
 has an internal state that must persist over time. Therefore, there is no reason
@@ -666,13 +554,12 @@ temporary object.
 Example of use:
 
 ```cpp
-entt::ContinuousLoader<entity_type> loader{registry};
-InputArchive input;
+entt::continuous_loader<entity_type> loader{registry};
+input_archive input;
 
 loader.entities(input)
     .destroyed(input)
-    .component<AComponent, AnotherComponent, DirtyComponent>(input, &DirtyComponent::parent, &DirtyComponent::child)
-    .tag<MyTag, DirtyTag>(input, &DirtyTag::container)
+    .component<a_component, another_component, dirty_component>(input, &dirty_component::parent, &dirty_component::child)
     .orphans()
     .shrink();
 ```
@@ -688,16 +575,16 @@ remote entity identifier not yet registered by the loader, the latter creates a
 local identifier so that it can keep the local entity in sync with the remote
 one.
 
-The `component` and `tag` member functions restore all and only the components
-and the tags specified and assign them to the right entities.<br/>
-In case the component or the tag contains entities itself (either as data
-members of type `entity_type` or as containers of entities), the loader can
-update them automatically. To do that, it's enough to specify the data members
-to update as shown in the example.
+The `component` member function restores all and only the components specified
+and assigns them to the right entities.<br/>
+In case the component contains entities itself (either as data members of type
+`entity_type` or as containers of entities), the loader can update them
+automatically. To do that, it's enough to specify the data members to update as
+shown in the example.
 
-The `orphans` member function literally destroys those entities that have
-neither components nor tags after a restore. It has exactly the same purpose
-described in the previous section and works the same way.
+The `orphans` member function literally destroys those entities that have no
+components after a restore. It has exactly the same purpose described in the
+previous section and works the same way.
 
 Finally, `shrink` helps to purge local entities that no longer have a remote
 conterpart. Users should invoke this member function after restoring each
@@ -721,9 +608,9 @@ In particular:
   Where `Entity` is the type of the entities used by the registry. Note that all
   the member functions of the snapshot class make also an initial call to this
   endpoint to save the _size_ of the set they are going to store.<br/>
-  In addition, an archive must accept a pair of entity and either component or
-  tag for each type to be serialized. Therefore, given a type `T`, the archive
-  must contain a function call operator with the following signature:
+  In addition, an archive must accept a pair of entity and component for each
+  type to be serialized. Therefore, given a type `T`, the archive must contain a
+  function call operator with the following signature:
 
   ```cpp
   void operator()(Entity, const T &);
@@ -744,9 +631,9 @@ In particular:
   underlying storage and copy it in the given variable. Note that all the member
   functions of a loader class make also an initial call to this endpoint to read
   the _size_ of the set they are going to load.<br/>
-  In addition, the archive must accept a pair of entity and either component or
-  tag for each type to be restored. Therefore, given a type `T`, the archive
-  must contain a function call operator with the following signature:
+  In addition, the archive must accept a pair of entity and component for each
+  type to be restored. Therefore, given a type `T`, the archive must contain a
+  function call operator with the following signature:
 
   ```cpp
   void operator()(Entity &, T &);
@@ -779,11 +666,11 @@ how many prototypes they want, each one initialized differently from the others.
 The following is an example of use of a prototype:
 
 ```cpp
-entt::DefaultRegistry registry;
-entt::DefaultPrototype prototype{registry};
+entt::registry registry;
+entt::prototype prototype{registry};
 
-prototype.set<Position>(100.f, 100.f);
-prototype.set<Velocity>(0.f, 0.f);
+prototype.set<position>(100.f, 100.f);
+prototype.set<velocity>(0.f, 0.f);
 
 // ...
 
@@ -847,11 +734,11 @@ The list of helpers will grow longer as time passes and new ideas come out.
 A _dependency function_ is a predefined listener, actually a function template
 to use to automatically assign components to an entity when a type has a
 dependency on some other types.<br/>
-The following adds components `AType` and `AnotherType` whenever `MyType` is
+The following adds components `a_type` and `another_type` whenever `my_type` is
 assigned to an entity:
 
 ```cpp
-entt::connnect<AType, AnotherType>(registry.construction<MyType>());
+entt::connnect<a_type, another_type>(registry.construction<my_type>());
 ```
 
 A component is assigned to an entity and thus default initialized only in case
@@ -860,7 +747,7 @@ be overriden.<br/>
 A dependency can easily be broken by means of the following function template:
 
 ```cpp
-entt::disconnect<AType, AnotherType>(registry.construction<MyType>());
+entt::disconnect<a_type, another_type>(registry.construction<my_type>());
 ```
 
 ### Labels
@@ -888,14 +775,14 @@ registry.valid(entt::null);
 ```
 
 In other terms, a registry will reject the null entity in all cases because it
-isn't considered valid. It means that the null entity cannot own components or
-tags for obvious reasons.<br/>
+isn't considered valid. It means that the null entity cannot own components for
+obvious reasons.<br/>
 The type of the null entity is internal and should not be used for any purpose
 other than defining the null entity itself. However, there exist implicit
 conversions from the null entity to identifiers of any allowed type:
 
 ```cpp
-typename entt::DefaultRegistry::entity_type null = entt::null;
+typename entt::registry::entity_type null = entt::null;
 ```
 
 Similarly, the null entity can be compared to any other identifier:
@@ -915,9 +802,9 @@ view can only iterate entities and their components, then read or update the
 data members of the latter.<br/>
 It is a subtle difference that can help designing a better software sometimes.
 
-There are mainly four kinds of views: standard (also known as `View`),
-persistent (also known as `PersistentView`), raw (also known as `RawView`) and
-runtime (also known as `RuntimeView`).<br/>
+There are mainly four kinds of views: standard (also known as `view`),
+persistent (also known as `persistent_view`), raw (also known as `raw_view`) and
+runtime (also known as `runtime_view`).<br/>
 All of them have pros and cons to take in consideration. In particular:
 
 * Standard views:
@@ -1023,10 +910,10 @@ All that they share is the way they are created by means of a registry:
 
 ```cpp
 // single component standard view
-auto single = registry.view<Position>();
+auto single = registry.view<position>();
 
 // multi component standard view
-auto multi = registry.view<Position, Velocity>();
+auto multi = registry.view<position, velocity>();
 ```
 
 For all that remains, it's worth discussing them separately.<br/>
@@ -1048,10 +935,10 @@ fact, they return newly created and correctly initialized iterators whenever
 To iterate a single component standard view, either use it in a range-for loop:
 
 ```cpp
-auto view = registry.view<Renderable>();
+auto view = registry.view<renderable>();
 
 for(auto entity: view) {
-    Renderable &renderable = view.get(entity);
+    renderable &renderable = view.get(entity);
 
     // ...
 }
@@ -1061,7 +948,7 @@ Or rely on the `each` member function to iterate entities and get all their
 components at once:
 
 ```cpp
-registry.view<Renderable>().each([](auto entity, auto &renderable) {
+registry.view<renderable>().each([](auto entity, auto &renderable) {
     // ...
 });
 ```
@@ -1093,15 +980,15 @@ fact, they return newly created and correctly initialized iterators whenever
 To iterate a multi component standard view, either use it in a range-for loop:
 
 ```cpp
-auto view = registry.view<Position, Velocity>();
+auto view = registry.view<position, velocity>();
 
 for(auto entity: view) {
     // a component at a time ...
-    Position &position = view.get<Position>(entity);
-    Velocity &velocity = view.get<Velocity>(entity);
+    auto &position = view.get<position>(entity);
+    auto &velocity = view.get<velocity>(entity);
 
     // ... or multiple components at once
-    std::tuple<Position &, Velocity &> tup = view.get<Position, Velocity>(entity);
+    auto &[pos, vel] = view.get<position, velocity>(entity);
 
     // ...
 }
@@ -1111,7 +998,7 @@ Or rely on the `each` member function to iterate entities and get all their
 components at once:
 
 ```cpp
-registry.view<Position, Velocity>().each([](auto entity, auto &position, auto &velocity) {
+registry.view<position, velocity>().each([](auto entity, auto &pos, auto &vel) {
     // ...
 });
 ```
@@ -1132,12 +1019,10 @@ tightly packed in memory for fast iterations.<br/>
 In general, persistent views don't stay true to the order of any set of
 components unless users explicitly sort them.
 
-Persistent views can be used only to iterate multiple components. To create this
-kind of views, the tag `persistent_t` must also be used in order to disambiguate
-overloads of the `view` member function:
+Persistent views can be used only to iterate multiple components:
 
 ```cpp
-auto view = registry.view<Position, Velocity>(entt::persistent_t{});
+auto view = registry.persistent_view<position, velocity>();
 ```
 
 There is no need to store views around for they are extremely cheap to
@@ -1149,13 +1034,13 @@ time they are constructed and this could be quite costly. To avoid it, consider
 asking to the registry to _prepare_ them when no entities have been created yet:
 
 ```cpp
-registry.prepare<Position, Velocity>();
+registry.prepare_persistent_view<position, velocity>();
 ```
 
-If the registry is empty, preparation is extremely fast. Moreover the `prepare`
-member function template is idempotent. Feel free to invoke it even more than
-once: if the view has been already prepared before, the function returns
-immediately and does nothing.
+If the registry is empty, preparation is extremely fast. Moreover the
+`prepare_persistent_view` member function template is idempotent. Feel free to
+invoke it even more than once: if the view has been already prepared before, the
+function returns immediately and does nothing.
 
 A persistent view offers a bunch of functionalities to get the number of
 entities it's going to return, a raw access to the entity list and the
@@ -1167,15 +1052,15 @@ Refer to the inline documentation for all the details.
 To iterate a persistent view, either use it in a range-for loop:
 
 ```cpp
-auto view = registry.view<Position, Velocity>(entt::persistent_t{});
+auto view = registry.persistent_view<position, velocity>();
 
 for(auto entity: view) {
     // a component at a time ...
-    Position &position = view.get<Position>(entity);
-    Velocity &velocity = view.get<Velocity>(entity);
+    auto &position = view.get<position>(entity);
+    auto &velocity = view.get<velocity>(entity);
 
     // ... or multiple components at once
-    std::tuple<Position &, Velocity &> tup = view.get<Position, Velocity>(entity);
+    auto &[pos, vel] = view.get<position, velocity>(entity);
 
     // ...
 }
@@ -1185,7 +1070,7 @@ Or rely on the `each` member function to iterate entities and get all their
 components at once:
 
 ```cpp
-registry.view<Position, Velocity>(entt::persistent_t{}).each([](auto entity, auto &position, auto &velocity) {
+registry.persistent_view<position, velocity>().each([](auto entity, auto &pos, auto &vel) {
     // ...
 });
 ```
@@ -1207,12 +1092,10 @@ going to return and a raw access to the entity list as well as to the component
 list.<br/>
 Refer to the inline documentation for all the details.
 
-Raw views can be used only to iterate components for a single type. To create
-this kind of views, the tag `raw_t` must also be used in order to disambiguate
-overloads of the `view` member function:
+Raw views can be used only to iterate components for a single type:
 
 ```cpp
-auto view = registry.view<Renderable>(entt::raw_t{});
+auto view = registry.raw_view<renderable>();
 ```
 
 There is no need to store views around for they are extremely cheap to
@@ -1222,7 +1105,7 @@ fact, they return newly created and correctly initialized iterators whenever
 To iterate a raw view, use it in a range-for loop:
 
 ```cpp
-auto view = registry.view<Renderable>(entt::raw_t{});
+auto view = registry.raw_view<renderable>();
 
 for(auto &&component: raw) {
     // ...
@@ -1232,7 +1115,7 @@ for(auto &&component: raw) {
 Or rely on the `each` member function:
 
 ```cpp
-registry.view<Renderable>(entt::raw_t{}).each([](auto &renderable) {
+registry.raw_view<renderable>().each([](auto &renderable) {
     // ...
 });
 ```
@@ -1262,17 +1145,17 @@ To iterate a runtime view, either use it in a range-for loop:
 
 ```cpp
 using component_type = typename decltype(registry)::component_type;
-component_type types[] = { registry.type<Position>(), registry.type<Velocity>() };
+component_type types[] = { registry.type<position>(), registry.type<velocity>() };
 
-auto view = registry.view(std::cbegin(types), std::cend(types));
+auto view = registry.runtime_view(std::cbegin(types), std::cend(types));
 
 for(auto entity: view) {
     // a component at a time ...
-    Position &position = registry.get<Position>(entity);
-    Velocity &velocity = registry.get<Velocity>(entity);
+    auto &position = registry.get<position>(entity);
+    auto &velocity = registry.get<velocity>(entity);
 
     // ... or multiple components at once
-    std::tuple<Position &, Velocity &> tup = view.get<Position, Velocity>(entity);
+    auto &[pos, vel] = view.get<position, velocity>(entity);
 
     // ...
 }
@@ -1282,9 +1165,9 @@ Or rely on the `each` member function to iterate entities:
 
 ```cpp
 using component_type = typename decltype(registry)::component_type;
-component_type types[] = { registry.type<Position>(), registry.type<Velocity>() };
+component_type types[] = { registry.type<position>(), registry.type<velocity>() };
 
-auto view = registry.view(std::cbegin(types), std::cend(types)).each([](auto entity) {
+auto view = registry.runtime_view(std::cbegin(types), std::cend(types)).each([](auto entity) {
     // ...
 });
 ```
@@ -1320,8 +1203,7 @@ combining this function with a bunch of custom tests.<br/>
 In all the other cases, this is the way to go.
 
 There exists also another member function to use to retrieve orphans. An orphan
-is an entity that is still in use and has neither assigned components nor
-tags.<br/>
+is an entity that is still in use and has no assigned components.<br/>
 The signature of the function is the same of `each`:
 
 ```cpp

+ 11 - 11
docs/locator.md

@@ -32,13 +32,13 @@ initialize it. As an example:
 
 ```cpp
 // the service has no base type, a locator is used to treat it as a kind of singleton
-entt::ServiceLocator<MyService>::set(params...);
+entt::service_locator<my_service>::set(params...);
 
 // sets up an opaque service
-entt::ServiceLocator<AudioInterface>::set<AudioImplementation>(params...);
+entt::service_locator<audio_interface>::set<audio_implementation>(params...);
 
 // resets (destroys) the service
-entt::ServiceLocator<AudioInterface>::reset();
+entt::service_locator<audio_interface>::reset();
 ```
 
 The locator can also be queried to know if an active service is currently set
@@ -46,30 +46,30 @@ and to retrieve it if necessary (either as a pointer or as a reference):
 
 ```cpp
 // no service currently set
-auto empty = entt::ServiceLocator<AudioInterface>::empty();
+auto empty = entt::service_locator<audio_interface>::empty();
 
 // gets a (possibly empty) shared pointer to the service ...
-std::shared_ptr<AudioInterface> ptr = entt::ServiceLocator<AudioInterface>::get();
+std::shared_ptr<audio_interface> ptr = entt::service_locator<audio_interface>::get();
 
 // ... or a reference, but it's undefined behaviour if the service isn't set yet
-AudioInterface &ref = entt::ServiceLocator<AudioInterface>::ref();
+audio_interface &ref = entt::service_locator<audio_interface>::ref();
 ```
 
 A common use is to wrap the different locators in a container class, creating
 aliases for the various services:
 
 ```cpp
-struct Locator {
-    using Camera = entt::ServiceLocator<CameraInterface>;
-    using Audio = entt::ServiceLocator<AudioInterface>;
+struct locator {
+    using camera = entt::service_locator<camera_interface>;
+    using audio = entt::service_locator<audio_interface>;
     // ...
 };
 
 // ...
 
 void init() {
-    Locator::Camera::set<CameraNull>();
-    Locator::Audio::set<AudioImplementation>(params...);
+    locator::camera::set<camera_null>();
+    locator::audio::set<audio_implementation>(params...);
     // ...
 }
 ```

+ 7 - 7
docs/process.md

@@ -24,7 +24,7 @@ that users can use to define and execute cooperative processes.
 
 # The process
 
-A typical process must inherit from the `Process` class template that stays true
+A typical process must inherit from the `process` class template that stays true
 to the CRTP idiom. Moreover, derived classes must specify what's the intended
 type for elapsed times.
 
@@ -70,7 +70,7 @@ life cycle of a process from a derived class.
 Here is a minimal example for the sake of curiosity:
 
 ```cpp
-struct MyProcess: entt::Process<MyProcess, std::uint32_t> {
+struct my_process: entt::process<my_process, std::uint32_t> {
     using delta_type = std::uint32_t;
 
     void update(delta_type delta, void *) {
@@ -137,7 +137,7 @@ Using a scheduler is straightforward. To create it, users must provide only the
 type for the elapsed times and no arguments at all:
 
 ```cpp
-Scheduler<std::uint32_t> scheduler;
+entt::scheduler<std::uint32_t> scheduler;
 ```
 
 It has member functions to query its internal data structures, like `empty` or
@@ -148,7 +148,7 @@ It has member functions to query its internal data structures, like `empty` or
 const auto empty = scheduler.empty();
 
 // gets the number of processes still running
-Scheduler<std::uint32_t>::size_type size = scheduler.size();
+entt::scheduler<std::uint32_t>::size_type size = scheduler.size();
 
 // resets the scheduler to its initial state and discards all the processes
 scheduler.clear();
@@ -156,12 +156,12 @@ scheduler.clear();
 
 To attach a process to a scheduler there are mainly two ways:
 
-* If the process inherits from the `Process` class template, it's enough to
+* If the process inherits from the `process` class template, it's enough to
   indicate its type and submit all the parameters required to construct it to
   the `attach` member function:
 
   ```cpp
-  scheduler.attach<MyProcess>("foobar");
+  scheduler.attach<my_process>("foobar");
   ```
 
 * Otherwise, in case of a lambda or a functor, it's enough to provide an
@@ -185,7 +185,7 @@ scheduler.attach([](auto delta, void *, auto succeed, auto fail) {
     // ...
 })
 // appends a child in the form of a process class
-.then<MyProcess>();
+.then<my_process>();
 ```
 
 To update a scheduler and thus all its processes, the `update` member function

+ 19 - 19
docs/resource.md

@@ -38,29 +38,29 @@ whatever. There are no limits.<br/>
 As a minimal example:
 
 ```cpp
-struct MyResource { const int value; };
+struct my_resource { const int value; };
 ```
 
 A _loader_ is a class the aim of which is to load a specific resource. It has to
 inherit directly from the dedicated base class as in the following example:
 
 ```cpp
-struct MyLoader final: entt::ResourceLoader<MyLoader, MyResource> {
+struct my_loader final: entt::resource_loader<my_loader, my_resource> {
     // ...
 };
 ```
 
-Where `MyResource` is the type of resources it creates.<br/>
+Where `my_resource` is the type of resources it creates.<br/>
 A resource loader must also expose a public const member function named `load`
 that accepts a variable number of arguments and returns a shared pointer to a
 resource.<br/>
 As an example:
 
 ```cpp
-struct MyLoader: entt::ResourceLoader<MyLoader, MyResource> {
-    std::shared_ptr<MyResource> load(int value) const {
+struct my_loader: entt::resource_loader<my_loader, my_resource> {
+    std::shared_ptr<my_resource> load(int value) const {
         // ...
-        return std::shared_ptr<MyResource>(new MyResource{ value });
+        return std::shared_ptr<my_resource>(new my_resource{ value });
     }
 };
 ```
@@ -76,11 +76,11 @@ Finally, a cache is a specialization of a class template tailored to a specific
 resource:
 
 ```cpp
-using MyResourceCache = entt::ResourceCache<MyResource>;
+using my_resource_cache = entt::resource_cache<my_resource>;
 
 // ...
 
-MyResourceCache cache{};
+my_resource_cache cache{};
 ```
 
 The idea is to create different caches for different types of resources and to
@@ -109,19 +109,19 @@ Before to explore this part of the interface, it makes sense to mention how
 resources are identified. The type of the identifiers to use is defined as:
 
 ```cpp
-entt::ResourceCache<Resource>::resource_type
+entt::resource_cache<resource>::resource_type
 ```
 
-Where `resource_type` is an alias for `entt::HashedString`. Therefore, resource
+Where `resource_type` is an alias for `entt::hashed_string`. Therefore, resource
 identifiers are created explicitly as in the following example:
 
 ```cpp
-constexpr auto identifier = entt::ResourceCache<Resource>::resource_type{"my/resource/identifier"};
+constexpr auto identifier = entt::resource_cache<resource>::resource_type{"my/resource/identifier"};
 // this is equivalent to the following
-constexpr auto hs = entt::HashedString{"my/resource/identifier"};
+constexpr auto hs = entt::hashed_string{"my/resource/identifier"};
 ```
 
-The class `HashedString` is described in a dedicated section, so I won't do in
+The class `hashed_string` is described in a dedicated section, so I won't do in
 details here.
 
 Resources are loaded and thus stored in a cache through the `load` member
@@ -130,10 +130,10 @@ identifier and the parameters used to construct the resource as arguments:
 
 ```cpp
 // uses the identifier declared above
-cache.load<MyLoader>(identifier, 0);
+cache.load<my_loader>(identifier, 0);
 
 // uses a const char * directly as an identifier
-cache.load<MyLoader>("another/identifier", 42);
+cache.load<my_loader>("another/identifier", 42);
 ```
 
 The return value can be used to know if the resource has been loaded correctly.
@@ -141,7 +141,7 @@ In case the loader returns an invalid pointer or the resource already exists in
 the cache, a false value is returned:
 
 ```cpp
-if(!cache.load<MyLoader>("another/identifier", 42)) {
+if(!cache.load<my_loader>("another/identifier", 42)) {
     // ...
 }
 ```
@@ -159,7 +159,7 @@ There exists also a member function to use to force a reload of an already
 existing resource if needed:
 
 ```cpp
-auto result = cache.reload<MyLoader>("another/identifier", 42);
+auto result = cache.reload<my_loader>("another/identifier", 42);
 ```
 
 As above, the function returns true in case of success, false otherwise. The
@@ -170,7 +170,7 @@ snippet:
 
 ```cpp
 cache.discard(identifier);
-cache.load<MyLoader>(identifier, 42);
+cache.load<my_loader>(identifier, 42);
 ```
 
 Where the `discard` member function is used to get rid of a resource if loaded.
@@ -233,7 +233,7 @@ return a boolean value. Instead, it returns a (possibly invalid) handle for the
 resource:
 
 ```cpp
-auto handle = cache.temp<MyLoader>("another/identifier", 42);
+auto handle = cache.temp<my_loader>("another/identifier", 42);
 ```
 
 Do not forget to test the handle for validity. Otherwise, getting the reference

+ 8 - 10
docs/shared.md

@@ -4,23 +4,22 @@ To make sure that an application and a shared library that use both `EnTT` can
 interact correctly when symbols are hidden by default, there are some tricks to
 follow.<br/>
 In particular and in order to avoid undefined behaviors, all the instantiation
-of the `Family` class template shall be made explicit along with the system-wide
+of the `family` class template shall be made explicit along with the system-wide
 specifier to use to export them.
 
 At the time I'm writing this document, the classes that use internally the above
-mentioned class template are `Dispatcher`, `Emitter` and `Registry`. Therefore
-and as an example, if you use the `Registry` class template in your shared
+mentioned class template are `dispatcher`, `emitter` and `registry`. Therefore
+and as an example, if you use the `registry` class template in your shared
 library and want to set symbols visibility to _hidden_ by default, the following
 lines are required to allow it to function properly with a client that also uses
-the `Registry` somehow:
+the `registry` somehow:
 
 * On GNU/Linux:
 
   ```cpp
   namespace entt {
-      template class __attribute__((visibility("default"))) Family<struct InternalRegistryTagFamily>;
-      template class __attribute__((visibility("default"))) Family<struct InternalRegistryComponentFamily>;
-      template class __attribute__((visibility("default"))) Family<struct InternalRegistryHandlerFamily>;
+      template class __attribute__((visibility("default"))) family<struct internal_registry_component_family>;
+      template class __attribute__((visibility("default"))) family<struct internal_registry_handler_family>;
   }
   ```
 
@@ -28,9 +27,8 @@ the `Registry` somehow:
 
   ```cpp
   namespace entt {
-      template class __declspec(dllexport) Family<struct InternalRegistryTagFamily>;
-      template class __declspec(dllexport) Family<struct InternalRegistryComponentFamily>;
-      template class __declspec(dllexport) Family<struct InternalRegistryHandlerFamily>;
+      template class __declspec(dllexport) family<struct internal_registry_component_family>;
+      template class __declspec(dllexport) family<struct internal_registry_handler_family>;
   }
   ```
 

+ 52 - 42
docs/signal.md

@@ -57,10 +57,10 @@ To create instances of signal handlers there exist mainly two ways:
 
 ```cpp
 // no collector type
-entt::SigH<void(int, char)> signal;
+entt::sigh<void(int, char)> signal;
 
 // explicit collector type
-entt::SigH<void(int, char), MyCollector<bool>> collector;
+entt::sigh<void(int, char), my_collector<bool>> collector;
 ```
 
 As expected, they offer all the basic functionalities required to know how many
@@ -73,16 +73,16 @@ listeners in all their forms by means of a sink:
 ```cpp
 void foo(int, char) { /* ... */ }
 
-struct S {
-    void bar(int, char) { /* ... */ }
+struct listener {
+    void bar(const int &, char) { /* ... */ }
 };
 
 // ...
 
-S instance;
+listener instance;
 
 signal.sink().connect<&foo>();
-signal.sink().connect<S, &S::bar>(&instance);
+signal.sink().connect<&listener::bar>(&instance);
 
 // ...
 
@@ -90,7 +90,7 @@ signal.sink().connect<S, &S::bar>(&instance);
 signal.sink().disconnect<&foo>();
 
 // disconnect a specific member function of an instance ...
-signal.sink().disconnect<S, &S::bar>(&instance);
+signal.sink().disconnect<&listener::bar>(&instance);
 
 // ... or an instance as a whole
 signal.sink().disconnect(&instance);
@@ -99,6 +99,10 @@ signal.sink().disconnect(&instance);
 signal.sink().disconnect();
 ```
 
+As shown above, listeners do not have to strictly follow the signature of the
+signal. As long as a listener can be invoked with the given arguments to yield a
+result that is convertible to the given result type, everything works just fine.
+
 Once listeners are attached (or even if there are no listeners at all), events
 and data in general can be published through a signal by means of the `publish`
 member function:
@@ -111,7 +115,7 @@ To collect data, the `collect` member function should be used instead. Below is
 a minimal example to show how to use it:
 
 ```cpp
-struct MyCollector {
+struct my_collector {
     std::vector<int> vec{};
 
     bool operator()(int v) noexcept {
@@ -125,12 +129,12 @@ int g() { return 1; }
 
 // ...
 
-entt::SigH<int(), MyCollector<int>> signal;
+entt::sigh<int(), my_collector<int>> signal;
 
 signal.sink().connect<&f>();
 signal.sink().connect<&g>();
 
-MyCollector collector = signal.collect();
+my_collector collector = signal.collect();
 
 assert(collector.vec[0] == 0);
 assert(collector.vec[1] == 1);
@@ -155,7 +159,7 @@ The interface is trivial. It offers a default constructor to create empty
 delegates:
 
 ```cpp
-entt::Delegate<int(int)> delegate{};
+entt::delegate<int(int)> delegate{};
 ```
 
 All what is needed to create an instance is to specify the type of the function
@@ -170,16 +174,16 @@ There exist two functions to do that, both named `connect`:
 ```cpp
 int f(int i) { return i; }
 
-struct MyStruct {
-    int f(int i) { return i }
+struct my_struct {
+    int f(const int &i) { return i }
 };
 
 // bind a free function to the delegate
 delegate.connect<&f>();
 
 // bind a member function to the delegate
-MyStruct instance;
-delegate.connect<MyStruct, &MyStruct::f>(&instance);
+my_struct instance;
+delegate.connect<&my_struct::f>(&instance);
 ```
 
 It hasn't a `disconnect` counterpart. Instead, there exists a `reset` member
@@ -197,6 +201,11 @@ usual:
 auto ret = delegate(42);
 ```
 
+As shown above, listeners do not have to strictly follow the signature of the
+delegate. As long as a listener can be invoked with the given arguments to yield
+a result that is convertible to the given result type, everything works just
+fine.
+
 Probably too much small and pretty poor of functionalities, but the delegate
 class can help in a lot of cases and it has shown that it is worth keeping it
 within the library.
@@ -211,12 +220,13 @@ doesn't require that all the types of events are specified when declared:
 
 ```cpp
 // define a general purpose dispatcher that works with naked pointers
-entt::Dispatcher dispatcher{};
+entt::dispatcher dispatcher{};
 ```
 
 In order to register an instance of a class to a dispatcher, its type must
-expose one or more member functions of which the return types are `void` and the
-argument lists are `const E &`, for each type of event `E`.<br/>
+expose one or more member functions the arguments of which are such that
+`const E &` can be converted to them for each type of event `E`, no matter what
+the return value is.<br/>
 To ease the development, member functions that are named `receive` are
 automatically detected and have not to be explicitly specified when registered.
 In all the other cases, the name of the member function aimed to receive the
@@ -224,28 +234,28 @@ event must be provided to the `connect` member function of the sink bound to the
 specific event:
 
 ```cpp
-struct AnEvent { int value; };
-struct AnotherEvent {};
+struct an_event { int value; };
+struct another_event {};
 
-struct Listener
+struct listener
 {
-    void receive(const AnEvent &) { /* ... */ }
-    void method(const AnotherEvent &) { /* ... */ }
+    void receive(const an_event &) { /* ... */ }
+    void method(const another_event &) { /* ... */ }
 };
 
 // ...
 
-Listener listener;
-dispatcher.sink<AnEvent>().connect(&listener);
-dispatcher.sink<AnotherEvent>().connect<Listener, &Listener::method>(&listener);
+listener listener;
+dispatcher.sink<an_event>().connect(&listener);
+dispatcher.sink<another_event>().connect<&listener::method>(&listener);
 ```
 
 The `disconnect` member function follows the same pattern and can be used to
 selectively remove listeners:
 
 ```cpp
-dispatcher.sink<AnEvent>().disconnect(&listener);
-dispatcher.sink<AnotherEvent>().disconnect<Listener, &Listener::method>(&listener);
+dispatcher.sink<an_event>().disconnect(&listener);
+dispatcher.sink<another_event>().disconnect<&listener::method>(&listener);
 ```
 
 The `trigger` member function serves the purpose of sending an immediate event
@@ -256,8 +266,8 @@ it.<br/>
 As an example:
 
 ```cpp
-dispatcher.trigger<AnEvent>(42);
-dispatcher.trigger<AnotherEvent>();
+dispatcher.trigger<an_event>(42);
+dispatcher.trigger<another_event>();
 ```
 
 Listeners are invoked immediately, order of execution isn't guaranteed. This
@@ -269,8 +279,8 @@ allows to maintain control over the moment they are sent to listeners. The
 signature of this method is more or less the same of `trigger`:
 
 ```cpp
-dispatcher.enqueue<AnEvent>(42);
-dispatcher.enqueue<AnotherEvent>();
+dispatcher.enqueue<an_event>(42);
+dispatcher.enqueue<another_event>();
 ```
 
 Events are stored aside until the `update` member function is invoked, then all
@@ -278,7 +288,7 @@ the messages that are still pending are sent to the listeners at once:
 
 ```cpp
 // emits all the events of the given type at once
-dispatcher.update<MyEvent>();
+dispatcher.update<my_event>();
 
 // emits all the events queued so far at once
 dispatcher.update();
@@ -299,7 +309,7 @@ To create a custom emitter type, derived classes must inherit directly from the
 base class as:
 
 ```cpp
-struct MyEmitter: Emitter<MyEmitter> {
+struct my_emitter: emitter<my_emitter> {
     // ...
 }
 ```
@@ -320,14 +330,14 @@ the other side, an event emitter is movable but not copyable by default.
 To create new instances of an emitter, no arguments are required:
 
 ```cpp
-MyEmitter emitter{};
+my_emitter emitter{};
 ```
 
 Listeners must be movable and callable objects (free functions, lambdas,
 functors, `std::function`s, whatever) whose function type is:
 
 ```cpp
-void(const Event &, MyEmitter &)
+void(const Event &, my_emitter &)
 ```
 
 Where `Event` is the type of event they want to listen.<br/>
@@ -340,7 +350,7 @@ slightly from each other:
   As an example:
 
   ```cpp
-  auto conn = emitter.on<MyEvent>([](const MyEvent &event, MyEmitter &emitter) {
+  auto conn = emitter.on<my_event>([](const my_event &event, my_emitter &emitter) {
       // ...
   });
   ```
@@ -355,7 +365,7 @@ slightly from each other:
   As an example:
 
   ```cpp
-  auto conn = emitter.once<MyEvent>([](const MyEvent &event, MyEmitter &emitter) {
+  auto conn = emitter.once<my_event>([](const my_event &event, my_emitter &emitter) {
       // ...
   });
   ```
@@ -375,7 +385,7 @@ listeners for a given type of event or to clear the emitter:
 
 ```cpp
 // removes all the listener for the specific event
-emitter.clear<MyEvent>();
+emitter.clear<my_event>();
 
 // removes all the listeners registered so far
 emitter.clear();
@@ -386,11 +396,11 @@ member function offers a convenient approach that relieves users from having to
 create the event:
 
 ```cpp
-struct MyEvent { int i; };
+struct my_event { int i; };
 
 // ...
 
-emitter.publish<MyEvent>(42);
+emitter.publish<my_event>(42);
 ```
 
 Finally, the `empty` member function tests if there exists at least either a
@@ -400,7 +410,7 @@ listener registered with the event emitter or to a given type of event:
 bool empty;
 
 // checks if there is any listener registered for the specific event
-empty = emitter.empty<MyEvent>();
+empty = emitter.empty<my_event>();
 
 // checks it there are listeners registered with the event emitter
 empty = emitter.empty();

+ 3 - 3
src/entt/core/algorithm.hpp

@@ -18,7 +18,7 @@ namespace entt {
  * This class fills the gap by wrapping some flavors of `std::sort` in a
  * function object.
  */
-struct StdSort final {
+struct std_sort final {
     /**
      * @brief Sorts the elements in a range.
      *
@@ -40,7 +40,7 @@ struct StdSort final {
 
 
 /*! @brief Function object for performing insertion sort. */
-struct InsertionSort final {
+struct insertion_sort final {
     /**
      * @brief Sorts the elements in a range.
      *
@@ -73,7 +73,7 @@ struct InsertionSort final {
 
 
 /*! @brief Function object for performing bubble sort (single iteration). */
-struct OneShotBubbleSort final {
+struct one_shot_bubble_sort final {
     /**
      * @brief Tries to sort the elements in a range.
      *

+ 6 - 17
src/entt/core/family.hpp

@@ -19,34 +19,23 @@ namespace entt {
  * identifiers.
  */
 template<typename...>
-class Family {
-    static std::atomic<std::size_t> identifier;
+class family {
+    inline static std::atomic<std::size_t> identifier;
 
     template<typename...>
-    static std::size_t family() ENTT_NOEXCEPT {
-        static const std::size_t value = identifier.fetch_add(1);
-        return value;
-    }
+    inline static const auto inner = identifier.fetch_add(1);
 
 public:
     /*! @brief Unsigned integer type. */
     using family_type = std::size_t;
 
-    /**
-     * @brief Returns an unique identifier for the given type.
-     * @return Statically generated unique identifier for the given type.
-     */
+    /*! @brief Statically generated unique identifier for the given type. */
     template<typename... Type>
-    inline static family_type type() ENTT_NOEXCEPT {
-        return family<std::decay_t<Type>...>();
-    }
+    // at the time I'm writing, clang crashes during compilation if auto is used in place of family_type here
+    inline static const family_type type = inner<std::decay_t<Type>...>;
 };
 
 
-template<typename... Types>
-std::atomic<std::size_t> Family<Types...>::identifier{};
-
-
 }
 
 

+ 26 - 10
src/entt/core/hashed_string.hpp

@@ -19,10 +19,10 @@ namespace entt {
  * Because of that, a hashed string can also be used in constant expressions if
  * required.
  */
-class HashedString final {
-    struct ConstCharWrapper final {
+class hashed_string final {
+    struct const_wrapper final {
         // non-explicit constructor on purpose
-        constexpr ConstCharWrapper(const char *str) ENTT_NOEXCEPT: str{str} {}
+        constexpr const_wrapper(const char *str) ENTT_NOEXCEPT: str{str} {}
         const char *str;
     };
 
@@ -46,14 +46,14 @@ public:
      * characters.<br/>
      * Example of use:
      * @code{.cpp}
-     * HashedString sh{"my.png"};
+     * hashed_string hs{"my.png"};
      * @endcode
      *
      * @tparam N Number of characters of the identifier.
      * @param str Human-readable identifer.
      */
     template<std::size_t N>
-    constexpr HashedString(const char (&str)[N]) ENTT_NOEXCEPT
+    constexpr hashed_string(const char (&str)[N]) ENTT_NOEXCEPT
         : hash{helper(offset, str)}, str{str}
     {}
 
@@ -63,10 +63,26 @@ public:
      *
      * @param wrapper Helps achieving the purpose by relying on overloading.
      */
-    explicit constexpr HashedString(ConstCharWrapper wrapper) ENTT_NOEXCEPT
+    explicit constexpr hashed_string(const_wrapper wrapper) ENTT_NOEXCEPT
         : hash{helper(offset, wrapper.str)}, str{wrapper.str}
     {}
 
+    /**
+     * @brief Returns the human-readable representation of a hashed string.
+     * @return The string used to initialize the instance.
+     */
+    constexpr const char * data() const ENTT_NOEXCEPT {
+        return str;
+    }
+
+    /**
+     * @brief Returns the numeric representation of a hashed string.
+     * @return The numeric representation of the instance.
+     */
+    constexpr hash_type value() const ENTT_NOEXCEPT {
+        return hash;
+    }
+
     /**
      * @brief Returns the human-readable representation of a hashed string.
      * @return The string used to initialize the instance.
@@ -84,7 +100,7 @@ public:
      * @param other Hashed string with which to compare.
      * @return True if the two hashed strings are identical, false otherwise.
      */
-    constexpr bool operator==(const HashedString &other) const ENTT_NOEXCEPT {
+    constexpr bool operator==(const hashed_string &other) const ENTT_NOEXCEPT {
         return hash == other.hash;
     }
 
@@ -100,7 +116,7 @@ private:
  * @param rhs A valid hashed string.
  * @return True if the two hashed strings are identical, false otherwise.
  */
-constexpr bool operator!=(const HashedString &lhs, const HashedString &rhs) ENTT_NOEXCEPT {
+constexpr bool operator!=(const hashed_string &lhs, const hashed_string &rhs) ENTT_NOEXCEPT {
     return !(lhs == rhs);
 }
 
@@ -113,8 +129,8 @@ constexpr bool operator!=(const HashedString &lhs, const HashedString &rhs) ENTT
  * @param str The literal without its suffix.
  * @return A properly initialized hashed string.
  */
-constexpr entt::HashedString operator"" ENTT_HS_SUFFIX(const char *str, std::size_t) ENTT_NOEXCEPT {
-    return entt::HashedString{str};
+constexpr entt::hashed_string operator"" ENTT_HS_SUFFIX(const char *str, std::size_t) ENTT_NOEXCEPT {
+    return entt::hashed_string{str};
 }
 
 

+ 9 - 48
src/entt/core/ident.hpp

@@ -12,34 +12,6 @@
 namespace entt {
 
 
-/**
- * @cond TURN_OFF_DOXYGEN
- * Internal details not to be documented.
- */
-
-
-namespace internal {
-
-
-template<typename...>
-struct IsPartOf;
-
-template<typename Type, typename Current, typename... Other>
-struct IsPartOf<Type, Current, Other...>: std::conditional_t<std::is_same<Type, Current>::value, std::true_type, IsPartOf<Type, Other...>> {};
-
-template<typename Type>
-struct IsPartOf<Type>: std::false_type {};
-
-
-}
-
-
-/**
- * Internal details not to be documented.
- * @endcond TURN_OFF_DOXYGEN
- */
-
-
 /**
  * @brief Types identifiers.
  *
@@ -51,13 +23,13 @@ struct IsPartOf<Type>: std::false_type {};
  * Identifiers are constant expression and can be used in any context where such
  * an expression is required. As an example:
  * @code{.cpp}
- * using ID = entt::Identifier<AType, AnotherType>;
+ * using id = entt::identifier<a_type, another_type>;
  *
- * switch(aTypeIdentifier) {
- * case ID::get<AType>():
+ * switch(a_type_identifier) {
+ * case id::type<a_type>:
  *     // ...
  *     break;
- * case ID::get<AnotherType>():
+ * case id::type<another_type>:
  *     // ...
  *     break;
  * default:
@@ -68,33 +40,22 @@ struct IsPartOf<Type>: std::false_type {};
  * @tparam Types List of types for which to generate identifiers.
  */
 template<typename... Types>
-class Identifier final {
+class identifier final {
     using tuple_type = std::tuple<std::decay_t<Types>...>;
 
     template<typename Type, std::size_t... Indexes>
     static constexpr std::size_t get(std::index_sequence<Indexes...>) ENTT_NOEXCEPT {
-        static_assert(internal::IsPartOf<Type, Types...>::value, "!");
-
-        std::size_t max{};
-        using accumulator_type = std::size_t[];
-        accumulator_type accumulator = { (max = std::is_same<Type, std::tuple_element_t<Indexes, tuple_type>>::value ? Indexes : max)... };
-        (void)accumulator;
-        return max;
+        static_assert(std::disjunction_v<std::is_same<Type, Types>...>);
+        return (0 + ... + (std::is_same_v<Type, std::tuple_element_t<Indexes, tuple_type>> ? Indexes : std::size_t{}));
     }
 
 public:
     /*! @brief Unsigned integer type. */
     using identifier_type = std::size_t;
 
-    /**
-     * @brief Returns the identifier associated with a given type.
-     * @tparam Type of which to return the identifier.
-     * @return The identifier associated with the given type.
-     */
+    /*! @brief Statically generated unique identifier for the given type. */
     template<typename Type>
-    static constexpr identifier_type get() ENTT_NOEXCEPT {
-        return get<std::decay_t<Type>>(std::make_index_sequence<sizeof...(Types)>{});
-    }
+    inline static const identifier_type type = get<std::decay_t<Type>>(std::make_index_sequence<sizeof...(Types)>{});
 };
 
 

+ 5 - 11
src/entt/core/monostate.hpp

@@ -4,7 +4,6 @@
 
 #include <atomic>
 #include <cassert>
-#include "family.hpp"
 #include "hashed_string.hpp"
 
 
@@ -22,8 +21,8 @@ namespace entt {
  * both during an assignment and when they try to read back their data.
  * Otherwise, they can incur in unexpected results.
  */
-template<HashedString::hash_type>
-struct Monostate {
+template<hashed_string::hash_type>
+struct monostate {
     /**
      * @brief Assigns a value of a specific type to a given key.
      * @tparam Type Type of the value to assign.
@@ -31,7 +30,7 @@ struct Monostate {
      */
     template<typename Type>
     void operator=(Type val) const ENTT_NOEXCEPT {
-        Monostate::value<Type> = val;
+        value<Type> = val;
     }
 
     /**
@@ -41,20 +40,15 @@ struct Monostate {
      */
     template<typename Type>
     operator Type() const ENTT_NOEXCEPT {
-        return Monostate::value<Type>;
+        return value<Type>;
     }
 
 private:
     template<typename Type>
-    static std::atomic<Type> value;
+    inline static std::atomic<Type> value{};
 };
 
 
-template<HashedString::hash_type ID>
-template<typename Type>
-std::atomic<Type> Monostate<ID>::value{};
-
-
 }
 
 

+ 14 - 82
src/entt/entity/actor.hpp

@@ -21,9 +21,9 @@ namespace entt {
  * @tparam Entity A valid entity type (see entt_traits for more details).
  */
 template<typename Entity>
-struct Actor {
+struct actor {
     /*! @brief Type of registry used internally. */
-    using registry_type = Registry<Entity>;
+    using registry_type = registry<Entity>;
     /*! @brief Underlying entity identifier. */
     using entity_type = Entity;
 
@@ -31,17 +31,17 @@ struct Actor {
      * @brief Constructs an actor by using the given registry.
      * @param reg An entity-component system properly initialized.
      */
-    Actor(Registry<Entity> &reg)
+    actor(registry<Entity> &reg)
         : reg{&reg}, entt{reg.create()}
     {}
 
     /*! @brief Default destructor. */
-    virtual ~Actor() {
+    virtual ~actor() {
         reg->destroy(entt);
     }
 
     /*! @brief Copying an actor isn't allowed. */
-    Actor(const Actor &) = delete;
+    actor(const actor &) = delete;
 
     /**
      * @brief Move constructor.
@@ -52,14 +52,14 @@ struct Actor {
      *
      * @param other The instance to move from.
      */
-    Actor(Actor &&other)
+    actor(actor &&other)
         : reg{other.reg}, entt{other.entt}
     {
-        other.entt = entt::null;
+        other.entt = null;
     }
 
     /*! @brief Default copy assignment operator. @return This actor. */
-    Actor & operator=(const Actor &) = delete;
+    actor & operator=(const actor &) = delete;
 
     /**
      * @brief Move assignment operator.
@@ -71,7 +71,7 @@ struct Actor {
      * @param other The instance to move from.
      * @return This actor.
      */
-    Actor & operator=(Actor &&other) {
+    actor & operator=(actor &&other) {
         if(this != &other) {
             auto tmp{std::move(other)};
             std::swap(reg, tmp.reg);
@@ -81,24 +81,6 @@ struct Actor {
         return *this;
     }
 
-    /**
-     * @brief Assigns the given tag to an actor.
-     *
-     * A new instance of the given tag is created and initialized with the
-     * arguments provided (the tag must have a proper constructor or be of
-     * aggregate type). Then the tag is removed from its previous owner (if any)
-     * and assigned to the actor.
-     *
-     * @tparam Tag Type of the tag to create.
-     * @tparam Args Types of arguments to use to construct the tag.
-     * @param args Parameters to use to initialize the tag.
-     * @return A reference to the newly created tag.
-     */
-    template<typename Tag, typename... Args>
-    Tag & assign(tag_t, Args &&... args) {
-        return (reg->template remove<Tag>(), reg->template assign<Tag>(tag_t{}, entt, std::forward<Args>(args)...));
-    }
-
     /**
      * @brief Assigns the given component to an actor.
      *
@@ -118,16 +100,6 @@ struct Actor {
         return reg->template accommodate<Component>(entt, std::forward<Args>(args)...);
     }
 
-    /**
-     * @brief Removes the given tag from an actor.
-     * @tparam Tag Type of the tag to remove.
-     */
-    template<typename Tag>
-    void remove(tag_t) {
-        assert(has<Tag>(tag_t{}));
-        reg->template remove<Tag>();
-    }
-
     /**
      * @brief Removes the given component from an actor.
      * @tparam Component Type of the component to remove.
@@ -137,16 +109,6 @@ struct Actor {
         reg->template remove<Component>(entt);
     }
 
-    /**
-     * @brief Checks if an actor owns the given tag.
-     * @tparam Tag Type of the tag for which to perform the check.
-     * @return True if the actor owns the tag, false otherwise.
-     */
-    template<typename Tag>
-    bool has(tag_t) const ENTT_NOEXCEPT {
-        return (reg->template has<Tag>() && (reg->template attachee<Tag>() == entt));
-    }
-
     /**
      * @brief Checks if an actor has the given component.
      * @tparam Component Type of the component for which to perform the check.
@@ -157,27 +119,6 @@ struct Actor {
         return reg->template has<Component>(entt);
     }
 
-    /**
-     * @brief Returns a reference to the given tag for an actor.
-     * @tparam Tag Type of the tag to get.
-     * @return A reference to the instance of the tag owned by the actor.
-     */
-    template<typename Tag>
-    const Tag & get(tag_t) const ENTT_NOEXCEPT {
-        assert(has<Tag>(tag_t{}));
-        return reg->template get<Tag>();
-    }
-
-    /**
-     * @brief Returns a reference to the given tag for an actor.
-     * @tparam Tag Type of the tag to get.
-     * @return A reference to the instance of the tag owned by the actor.
-     */
-    template<typename Tag>
-    inline Tag & get(tag_t) ENTT_NOEXCEPT {
-        return const_cast<Tag &>(const_cast<const Actor *>(this)->get<Tag>(tag_t{}));
-    }
-
     /**
      * @brief Returns a reference to the given component for an actor.
      * @tparam Component Type of the component to get.
@@ -195,14 +136,14 @@ struct Actor {
      */
     template<typename Component>
     inline Component & get() ENTT_NOEXCEPT {
-        return const_cast<Component &>(const_cast<const Actor *>(this)->get<Component>());
+        return const_cast<Component &>(std::as_const(*this).template get<Component>());
     }
 
     /**
      * @brief Returns a reference to the underlying registry.
      * @return A reference to the underlying registry.
      */
-    inline const registry_type & registry() const ENTT_NOEXCEPT {
+    inline const registry_type & backend() const ENTT_NOEXCEPT {
         return *reg;
     }
 
@@ -210,8 +151,8 @@ struct Actor {
      * @brief Returns a reference to the underlying registry.
      * @return A reference to the underlying registry.
      */
-    inline registry_type & registry() ENTT_NOEXCEPT {
-        return const_cast<registry_type &>(const_cast<const Actor *>(this)->registry());
+    inline registry_type & backend() ENTT_NOEXCEPT {
+        return const_cast<registry_type &>(std::as_const(*this).backend());
     }
 
     /**
@@ -223,20 +164,11 @@ struct Actor {
     }
 
 private:
-    registry_type * reg;
+    registry_type *reg;
     Entity entt;
 };
 
 
-/**
- * @brief Default actor class.
- *
- * The default actor is the best choice for almost all the applications.<br/>
- * Users should have a really good reason to choose something different.
- */
-using DefaultActor = Actor<DefaultRegistry::entity_type>;
-
-
 }
 
 

+ 0 - 230
src/entt/entity/attachee.hpp

@@ -1,230 +0,0 @@
-#ifndef ENTT_ENTITY_ATTACHEE_HPP
-#define ENTT_ENTITY_ATTACHEE_HPP
-
-
-#include <cassert>
-#include <utility>
-#include <type_traits>
-#include "../config/config.h"
-#include "entity.hpp"
-
-
-namespace entt {
-
-
-/**
- * @brief Attachee.
- *
- * Primary template isn't defined on purpose. All the specializations give a
- * compile-time error, but for a few reasonable cases.
- */
-template<typename...>
-class Attachee;
-
-
-/**
- * @brief Basic attachee implementation.
- *
- * Convenience data structure used to store single instance components.
- *
- * @tparam Entity A valid entity type (see entt_traits for more details).
- */
-template<typename Entity>
-class Attachee<Entity> {
-public:
-    /*! @brief Underlying entity identifier. */
-    using entity_type = Entity;
-
-    /*! @brief Default constructor. */
-    Attachee() ENTT_NOEXCEPT
-        : owner{null}
-    {}
-
-    /*! @brief Default copy constructor. */
-    Attachee(const Attachee &) = default;
-    /*! @brief Default move constructor. */
-    Attachee(Attachee &&) = default;
-
-    /*! @brief Default copy assignment operator. @return This attachee. */
-    Attachee & operator=(const Attachee &) = default;
-    /*! @brief Default move assignment operator. @return This attachee. */
-    Attachee & operator=(Attachee &&) = default;
-
-    /*! @brief Default destructor. */
-    virtual ~Attachee() ENTT_NOEXCEPT = default;
-
-    /**
-     * @brief Returns the owner of an attachee.
-     * @return A valid entity identifier if an owner exists, the null entity
-     * identifier otherwise.
-     */
-    inline entity_type get() const ENTT_NOEXCEPT {
-        return owner;
-    }
-
-    /**
-     * @brief Assigns an entity to an attachee.
-     *
-     * @warning
-     * Attempting to assigns an entity to an attachee that already has an owner
-     * results in undefined behavior.<br/>
-     * An assertion will abort the execution at runtime in debug mode in case
-     * the attachee already has an owner.
-     *
-     * @param entity A valid entity identifier.
-     */
-    inline void construct(const entity_type entity) ENTT_NOEXCEPT {
-        assert(owner == null);
-        owner = entity;
-    }
-
-    /**
-     * @brief Removes an entity from an attachee.
-     *
-     * @warning
-     * Attempting to free an empty attachee results in undefined behavior.<br/>
-     * An assertion will abort the execution at runtime in debug mode if the
-     * attachee is already empty.
-     */
-    virtual void destroy() ENTT_NOEXCEPT {
-        assert(owner != null);
-        owner = null;
-    }
-
-private:
-    entity_type owner;
-};
-
-
-/**
- * @brief Extended attachee implementation.
- *
- * This specialization of an attachee associates an object to an entity. The
- * main purpose of this class is to use attachees to store tags in a Registry.
- * It guarantees fast access both to the element and to the entity.
- *
- * @sa Attachee<Entity>
- *
- * @tparam Entity A valid entity type (see entt_traits for more details).
- * @tparam Type Type of object assigned to the entity.
- */
-template<typename Entity, typename Type>
-class Attachee<Entity, Type>: public Attachee<Entity> {
-    using underlying_type = Attachee<Entity>;
-
-public:
-    /*! @brief Type of the object associated to the attachee. */
-    using object_type = Type;
-    /*! @brief Underlying entity identifier. */
-    using entity_type = typename underlying_type::entity_type;
-
-    /*! @brief Default constructor. */
-    Attachee() ENTT_NOEXCEPT = default;
-
-    /*! @brief Copying an attachee isn't allowed. */
-    Attachee(const Attachee &) = delete;
-    /*! @brief Moving an attachee isn't allowed. */
-    Attachee(Attachee &&) = delete;
-
-    /*! @brief Copying an attachee isn't allowed. @return This attachee. */
-    Attachee & operator=(const Attachee &) = delete;
-    /*! @brief Moving an attachee isn't allowed. @return This attachee. */
-    Attachee & operator=(Attachee &&) = delete;
-
-    /*! @brief Default destructor. */
-    ~Attachee() {
-        if(underlying_type::get() != null) {
-            reinterpret_cast<Type *>(&storage)->~Type();
-        }
-    }
-
-    /**
-     * @brief Returns the object associated to an attachee.
-     *
-     * @warning
-     * Attempting to query an empty attachee results in undefined behavior.<br/>
-     * An assertion will abort the execution at runtime in debug mode if the
-     * attachee is empty.
-     *
-     * @return The object associated to the attachee.
-     */
-    const Type & get() const ENTT_NOEXCEPT {
-        assert(underlying_type::get() != null);
-        return *reinterpret_cast<const Type *>(&storage);
-    }
-
-    /**
-     * @brief Returns the object associated to an attachee.
-     *
-     * @warning
-     * Attempting to query an empty attachee results in undefined behavior.<br/>
-     * An assertion will abort the execution at runtime in debug mode if the
-     * attachee is empty.
-     *
-     * @return The object associated to the attachee.
-     */
-    Type & get() ENTT_NOEXCEPT {
-        return const_cast<Type &>(const_cast<const Attachee *>(this)->get());
-    }
-
-    /**
-     * @brief Assigns an entity to an attachee and constructs its object.
-     *
-     * @warning
-     * Attempting to assigns an entity to an attachee that already has an owner
-     * results in undefined behavior.<br/>
-     * An assertion will abort the execution at runtime in debug mode in case
-     * the attachee already has an owner.
-     *
-     * @tparam Args Types of arguments to use to construct the object.
-     * @param entity A valid entity identifier.
-     * @param args Parameters to use to construct an object for the entity.
-     * @return The object associated to the attachee.
-     */
-    template<typename... Args>
-    Type & construct(entity_type entity, Args &&... args) ENTT_NOEXCEPT {
-        underlying_type::construct(entity);
-        new (&storage) Type{std::forward<Args>(args)...};
-        return *reinterpret_cast<Type *>(&storage);
-    }
-
-    /**
-     * @brief Removes an entity from an attachee and destroies its object.
-     *
-     * @warning
-     * Attempting to free an empty attachee results in undefined behavior.<br/>
-     * An assertion will abort the execution at runtime in debug mode if the
-     * attachee is already empty.
-     */
-    void destroy() ENTT_NOEXCEPT override {
-        reinterpret_cast<Type *>(&storage)->~Type();
-        underlying_type::destroy();
-    }
-
-    /**
-     * @brief Changes the owner of an attachee.
-     *
-     * The ownership of the attachee is transferred from one entity to another.
-     *
-     * @warning
-     * Attempting to transfer the ownership of an attachee that hasn't an owner
-     * results in undefined behavior.<br/>
-     * An assertion will abort the execution at runtime in debug mode in case
-     * the attachee hasn't an owner yet.
-     *
-     * @param entity A valid entity identifier.
-     */
-    void move(const entity_type entity) ENTT_NOEXCEPT {
-        underlying_type::destroy();
-        underlying_type::construct(entity);
-    }
-
-private:
-    std::aligned_storage_t<sizeof(Type), alignof(Type)> storage;
-};
-
-
-}
-
-
-#endif // ENTT_ENTITY_ATTACHEE_HPP

+ 10 - 10
src/entt/entity/entity.hpp

@@ -18,20 +18,20 @@ namespace entt {
 namespace internal {
 
 
-struct Null {
-    explicit constexpr Null() = default;
+struct null {
+    explicit constexpr null() = default;
 
     template<typename Entity>
     constexpr operator Entity() const ENTT_NOEXCEPT {
-        using traits_type = entt::entt_traits<Entity>;
+        using traits_type = entt_traits<Entity>;
         return traits_type::entity_mask | (traits_type::version_mask << traits_type::entity_shift);
     }
 
-    constexpr bool operator==(Null) const ENTT_NOEXCEPT {
+    constexpr bool operator==(null) const ENTT_NOEXCEPT {
         return true;
     }
 
-    constexpr bool operator!=(Null) const ENTT_NOEXCEPT {
+    constexpr bool operator!=(null) const ENTT_NOEXCEPT {
         return false;
     }
 
@@ -48,14 +48,14 @@ struct Null {
 
 
 template<typename Entity>
-constexpr bool operator==(const Entity entity, Null null) ENTT_NOEXCEPT {
-    return null == entity;
+constexpr bool operator==(const Entity entity, null other) ENTT_NOEXCEPT {
+    return other == entity;
 }
 
 
 template<typename Entity>
-constexpr bool operator!=(const Entity entity, Null null) ENTT_NOEXCEPT {
-    return null != entity;
+constexpr bool operator!=(const Entity entity, null other) ENTT_NOEXCEPT {
+    return other != entity;
 }
 
 
@@ -75,7 +75,7 @@ constexpr bool operator!=(const Entity entity, Null null) ENTT_NOEXCEPT {
  * any allowed type. Similarly, there exist comparision operators between the
  * null entity and any other entity identifier.
  */
-constexpr auto null = internal::Null{};
+constexpr auto null = internal::null{};
 
 
 }

+ 15 - 18
src/entt/entity/helper.hpp

@@ -6,7 +6,6 @@
 #include "../core/hashed_string.hpp"
 #include "../signal/sigh.hpp"
 #include "registry.hpp"
-#include "utility.hpp"
 
 
 namespace entt {
@@ -27,10 +26,8 @@ namespace entt {
  * @param entity A valid entity identifier.
  */
 template<typename Entity, typename... Component>
-void dependency(Registry<Entity> &registry, const Entity entity) {
-    using accumulator_type = int[];
-    accumulator_type accumulator = { ((registry.template has<Component>(entity) ? void() : (registry.template assign<Component>(entity), void())), 0)... };
-    (void)accumulator;
+void dependency(registry<Entity> &registry, const Entity entity) {
+    ((registry.template has<Component>(entity) ? void() : (registry.template assign<Component>(entity), void())), ...);
 }
 
 
@@ -40,11 +37,11 @@ void dependency(Registry<Entity> &registry, const Entity entity) {
  * A _dependency function_ is a built-in listener to use to automatically assign
  * components to an entity when a type has a dependency on some other types.
  *
- * The following adds components `AType` and `AnotherType` whenever `MyType` is
- * assigned to an entity:
+ * The following adds components `a_type` and `another_type` whenever `my_type`
+ * is assigned to an entity:
  * @code{.cpp}
- * entt::DefaultRegistry registry;
- * entt::connect<AType, AnotherType>(registry.construction<MyType>());
+ * entt::registry registry;
+ * entt::connect<a_type, another_type>(registry.construction<my_type>());
  * @endcode
  *
  * @tparam Dependency Types of components to assign to an entity if triggered.
@@ -52,7 +49,7 @@ void dependency(Registry<Entity> &registry, const Entity entity) {
  * @param sink A sink object properly initialized.
  */
 template<typename... Dependency, typename Entity>
-inline void connect(Sink<void(Registry<Entity> &, const Entity)> sink) {
+inline void connect(sink<void(registry<Entity> &, const Entity)> sink) {
     sink.template connect<dependency<Entity, Dependency...>>();
 }
 
@@ -63,11 +60,11 @@ inline void connect(Sink<void(Registry<Entity> &, const Entity)> sink) {
  * A _dependency function_ is a built-in listener to use to automatically assign
  * components to an entity when a type has a dependency on some other types.
  *
- * The following breaks the dependency between the component `MyType` and the
- * components `AType` and `AnotherType`:
+ * The following breaks the dependency between the component `my_type` and the
+ * components `a_type` and `another_type`:
  * @code{.cpp}
- * entt::DefaultRegistry registry;
- * entt::disconnect<AType, AnotherType>(registry.construction<MyType>());
+ * entt::registry registry;
+ * entt::disconnect<a_type, another_type>(registry.construction<my_type>());
  * @endcode
  *
  * @tparam Dependency Types of components used to create the dependency.
@@ -75,7 +72,7 @@ inline void connect(Sink<void(Registry<Entity> &, const Entity)> sink) {
  * @param sink A sink object properly initialized.
  */
 template<typename... Dependency, typename Entity>
-inline void disconnect(Sink<void(Registry<Entity> &, const Entity)> sink) {
+inline void disconnect(sink<void(registry<Entity> &, const Entity)> sink) {
     sink.template disconnect<dependency<Entity, Dependency...>>();
 }
 
@@ -89,14 +86,14 @@ inline void disconnect(Sink<void(Registry<Entity> &, const Entity)> sink) {
  * As an example and where the user defined literal for hashed strings hasn't
  * been changed:
  * @code{.cpp}
- * entt::DefaultRegistry registry;
+ * entt::registry registry;
  * registry.assign<entt::label<"enemy"_hs>>(entity);
  * @endcode
  *
  * @tparam Value The numeric representation of an instance of hashed string.
  */
-template<typename HashedString::hash_type Value>
-using label = std::integral_constant<typename HashedString::hash_type, Value>;
+template<typename hashed_string::hash_type Value>
+using label = std::integral_constant<typename hashed_string::hash_type, Value>;
 
 
 }

+ 61 - 94
src/entt/entity/prototype.hpp

@@ -37,27 +37,32 @@ namespace entt {
  * @tparam Entity A valid entity type (see entt_traits for more details).
  */
 template<typename Entity>
-class Prototype final {
-    using basic_fn_type = void(const Prototype &, Registry<Entity> &, const Entity);
-    using component_type = typename Registry<Entity>::component_type;
+class prototype final {
+    using basic_fn_type = void(const prototype &, registry<Entity> &, const Entity);
+    using component_type = typename registry<Entity>::component_type;
 
     template<typename Component>
-    struct Wrapper { Component component; };
+    struct component_wrapper { Component component; };
 
-    struct Handler {
+    struct component_handler {
         basic_fn_type *accommodate;
         basic_fn_type *assign;
     };
 
+    template<typename Component>
+    inline const Component & component() const ENTT_NOEXCEPT {
+        return reg->template get<component_wrapper<Component>>(entity).component;
+    }
+
     void release() {
-        if(registry->valid(entity)) {
-            registry->destroy(entity);
+        if(reg->valid(entity)) {
+            reg->destroy(entity);
         }
     }
 
 public:
     /*! @brief Registry type. */
-    using registry_type = Registry<Entity>;
+    using registry_type = registry<Entity>;
     /*! @brief Underlying entity identifier. */
     using entity_type = Entity;
     /*! @brief Unsigned integer type. */
@@ -65,22 +70,22 @@ public:
 
     /**
      * @brief Constructs a prototype that is bound to a given registry.
-     * @param registry A valid reference to a registry.
+     * @param reg A valid reference to a registry.
      */
-    Prototype(Registry<Entity> &registry)
-        : registry{&registry},
-          entity{registry.create()}
+    prototype(registry<Entity> &reg)
+        : reg{&reg},
+          entity{reg.create()}
     {}
 
     /**
      * @brief Releases all its resources.
      */
-    ~Prototype() {
+    ~prototype() {
         release();
     }
 
     /*! @brief Copying a prototype isn't allowed. */
-    Prototype(const Prototype &) = delete;
+    prototype(const prototype &) = delete;
 
     /**
      * @brief Move constructor.
@@ -91,16 +96,16 @@ public:
      *
      * @param other The instance to move from.
      */
-    Prototype(Prototype &&other)
+    prototype(prototype &&other)
         : handlers{std::move(other.handlers)},
-          registry{other.registry},
+          reg{other.reg},
           entity{other.entity}
     {
-        other.entity = entt::null;
+        other.entity = null;
     }
 
-    /*! @brief Copying a prototype isn't allowed. @return This Prototype. */
-    Prototype & operator=(const Prototype &) = delete;
+    /*! @brief Copying a prototype isn't allowed. @return This prototype. */
+    prototype & operator=(const prototype &) = delete;
 
     /**
      * @brief Move assignment operator.
@@ -110,13 +115,13 @@ public:
      * continue using them.
      *
      * @param other The instance to move from.
-     * @return This Prototype.
+     * @return This prototype.
      */
-    Prototype & operator=(Prototype &&other) {
+    prototype & operator=(prototype &&other) {
         if(this != &other) {
             auto tmp{std::move(other)};
             handlers.swap(tmp.handlers);
-            std::swap(registry, tmp.registry);
+            std::swap(reg, tmp.reg);
             std::swap(entity, tmp.entity);
         }
 
@@ -132,20 +137,20 @@ public:
      */
     template<typename Component, typename... Args>
     Component & set(Args &&... args) {
-        basic_fn_type *accommodate = [](const Prototype &prototype, Registry<Entity> &other, const Entity dst) {
-            const auto &wrapper = prototype.registry->template get<Wrapper<Component>>(prototype.entity);
+        basic_fn_type *accommodate = [](const prototype &prototype, registry<Entity> &other, const Entity dst) {
+            const auto &wrapper = prototype.reg->template get<component_wrapper<Component>>(prototype.entity);
             other.template accommodate<Component>(dst, wrapper.component);
         };
 
-        basic_fn_type *assign = [](const Prototype &prototype, Registry<Entity> &other, const Entity dst) {
+        basic_fn_type *assign = [](const prototype &prototype, registry<Entity> &other, const Entity dst) {
             if(!other.template has<Component>(dst)) {
-                const auto &wrapper = prototype.registry->template get<Wrapper<Component>>(prototype.entity);
+                const auto &wrapper = prototype.reg->template get<component_wrapper<Component>>(prototype.entity);
                 other.template assign<Component>(dst, wrapper.component);
             }
         };
 
-        handlers[registry->template type<Component>()] = Handler{accommodate, assign};
-        auto &wrapper = registry->template accommodate<Wrapper<Component>>(entity, Component{std::forward<Args>(args)...});
+        handlers[reg->template type<Component>()] = component_handler{accommodate, assign};
+        auto &wrapper = reg->template accommodate<component_wrapper<Component>>(entity, Component{std::forward<Args>(args)...});
         return wrapper.component;
     }
 
@@ -155,8 +160,8 @@ public:
      */
     template<typename Component>
     void unset() ENTT_NOEXCEPT {
-        registry->template reset<Wrapper<Component>>(entity);
-        handlers.erase(registry->template type<Component>());
+        reg->template reset<component_wrapper<Component>>(entity);
+        handlers.erase(reg->template type<Component>());
     }
 
     /**
@@ -166,11 +171,11 @@ public:
      */
     template<typename... Component>
     bool has() const ENTT_NOEXCEPT {
-        return registry->template has<Wrapper<Component>...>(entity);
+        return reg->template has<component_wrapper<Component>...>(entity);
     }
 
     /**
-     * @brief Returns a reference to the given component.
+     * @brief Returns references to the given components.
      *
      * @warning
      * Attempting to get a component from a prototype that doesn't own it
@@ -178,65 +183,37 @@ public:
      * An assertion will abort the execution at runtime in debug mode if the
      * prototype doesn't own an instance of the given component.
      *
-     * @tparam Component Type of component to get.
-     * @return A reference to the component owned by the prototype.
-     */
-    template<typename Component>
-    const Component & get() const ENTT_NOEXCEPT {
-        return registry->template get<Wrapper<Component>>(entity).component;
-    }
-
-    /**
-     * @brief Returns a reference to the given component.
-     *
-     * @warning
-     * Attempting to get a component from a prototype that doesn't own it
-     * results in undefined behavior.<br/>
-     * An assertion will abort the execution at runtime in debug mode if the
-     * prototype doesn't own an instance of the given component.
-     *
-     * @tparam Component Type of component to get.
-     * @return A reference to the component owned by the prototype.
-     */
-    template<typename Component>
-    inline Component & get() ENTT_NOEXCEPT {
-        return const_cast<Component &>(const_cast<const Prototype *>(this)->get<Component>());
-    }
-
-    /**
-     * @brief Returns a reference to the given components.
-     *
-     * @warning
-     * Attempting to get components from a prototype that doesn't own them
-     * results in undefined behavior.<br/>
-     * An assertion will abort the execution at runtime in debug mode if the
-     * prototype doesn't own instances of the given components.
-     *
-     * @tparam Component Type of components to get.
+     * @tparam Component Types of components to get.
      * @return References to the components owned by the prototype.
      */
     template<typename... Component>
-    inline std::enable_if_t<(sizeof...(Component) > 1), std::tuple<const Component &...>>
-    get() const ENTT_NOEXCEPT {
-        return std::tuple<const Component &...>{get<Component>()...};
+    decltype(auto) get() const ENTT_NOEXCEPT {
+        if constexpr(sizeof...(Component) == 1) {
+            return component<Component...>();
+        } else {
+            return std::tuple<const Component &...>{get<Component>()...};
+        }
     }
 
     /**
-     * @brief Returns a reference to the given components.
+     * @brief Returns references to the given components.
      *
      * @warning
-     * Attempting to get components from a prototype that doesn't own them
+     * Attempting to get a component from a prototype that doesn't own it
      * results in undefined behavior.<br/>
      * An assertion will abort the execution at runtime in debug mode if the
-     * prototype doesn't own instances of the given components.
+     * prototype doesn't own an instance of the given component.
      *
-     * @tparam Component Type of components to get.
+     * @tparam Component Types of components to get.
      * @return References to the components owned by the prototype.
      */
     template<typename... Component>
-    inline std::enable_if_t<(sizeof...(Component) > 1), std::tuple<Component &...>>
-    get() ENTT_NOEXCEPT {
-        return std::tuple<Component &...>{get<Component>()...};
+    inline decltype(auto) get() ENTT_NOEXCEPT {
+        if constexpr(sizeof...(Component) == 1) {
+            return (const_cast<Component &>(std::as_const(*this).template get<Component>()), ...);
+        } else {
+            return std::tuple<Component &...>{get<Component>()...};
+        }
     }
 
     /**
@@ -281,7 +258,7 @@ public:
      * @return A valid entity identifier.
      */
     inline entity_type create() const {
-        return create(*registry);
+        return create(*reg);
     }
 
     /**
@@ -332,7 +309,7 @@ public:
      * @param dst A valid entity identifier.
      */
     inline void assign(const entity_type dst) const {
-        assign(*registry, dst);
+        assign(*reg, dst);
     }
 
     /**
@@ -379,7 +356,7 @@ public:
      * @param dst A valid entity identifier.
      */
     inline void accommodate(const entity_type dst) const {
-        accommodate(*registry, dst);
+        accommodate(*reg, dst);
     }
 
     /**
@@ -428,7 +405,7 @@ public:
      * @param dst A valid entity identifier.
      */
     inline void operator()(const entity_type dst) const ENTT_NOEXCEPT {
-        assign(*registry, dst);
+        assign(*reg, dst);
     }
 
     /**
@@ -471,26 +448,16 @@ public:
      * @return A valid entity identifier.
      */
     inline entity_type operator()() const ENTT_NOEXCEPT {
-        return create(*registry);
+        return create(*reg);
     }
 
 private:
-    std::unordered_map<component_type, Handler> handlers;
-    Registry<Entity> *registry;
+    std::unordered_map<component_type, component_handler> handlers;
+    registry<Entity> *reg;
     entity_type entity;
 };
 
 
-/**
- * @brief Default prototype
- *
- * The default prototype is the best choice for almost all the
- * applications.<br/>
- * Users should have a really good reason to choose something different.
- */
-using DefaultPrototype = Prototype<DefaultRegistry::entity_type>;
-
-
 }
 
 

File diff suppressed because it is too large
+ 123 - 501
src/entt/entity/registry.hpp


+ 108 - 238
src/entt/entity/snapshot.hpp

@@ -11,7 +11,6 @@
 #include <unordered_map>
 #include "../config/config.h"
 #include "entt_traits.hpp"
-#include "utility.hpp"
 
 
 namespace entt {
@@ -21,28 +20,28 @@ namespace entt {
  * @brief Forward declaration of the registry class.
  */
 template<typename>
-class Registry;
+class registry;
 
 
 /**
  * @brief Utility class to create snapshots from a registry.
  *
  * A _snapshot_ can be either a dump of the entire registry or a narrower
- * selection of components and tags of interest.<br/>
+ * selection of components of interest.<br/>
  * This type can be used in both cases if provided with a correctly configured
  * output archive.
  *
  * @tparam Entity A valid entity type (see entt_traits for more details).
  */
 template<typename Entity>
-class Snapshot final {
+class snapshot final {
     /*! @brief A registry is allowed to create snapshots. */
-    friend class Registry<Entity>;
+    friend class registry<Entity>;
 
-    using follow_fn_type = Entity(const Registry<Entity> &, const Entity);
+    using follow_fn_type = Entity(const registry<Entity> &, const Entity);
 
-    Snapshot(const Registry<Entity> &registry, Entity seed, follow_fn_type *follow) ENTT_NOEXCEPT
-        : registry{registry},
+    snapshot(const registry<Entity> &reg, Entity seed, follow_fn_type *follow) ENTT_NOEXCEPT
+        : reg{reg},
           seed{seed},
           follow{follow}
     {}
@@ -54,8 +53,8 @@ class Snapshot final {
         while(first != last) {
             const auto entity = *(first++);
 
-            if(registry.template has<Component>(entity)) {
-                archive(entity, registry.template get<Component>(entity));
+            if(reg.template has<Component>(entity)) {
+                archive(entity, reg.template get<Component>(entity));
             }
         }
     }
@@ -67,26 +66,22 @@ class Snapshot final {
 
         while(begin != last) {
             const auto entity = *(begin++);
-            using accumulator_type = std::size_t[];
-            accumulator_type accumulator = { (registry.template has<Component>(entity) ? ++size[Indexes] : size[Indexes])... };
-            (void)accumulator;
+            ((reg.template has<Component>(entity) ? ++size[Indexes] : size[Indexes]), ...);
         }
 
-        using accumulator_type = int[];
-        accumulator_type accumulator = { (get<Component>(archive, size[Indexes], first, last), 0)... };
-        (void)accumulator;
+        (get<Component>(archive, size[Indexes], first, last), ...);
     }
 
 public:
     /*! @brief Copying a snapshot isn't allowed. */
-    Snapshot(const Snapshot &) = delete;
+    snapshot(const snapshot &) = delete;
     /*! @brief Default move constructor. */
-    Snapshot(Snapshot &&) = default;
+    snapshot(snapshot &&) = default;
 
     /*! @brief Copying a snapshot isn't allowed. @return This snapshot. */
-    Snapshot & operator=(const Snapshot &) = delete;
+    snapshot & operator=(const snapshot &) = delete;
     /*! @brief Default move assignment operator. @return This snapshot. */
-    Snapshot & operator=(Snapshot &&) = default;
+    snapshot & operator=(snapshot &&) = default;
 
     /**
      * @brief Puts aside all the entities that are still in use.
@@ -99,9 +94,9 @@ public:
      * @return An object of this type to continue creating the snapshot.
      */
     template<typename Archive>
-    const Snapshot & entities(Archive &archive) const {
-        archive(static_cast<Entity>(registry.alive()));
-        registry.each([&archive](const auto entity) { archive(entity); });
+    const snapshot & entities(Archive &archive) const {
+        archive(static_cast<Entity>(reg.alive()));
+        reg.each([&archive](const auto entity) { archive(entity); });
         return *this;
     }
 
@@ -116,8 +111,8 @@ public:
      * @return An object of this type to continue creating the snapshot.
      */
     template<typename Archive>
-    const Snapshot & destroyed(Archive &archive) const {
-        auto size = registry.size() - registry.alive();
+    const snapshot & destroyed(Archive &archive) const {
+        auto size = reg.size() - reg.alive();
         archive(static_cast<Entity>(size));
 
         if(size) {
@@ -125,7 +120,7 @@ public:
             archive(curr);
 
             for(--size; size; --size) {
-                curr = follow(registry, curr);
+                curr = follow(reg, curr);
                 archive(curr);
             }
         }
@@ -133,32 +128,6 @@ public:
         return *this;
     }
 
-    /**
-     * @brief Puts aside the given component.
-     *
-     * Each instance is serialized together with the entity to which it belongs.
-     * Entities are serialized along with their versions.
-     *
-     * @tparam Component Type of component to serialize.
-     * @tparam Archive Type of output archive.
-     * @param archive A valid reference to an output archive.
-     * @return An object of this type to continue creating the snapshot.
-     */
-    template<typename Component, typename Archive>
-    const Snapshot & component(Archive &archive) const {
-        const auto sz = registry.template size<Component>();
-        const auto *entities = registry.template data<Component>();
-
-        archive(static_cast<Entity>(sz));
-
-        for(std::remove_const_t<decltype(sz)> i{}; i < sz; ++i) {
-            const auto entity = entities[i];
-            archive(entity, registry.template get<Component>(entity));
-        };
-
-        return *this;
-    }
-
     /**
      * @brief Puts aside the given components.
      *
@@ -171,11 +140,21 @@ public:
      * @return An object of this type to continue creating the snapshot.
      */
     template<typename... Component, typename Archive>
-    std::enable_if_t<(sizeof...(Component) > 1), const Snapshot &>
-    component(Archive &archive) const {
-        using accumulator_type = int[];
-        accumulator_type accumulator = { 0, (component<Component>(archive), 0)... };
-        (void)accumulator;
+    const snapshot & component(Archive &archive) const {
+        if constexpr(sizeof...(Component) == 1) {
+            const auto sz = reg.template size<Component...>();
+            const auto *entities = reg.template data<Component...>();
+
+            archive(static_cast<Entity>(sz));
+
+            for(std::remove_const_t<decltype(sz)> i{}; i < sz; ++i) {
+                const auto entity = entities[i];
+                archive(entity, reg.template get<Component...>(entity));
+            };
+        } else {
+            (component<Component>(archive), ...);
+        }
+
         return *this;
     }
 
@@ -194,58 +173,13 @@ public:
      * @return An object of this type to continue creating the snapshot.
      */
     template<typename... Component, typename Archive, typename It>
-    const Snapshot & component(Archive &archive, It first, It last) const {
+    const snapshot & component(Archive &archive, It first, It last) const {
         component<Component...>(archive, first, last, std::make_index_sequence<sizeof...(Component)>{});
         return *this;
     }
 
-    /**
-     * @brief Puts aside the given tag.
-     *
-     * Each instance is serialized together with the entity to which it belongs.
-     * Entities are serialized along with their versions.
-     *
-     * @tparam Tag Type of tag to serialize.
-     * @tparam Archive Type of output archive.
-     * @param archive A valid reference to an output archive.
-     * @return An object of this type to continue creating the snapshot.
-     */
-    template<typename Tag, typename Archive>
-    const Snapshot & tag(Archive &archive) const {
-        const bool has = registry.template has<Tag>();
-
-        // numerical length is forced for tags to facilitate loading
-        archive(has ? Entity(1): Entity{});
-
-        if(has) {
-            archive(registry.template attachee<Tag>(), registry.template get<Tag>());
-        }
-
-        return *this;
-    }
-
-    /**
-     * @brief Puts aside the given tags.
-     *
-     * Each instance is serialized together with the entity to which it belongs.
-     * Entities are serialized along with their versions.
-     *
-     * @tparam Tag Types of tags to serialize.
-     * @tparam Archive Type of output archive.
-     * @param archive A valid reference to an output archive.
-     * @return An object of this type to continue creating the snapshot.
-     */
-    template<typename... Tag, typename Archive>
-    std::enable_if_t<(sizeof...(Tag) > 1), const Snapshot &>
-    tag(Archive &archive) const {
-        using accumulator_type = int[];
-        accumulator_type accumulator = { 0, (tag<Tag>(archive), 0)... };
-        (void)accumulator;
-        return *this;
-    }
-
 private:
-    const Registry<Entity> &registry;
+    const registry<Entity> &reg;
     const Entity seed;
     follow_fn_type *follow;
 };
@@ -262,18 +196,18 @@ private:
  * @tparam Entity A valid entity type (see entt_traits for more details).
  */
 template<typename Entity>
-class SnapshotLoader final {
+class snapshot_loader final {
     /*! @brief A registry is allowed to create snapshot loaders. */
-    friend class Registry<Entity>;
+    friend class registry<Entity>;
 
-    using assure_fn_type = void(Registry<Entity> &, const Entity, const bool);
+    using assure_fn_type = void(registry<Entity> &, const Entity, const bool);
 
-    SnapshotLoader(Registry<Entity> &registry, assure_fn_type *assure_fn) ENTT_NOEXCEPT
-        : registry{registry},
+    snapshot_loader(registry<Entity> &reg, assure_fn_type *assure_fn) ENTT_NOEXCEPT
+        : reg{reg},
           assure_fn{assure_fn}
     {
         // restore a snapshot as a whole requires a clean registry
-        assert(!registry.capacity());
+        assert(!reg.capacity());
     }
 
     template<typename Archive>
@@ -284,7 +218,7 @@ class SnapshotLoader final {
         while(length--) {
             Entity entity{};
             archive(entity);
-            assure_fn(registry, entity, destroyed);
+            assure_fn(reg, entity, destroyed);
         }
     }
 
@@ -298,21 +232,21 @@ class SnapshotLoader final {
             Type instance{};
             archive(entity, instance);
             static constexpr auto destroyed = false;
-            assure_fn(registry, entity, destroyed);
-            registry.template assign<Type>(args..., entity, static_cast<const Type &>(instance));
+            assure_fn(reg, entity, destroyed);
+            reg.template assign<Type>(args..., entity, std::as_const(instance));
         }
     }
 
 public:
     /*! @brief Copying a snapshot loader isn't allowed. */
-    SnapshotLoader(const SnapshotLoader &) = delete;
+    snapshot_loader(const snapshot_loader &) = delete;
     /*! @brief Default move constructor. */
-    SnapshotLoader(SnapshotLoader &&) = default;
+    snapshot_loader(snapshot_loader &&) = default;
 
     /*! @brief Copying a snapshot loader isn't allowed. @return This loader. */
-    SnapshotLoader & operator=(const SnapshotLoader &) = delete;
+    snapshot_loader & operator=(const snapshot_loader &) = delete;
     /*! @brief Default move assignment operator. @return This loader. */
-    SnapshotLoader & operator=(SnapshotLoader &&) = default;
+    snapshot_loader & operator=(snapshot_loader &&) = default;
 
     /**
      * @brief Restores entities that were in use during serialization.
@@ -325,7 +259,7 @@ public:
      * @return A valid loader to continue restoring data.
      */
     template<typename Archive>
-    const SnapshotLoader & entities(Archive &archive) const {
+    const snapshot_loader & entities(Archive &archive) const {
         static constexpr auto destroyed = false;
         assure(archive, destroyed);
         return *this;
@@ -342,7 +276,7 @@ public:
      * @return A valid loader to continue restoring data.
      */
     template<typename Archive>
-    const SnapshotLoader & destroyed(Archive &archive) const {
+    const snapshot_loader & destroyed(Archive &archive) const {
         static constexpr auto destroyed = true;
         assure(archive, destroyed);
         return *this;
@@ -362,54 +296,31 @@ public:
      * @return A valid loader to continue restoring data.
      */
     template<typename... Component, typename Archive>
-    const SnapshotLoader & component(Archive &archive) const {
-        using accumulator_type = int[];
-        accumulator_type accumulator = { 0, (assign<Component>(archive), 0)... };
-        (void)accumulator;
+    const snapshot_loader & component(Archive &archive) const {
+        (assign<Component>(archive), ...);
         return *this;
     }
 
     /**
-     * @brief Restores tags and assigns them to the right entities.
-     *
-     * The template parameter list must be exactly the same used during
-     * serialization. In the event that the entity to which the tag is assigned
-     * doesn't exist yet, the loader will take care to create it with the
-     * version it originally had.
-     *
-     * @tparam Tag Types of tags to restore.
-     * @tparam Archive Type of input archive.
-     * @param archive A valid reference to an input archive.
-     * @return A valid loader to continue restoring data.
-     */
-    template<typename... Tag, typename Archive>
-    const SnapshotLoader & tag(Archive &archive) const {
-        using accumulator_type = int[];
-        accumulator_type accumulator = { 0, (assign<Tag>(archive, tag_t{}), 0)... };
-        (void)accumulator;
-        return *this;
-    }
-
-    /**
-     * @brief Destroys those entities that have neither components nor tags.
+     * @brief Destroys those entities that have no components.
      *
      * In case all the entities were serialized but only part of the components
-     * and tags was saved, it could happen that some of the entities have
-     * neither components nor tags once restored.<br/>
+     * was saved, it could happen that some of the entities have no components
+     * once restored.<br/>
      * This functions helps to identify and destroy those entities.
      *
      * @return A valid loader to continue restoring data.
      */
-    const SnapshotLoader & orphans() const {
-        registry.orphans([this](const auto entity) {
-            registry.destroy(entity);
+    const snapshot_loader & orphans() const {
+        reg.orphans([this](const auto entity) {
+            reg.destroy(entity);
         });
 
         return *this;
     }
 
 private:
-    Registry<Entity> &registry;
+    registry<Entity> &reg;
     assure_fn_type *assure_fn;
 };
 
@@ -431,16 +342,16 @@ private:
  * @tparam Entity A valid entity type (see entt_traits for more details).
  */
 template<typename Entity>
-class ContinuousLoader final {
+class continuous_loader final {
     using traits_type = entt_traits<Entity>;
 
     void destroy(Entity entity) {
         const auto it = remloc.find(entity);
 
         if(it == remloc.cend()) {
-            const auto local = registry.create();
+            const auto local = reg.create();
             remloc.emplace(entity, std::make_pair(local, true));
-            registry.destroy(local);
+            reg.destroy(local);
         }
     }
 
@@ -448,39 +359,35 @@ class ContinuousLoader final {
         const auto it = remloc.find(entity);
 
         if(it == remloc.cend()) {
-            const auto local = registry.create();
+            const auto local = reg.create();
             remloc.emplace(entity, std::make_pair(local, true));
         } else {
             remloc[entity].first =
-                    registry.valid(remloc[entity].first)
+                    reg.valid(remloc[entity].first)
                     ? remloc[entity].first
-                    : registry.create();
+                    : reg.create();
 
             // set the dirty flag
             remloc[entity].second = true;
         }
     }
 
-    template<typename Type, typename Member>
-    std::enable_if_t<std::is_same<Member, Entity>::value>
-    update(Type &instance, Member Type:: *member) {
-        instance.*member = map(instance.*member);
-    }
-
-    template<typename Type, typename Member>
-    std::enable_if_t<std::is_same<typename std::iterator_traits<typename Member::iterator>::value_type, Entity>::value>
-    update(Type &instance, Member Type:: *member) {
-        for(auto &entity: instance.*member) {
-            entity = map(entity);
+    template<typename Other, typename Type, typename Member>
+    void update(Other &instance, Member Type:: *member) {
+        if constexpr(!std::is_same_v<Other, Type>) {
+            return;
+        } else if constexpr(std::is_same_v<Member, Entity>) {
+            instance.*member = map(instance.*member);
+        } else {
+            // maybe a container? let's try...
+            for(auto &entity: instance.*member) {
+                entity = map(entity);
+            }
         }
     }
 
-    template<typename Other, typename Type, typename Member>
-    std::enable_if_t<!std::is_same<Other, Type>::value>
-    update(Other &, Member Type:: *) {}
-
     template<typename Archive>
-    void assure(Archive &archive, void(ContinuousLoader:: *member)(Entity)) {
+    void assure(Archive &archive, void(continuous_loader:: *member)(Entity)) {
         Entity length{};
         archive(length);
 
@@ -496,8 +403,8 @@ class ContinuousLoader final {
         for(auto &&ref: remloc) {
             const auto local = ref.second.first;
 
-            if(registry.valid(local)) {
-                registry.template reset<Component>(local);
+            if(reg.valid(local)) {
+                reg.template reset<Component>(local);
             }
         }
     }
@@ -510,14 +417,9 @@ class ContinuousLoader final {
         while(length--) {
             Entity entity{};
             Other instance{};
-
             archive(entity, instance);
             restore(entity);
-
-            using accumulator_type = int[];
-            accumulator_type accumulator = { 0, (update(instance, member), 0)... };
-            (void)accumulator;
-
+            (update(instance, member), ...);
             func(map(entity), instance);
         }
     }
@@ -528,21 +430,21 @@ public:
 
     /**
      * @brief Constructs a loader that is bound to a given registry.
-     * @param registry A valid reference to a registry.
+     * @param reg A valid reference to a registry.
      */
-    ContinuousLoader(Registry<entity_type> &registry) ENTT_NOEXCEPT
-        : registry{registry}
+    continuous_loader(registry<entity_type> &reg) ENTT_NOEXCEPT
+        : reg{reg}
     {}
 
     /*! @brief Copying a snapshot loader isn't allowed. */
-    ContinuousLoader(const ContinuousLoader &) = delete;
+    continuous_loader(const continuous_loader &) = delete;
     /*! @brief Default move constructor. */
-    ContinuousLoader(ContinuousLoader &&) = default;
+    continuous_loader(continuous_loader &&) = default;
 
     /*! @brief Copying a snapshot loader isn't allowed. @return This loader. */
-    ContinuousLoader & operator=(const ContinuousLoader &) = delete;
+    continuous_loader & operator=(const continuous_loader &) = delete;
     /*! @brief Default move assignment operator. @return This loader. */
-    ContinuousLoader & operator=(ContinuousLoader &&) = default;
+    continuous_loader & operator=(continuous_loader &&) = default;
 
     /**
      * @brief Restores entities that were in use during serialization.
@@ -555,8 +457,8 @@ public:
      * @return A non-const reference to this loader.
      */
     template<typename Archive>
-    ContinuousLoader & entities(Archive &archive) {
-        assure(archive, &ContinuousLoader::restore);
+    continuous_loader & entities(Archive &archive) {
+        assure(archive, &continuous_loader::restore);
         return *this;
     }
 
@@ -571,8 +473,8 @@ public:
      * @return A non-const reference to this loader.
      */
     template<typename Archive>
-    ContinuousLoader & destroyed(Archive &archive) {
-        assure(archive, &ContinuousLoader::destroy);
+    continuous_loader & destroyed(Archive &archive) {
+        assure(archive, &continuous_loader::destroy);
         return *this;
     }
 
@@ -596,45 +498,13 @@ public:
      * @return A non-const reference to this loader.
      */
     template<typename... Component, typename Archive, typename... Type, typename... Member>
-    ContinuousLoader & component(Archive &archive, Member Type:: *... member) {
+    continuous_loader & component(Archive &archive, Member Type:: *... member) {
         auto apply = [this](const auto entity, const auto &component) {
-            registry.template accommodate<std::decay_t<decltype(component)>>(entity, component);
-        };
-
-        using accumulator_type = int[];
-        accumulator_type accumulator = { 0, (reset<Component>(), assign<Component>(archive, apply, member...), 0)... };
-        (void)accumulator;
-        return *this;
-    }
-
-    /**
-     * @brief Restores tags and assigns them to the right entities.
-     *
-     * The template parameter list must be exactly the same used during
-     * serialization. In the event that the entity to which the tag is assigned
-     * doesn't exist yet, the loader will take care to create a local
-     * counterpart for it.<br/>
-     * Members can be either data members of type entity_type or containers of
-     * entities. In both cases, the loader will visit them and update the
-     * entities by replacing each one with its local counterpart.
-     *
-     * @tparam Tag Type of tag to restore.
-     * @tparam Archive Type of input archive.
-     * @tparam Type Types of components to update with local counterparts.
-     * @tparam Member Types of members to update with their local counterparts.
-     * @param archive A valid reference to an input archive.
-     * @param member Members to update with their local counterparts.
-     * @return A non-const reference to this loader.
-     */
-    template<typename... Tag, typename Archive, typename... Type, typename... Member>
-    ContinuousLoader & tag(Archive &archive, Member Type:: *... member) {
-        auto apply = [this](const auto entity, const auto &tag) {
-            registry.template assign<std::decay_t<decltype(tag)>>(tag_t{}, entity, tag);
+            reg.template accommodate<std::decay_t<decltype(component)>>(entity, component);
         };
 
-        using accumulator_type = int[];
-        accumulator_type accumulator = { 0, (registry.template remove<Tag>(), assign<Tag>(archive, apply, member...), 0)... };
-        (void)accumulator;
+        (reset<Component>(), ...);
+        (assign<Component>(archive, apply, member...), ...);
         return *this;
     }
 
@@ -646,7 +516,7 @@ public:
      *
      * @return A non-const reference to this loader.
      */
-    ContinuousLoader & shrink() {
+    continuous_loader & shrink() {
         auto it = remloc.begin();
 
         while(it != remloc.cend()) {
@@ -657,8 +527,8 @@ public:
                 dirty = false;
                 ++it;
             } else {
-                if(registry.valid(local)) {
-                    registry.destroy(local);
+                if(reg.valid(local)) {
+                    reg.destroy(local);
                 }
 
                 it = remloc.erase(it);
@@ -669,18 +539,18 @@ public:
     }
 
     /**
-     * @brief Destroys those entities that have neither components nor tags.
+     * @brief Destroys those entities that have no components.
      *
      * In case all the entities were serialized but only part of the components
-     * and tags was saved, it could happen that some of the entities have
-     * neither components nor tags once restored.<br/>
+     * was saved, it could happen that some of the entities have no components
+     * once restored.<br/>
      * This functions helps to identify and destroy those entities.
      *
      * @return A non-const reference to this loader.
      */
-    ContinuousLoader & orphans() {
-        registry.orphans([this](const auto entity) {
-            registry.destroy(entity);
+    continuous_loader & orphans() {
+        reg.orphans([this](const auto entity) {
+            reg.destroy(entity);
         });
 
         return *this;
@@ -714,7 +584,7 @@ public:
 
 private:
     std::unordered_map<Entity, std::pair<Entity, bool>> remloc;
-    Registry<Entity> &registry;
+    registry<Entity> &reg;
 };
 
 

+ 87 - 111
src/entt/entity/sparse_set.hpp

@@ -26,7 +26,7 @@ namespace entt {
  * compile-time error, but for a few reasonable cases.
  */
 template<typename...>
-class SparseSet;
+class sparse_set;
 
 
 /**
@@ -36,8 +36,8 @@ class SparseSet;
  * Two arrays: an _external_ one and an _internal_ one; a _sparse_ one and a
  * _packed_ one; one used for direct access through contiguous memory, the other
  * one used to get the data through an extra level of indirection.<br/>
- * This is largely used by the Registry to offer users the fastest access ever
- * to the components. View and PersistentView are entirely designed around
+ * This is largely used by the registry to offer users the fastest access ever
+ * to the components. Views in general are almost entirely designed around
  * sparse sets.
  *
  * This type of data structure is widely documented in the literature and on the
@@ -57,16 +57,16 @@ class SparseSet;
  * @tparam Entity A valid entity type (see entt_traits for more details).
  */
 template<typename Entity>
-class SparseSet<Entity> {
+class sparse_set<Entity> {
     using traits_type = entt_traits<Entity>;
 
-    class Iterator final {
-        friend class SparseSet<Entity>;
+    class iterator final {
+        friend class sparse_set<Entity>;
 
         using direct_type = const std::vector<Entity>;
         using index_type = typename traits_type::difference_type;
 
-        Iterator(direct_type *direct, index_type index) ENTT_NOEXCEPT
+        iterator(direct_type *direct, index_type index) ENTT_NOEXCEPT
             : direct{direct}, index{index}
         {}
 
@@ -77,47 +77,47 @@ class SparseSet<Entity> {
         using reference = value_type &;
         using iterator_category = std::random_access_iterator_tag;
 
-        Iterator() ENTT_NOEXCEPT = default;
+        iterator() ENTT_NOEXCEPT = default;
 
-        Iterator(const Iterator &) ENTT_NOEXCEPT = default;
-        Iterator & operator=(const Iterator &) ENTT_NOEXCEPT = default;
+        iterator(const iterator &) ENTT_NOEXCEPT = default;
+        iterator & operator=(const iterator &) ENTT_NOEXCEPT = default;
 
-        Iterator & operator++() ENTT_NOEXCEPT {
+        iterator & operator++() ENTT_NOEXCEPT {
             return --index, *this;
         }
 
-        Iterator operator++(int) ENTT_NOEXCEPT {
-            Iterator orig = *this;
+        iterator operator++(int) ENTT_NOEXCEPT {
+            iterator orig = *this;
             return ++(*this), orig;
         }
 
-        Iterator & operator--() ENTT_NOEXCEPT {
+        iterator & operator--() ENTT_NOEXCEPT {
             return ++index, *this;
         }
 
-        Iterator operator--(int) ENTT_NOEXCEPT {
-            Iterator orig = *this;
+        iterator operator--(int) ENTT_NOEXCEPT {
+            iterator orig = *this;
             return --(*this), orig;
         }
 
-        Iterator & operator+=(const difference_type value) ENTT_NOEXCEPT {
+        iterator & operator+=(const difference_type value) ENTT_NOEXCEPT {
             index -= value;
             return *this;
         }
 
-        Iterator operator+(const difference_type value) const ENTT_NOEXCEPT {
-            return Iterator{direct, index-value};
+        iterator operator+(const difference_type value) const ENTT_NOEXCEPT {
+            return iterator{direct, index-value};
         }
 
-        inline Iterator & operator-=(const difference_type value) ENTT_NOEXCEPT {
+        inline iterator & operator-=(const difference_type value) ENTT_NOEXCEPT {
             return (*this += -value);
         }
 
-        inline Iterator operator-(const difference_type value) const ENTT_NOEXCEPT {
+        inline iterator operator-(const difference_type value) const ENTT_NOEXCEPT {
             return (*this + -value);
         }
 
-        difference_type operator-(const Iterator &other) const ENTT_NOEXCEPT {
+        difference_type operator-(const iterator &other) const ENTT_NOEXCEPT {
             return other.index - index;
         }
 
@@ -126,27 +126,27 @@ class SparseSet<Entity> {
             return (*direct)[pos];
         }
 
-        bool operator==(const Iterator &other) const ENTT_NOEXCEPT {
+        bool operator==(const iterator &other) const ENTT_NOEXCEPT {
             return other.index == index;
         }
 
-        inline bool operator!=(const Iterator &other) const ENTT_NOEXCEPT {
+        inline bool operator!=(const iterator &other) const ENTT_NOEXCEPT {
             return !(*this == other);
         }
 
-        bool operator<(const Iterator &other) const ENTT_NOEXCEPT {
+        bool operator<(const iterator &other) const ENTT_NOEXCEPT {
             return index > other.index;
         }
 
-        bool operator>(const Iterator &other) const ENTT_NOEXCEPT {
+        bool operator>(const iterator &other) const ENTT_NOEXCEPT {
             return index < other.index;
         }
 
-        inline bool operator<=(const Iterator &other) const ENTT_NOEXCEPT {
+        inline bool operator<=(const iterator &other) const ENTT_NOEXCEPT {
             return !(*this > other);
         }
 
-        inline bool operator>=(const Iterator &other) const ENTT_NOEXCEPT {
+        inline bool operator>=(const iterator &other) const ENTT_NOEXCEPT {
             return !(*this < other);
         }
 
@@ -170,25 +170,25 @@ public:
     /*! @brief Unsigned integer type. */
     using size_type = std::size_t;
     /*! @brief Input iterator type. */
-    using iterator_type = Iterator;
+    using iterator_type = iterator;
     /*! @brief Constant input iterator type. */
-    using const_iterator_type = Iterator;
+    using const_iterator_type = iterator;
 
     /*! @brief Default constructor. */
-    SparseSet() ENTT_NOEXCEPT = default;
+    sparse_set() ENTT_NOEXCEPT = default;
 
     /*! @brief Default destructor. */
-    virtual ~SparseSet() ENTT_NOEXCEPT = default;
+    virtual ~sparse_set() ENTT_NOEXCEPT = default;
 
     /*! @brief Copying a sparse set isn't allowed. */
-    SparseSet(const SparseSet &) = delete;
+    sparse_set(const sparse_set &) = delete;
     /*! @brief Default move constructor. */
-    SparseSet(SparseSet &&) = default;
+    sparse_set(sparse_set &&) = default;
 
     /*! @brief Copying a sparse set isn't allowed. @return This sparse set. */
-    SparseSet & operator=(const SparseSet &) = delete;
+    sparse_set & operator=(const sparse_set &) = delete;
     /*! @brief Default move assignment operator. @return This sparse set. */
-    SparseSet & operator=(SparseSet &&) = default;
+    sparse_set & operator=(sparse_set &&) = default;
 
     /**
      * @brief Increases the capacity of a sparse set.
@@ -517,7 +517,7 @@ public:
      *
      * @param other The sparse sets that imposes the order of the entities.
      */
-    void respect(const SparseSet<Entity> &other) ENTT_NOEXCEPT {
+    void respect(const sparse_set &other) ENTT_NOEXCEPT {
         auto from = other.cbegin();
         auto to = other.cend();
 
@@ -555,7 +555,7 @@ private:
  *
  * This specialization of a sparse set associates an object to an entity. The
  * main purpose of this class is to use sparse sets to store components in a
- * Registry. It guarantees fast access both to the elements and to the entities.
+ * registry. It guarantees fast access both to the elements and to the entities.
  *
  * @note
  * Entities and objects have the same order. It's guaranteed both in case of raw
@@ -567,24 +567,24 @@ private:
  * iterate directly the internal packed array (see `raw` and `size` member
  * functions for that). Use `begin` and `end` instead.
  *
- * @sa SparseSet<Entity>
+ * @sa sparse_set<Entity>
  *
  * @tparam Entity A valid entity type (see entt_traits for more details).
  * @tparam Type Type of objects assigned to the entities.
  */
 template<typename Entity, typename Type>
-class SparseSet<Entity, Type>: public SparseSet<Entity> {
-    using underlying_type = SparseSet<Entity>;
+class sparse_set<Entity, Type>: public sparse_set<Entity> {
+    using underlying_type = sparse_set<Entity>;
     using traits_type = entt_traits<Entity>;
 
     template<bool Const>
-    class Iterator final {
-        friend class SparseSet<Entity, Type>;
+    class iterator final {
+        friend class sparse_set<Entity, Type>;
 
         using instance_type = std::conditional_t<Const, const std::vector<Type>, std::vector<Type>>;
         using index_type = typename traits_type::difference_type;
 
-        Iterator(instance_type *instances, index_type index) ENTT_NOEXCEPT
+        iterator(instance_type *instances, index_type index) ENTT_NOEXCEPT
             : instances{instances}, index{index}
         {}
 
@@ -595,47 +595,47 @@ class SparseSet<Entity, Type>: public SparseSet<Entity> {
         using reference = value_type &;
         using iterator_category = std::random_access_iterator_tag;
 
-        Iterator() ENTT_NOEXCEPT = default;
+        iterator() ENTT_NOEXCEPT = default;
 
-        Iterator(const Iterator &) ENTT_NOEXCEPT = default;
-        Iterator & operator=(const Iterator &) ENTT_NOEXCEPT = default;
+        iterator(const iterator &) ENTT_NOEXCEPT = default;
+        iterator & operator=(const iterator &) ENTT_NOEXCEPT = default;
 
-        Iterator & operator++() ENTT_NOEXCEPT {
+        iterator & operator++() ENTT_NOEXCEPT {
             return --index, *this;
         }
 
-        Iterator operator++(int) ENTT_NOEXCEPT {
-            Iterator orig = *this;
+        iterator operator++(int) ENTT_NOEXCEPT {
+            iterator orig = *this;
             return ++(*this), orig;
         }
 
-        Iterator & operator--() ENTT_NOEXCEPT {
+        iterator & operator--() ENTT_NOEXCEPT {
             return ++index, *this;
         }
 
-        Iterator operator--(int) ENTT_NOEXCEPT {
-            Iterator orig = *this;
+        iterator operator--(int) ENTT_NOEXCEPT {
+            iterator orig = *this;
             return --(*this), orig;
         }
 
-        Iterator & operator+=(const difference_type value) ENTT_NOEXCEPT {
+        iterator & operator+=(const difference_type value) ENTT_NOEXCEPT {
             index -= value;
             return *this;
         }
 
-        Iterator operator+(const difference_type value) const ENTT_NOEXCEPT {
-            return Iterator{instances, index-value};
+        iterator operator+(const difference_type value) const ENTT_NOEXCEPT {
+            return iterator{instances, index-value};
         }
 
-        inline Iterator & operator-=(const difference_type value) ENTT_NOEXCEPT {
+        inline iterator & operator-=(const difference_type value) ENTT_NOEXCEPT {
             return (*this += -value);
         }
 
-        inline Iterator operator-(const difference_type value) const ENTT_NOEXCEPT {
+        inline iterator operator-(const difference_type value) const ENTT_NOEXCEPT {
             return (*this + -value);
         }
 
-        difference_type operator-(const Iterator &other) const ENTT_NOEXCEPT {
+        difference_type operator-(const iterator &other) const ENTT_NOEXCEPT {
             return other.index - index;
         }
 
@@ -644,27 +644,27 @@ class SparseSet<Entity, Type>: public SparseSet<Entity> {
             return (*instances)[pos];
         }
 
-        bool operator==(const Iterator &other) const ENTT_NOEXCEPT {
+        bool operator==(const iterator &other) const ENTT_NOEXCEPT {
             return other.index == index;
         }
 
-        inline bool operator!=(const Iterator &other) const ENTT_NOEXCEPT {
+        inline bool operator!=(const iterator &other) const ENTT_NOEXCEPT {
             return !(*this == other);
         }
 
-        bool operator<(const Iterator &other) const ENTT_NOEXCEPT {
+        bool operator<(const iterator &other) const ENTT_NOEXCEPT {
             return index > other.index;
         }
 
-        bool operator>(const Iterator &other) const ENTT_NOEXCEPT {
+        bool operator>(const iterator &other) const ENTT_NOEXCEPT {
             return index < other.index;
         }
 
-        inline bool operator<=(const Iterator &other) const ENTT_NOEXCEPT {
+        inline bool operator<=(const iterator &other) const ENTT_NOEXCEPT {
             return !(*this > other);
         }
 
-        inline bool operator>=(const Iterator &other) const ENTT_NOEXCEPT {
+        inline bool operator>=(const iterator &other) const ENTT_NOEXCEPT {
             return !(*this < other);
         }
 
@@ -690,22 +690,22 @@ public:
     /*! @brief Unsigned integer type. */
     using size_type = typename underlying_type::size_type;
     /*! @brief Input iterator type. */
-    using iterator_type = Iterator<false>;
+    using iterator_type = iterator<false>;
     /*! @brief Constant input iterator type. */
-    using const_iterator_type = Iterator<true>;
+    using const_iterator_type = iterator<true>;
 
     /*! @brief Default constructor. */
-    SparseSet() ENTT_NOEXCEPT = default;
+    sparse_set() ENTT_NOEXCEPT = default;
 
     /*! @brief Copying a sparse set isn't allowed. */
-    SparseSet(const SparseSet &) = delete;
+    sparse_set(const sparse_set &) = delete;
     /*! @brief Default move constructor. */
-    SparseSet(SparseSet &&) = default;
+    sparse_set(sparse_set &&) = default;
 
     /*! @brief Copying a sparse set isn't allowed. @return This sparse set. */
-    SparseSet & operator=(const SparseSet &) = delete;
+    sparse_set & operator=(const sparse_set &) = delete;
     /*! @brief Default move assignment operator. @return This sparse set. */
-    SparseSet & operator=(SparseSet &&) = default;
+    sparse_set & operator=(sparse_set &&) = default;
 
     /**
      * @brief Increases the capacity of a sparse set.
@@ -877,7 +877,7 @@ public:
      * @return A reference to the requested element.
      */
     inline object_type & operator[](const size_type pos) ENTT_NOEXCEPT {
-        return const_cast<object_type &>(const_cast<const SparseSet *>(this)->operator[](pos));
+        return const_cast<object_type &>(std::as_const(*this).operator[](pos));
     }
 
     /**
@@ -909,17 +909,16 @@ public:
      * @return The object associated to the entity.
      */
     inline object_type & get(const entity_type entity) ENTT_NOEXCEPT {
-        return const_cast<object_type &>(const_cast<const SparseSet *>(this)->get(entity));
+        return const_cast<object_type &>(std::as_const(*this).get(entity));
     }
 
     /**
      * @brief Assigns an entity to a sparse set and constructs its object.
      *
      * @note
-     * _Sfinae'd_ function.<br/>
-     * This version is used for types that can be constructed in place directly.
-     * It doesn't work well with aggregates because of the placement new usually
-     * performed under the hood during an _emplace back_.
+     * This version accept both types that can be constructed in place directly
+     * and types like aggregates that do not work well with a placement new as
+     * performed usually under the hood during an _emplace back_.
      *
      * @warning
      * Attempting to use an entity that already belongs to the sparse set
@@ -933,38 +932,15 @@ public:
      * @return The object associated to the entity.
      */
     template<typename... Args>
-    std::enable_if_t<std::is_constructible<Type, Args...>::value, object_type &>
-    construct(const entity_type entity, Args &&... args) {
+    object_type & construct(const entity_type entity, Args &&... args) {
         underlying_type::construct(entity);
-        instances.emplace_back(std::forward<Args>(args)...);
-        return instances.back();
-    }
 
-    /**
-     * @brief Assigns an entity to a sparse set and constructs its object.
-     *
-     * @note
-     * _Sfinae'd_ function.<br/>
-     * Fallback for aggregates and types in general that do not work well with a
-     * placement new as performed usually under the hood during an
-     * _emplace back_.
-     *
-     * @warning
-     * Attempting to use an entity that already belongs to the sparse set
-     * results in undefined behavior.<br/>
-     * An assertion will abort the execution at runtime in debug mode if the
-     * sparse set already contains the given entity.
-     *
-     * @tparam Args Types of arguments to use to construct the object.
-     * @param entity A valid entity identifier.
-     * @param args Parameters to use to construct an object for the entity.
-     * @return The object associated to the entity.
-     */
-    template<typename... Args>
-    std::enable_if_t<!std::is_constructible<Type, Args...>::value, object_type &>
-    construct(const entity_type entity, Args &&... args) {
-        underlying_type::construct(entity);
-        instances.emplace_back(Type{std::forward<Args>(args)...});
+        if constexpr(std::is_aggregate_v<Type>) {
+            instances.emplace_back(Type{std::forward<Args>(args)...});
+        } else {
+            instances.emplace_back(std::forward<Args>(args)...);
+        }
+
         return instances.back();
     }
 
@@ -1029,13 +1005,13 @@ public:
      * @param sort A valid sort function object.
      * @param args Arguments to forward to the sort function object, if any.
      */
-    template<typename Compare, typename Sort = StdSort, typename... Args>
+    template<typename Compare, typename Sort = std_sort, typename... Args>
     void sort(Compare compare, Sort sort = Sort{}, Args &&... args) {
         std::vector<size_type> copy(instances.size());
         std::iota(copy.begin(), copy.end(), 0);
 
         sort(copy.begin(), copy.end(), [this, compare = std::move(compare)](const auto lhs, const auto rhs) {
-            return compare(const_cast<const object_type &>(instances[rhs]), const_cast<const object_type &>(instances[lhs]));
+            return compare(std::as_const(instances[rhs]), std::as_const(instances[lhs]));
         }, std::forward<Args>(args)...);
 
         for(size_type pos = 0, last = copy.size(); pos < last; ++pos) {
@@ -1077,7 +1053,7 @@ public:
      *
      * @param other The sparse sets that imposes the order of the entities.
      */
-    void respect(const SparseSet<Entity> &other) ENTT_NOEXCEPT {
+    void respect(const sparse_set<Entity> &other) ENTT_NOEXCEPT {
         auto from = other.cbegin();
         auto to = other.cend();
 

+ 0 - 23
src/entt/entity/utility.hpp

@@ -1,23 +0,0 @@
-#ifndef ENTT_ENTITY_UTILITY_HPP
-#define ENTT_ENTITY_UTILITY_HPP
-
-
-namespace entt {
-
-
-/*! @brief Tag class type used to disambiguate overloads. */
-struct tag_t final {};
-
-
-/*! @brief Persistent view type used to disambiguate overloads. */
-struct persistent_t final {};
-
-
-/*! @brief Raw view type used to disambiguate overloads. */
-struct raw_t final {};
-
-
-}
-
-
-#endif // ENTT_ENTITY_UTILITY_HPP

File diff suppressed because it is too large
+ 209 - 245
src/entt/entity/view.hpp


+ 0 - 2
src/entt/entt.hpp

@@ -4,7 +4,6 @@
 #include "core/ident.hpp"
 #include "core/monostate.hpp"
 #include "entity/actor.hpp"
-#include "entity/attachee.hpp"
 #include "entity/entity.hpp"
 #include "entity/entt_traits.hpp"
 #include "entity/helper.hpp"
@@ -12,7 +11,6 @@
 #include "entity/registry.hpp"
 #include "entity/snapshot.hpp"
 #include "entity/sparse_set.hpp"
-#include "entity/utility.hpp"
 #include "entity/view.hpp"
 #include "locator/locator.hpp"
 #include "process/process.hpp"

+ 4 - 8
src/entt/locator/locator.hpp

@@ -23,14 +23,14 @@ namespace entt {
  * @tparam Service Type of service managed by the locator.
  */
 template<typename Service>
-struct ServiceLocator final {
+struct service_locator final {
     /*! @brief Type of service offered. */
     using service_type = Service;
 
     /*! @brief Default constructor, deleted on purpose. */
-    ServiceLocator() = delete;
+    service_locator() = delete;
     /*! @brief Default destructor, deleted on purpose. */
-    ~ServiceLocator() = delete;
+    ~service_locator() = delete;
 
     /**
      * @brief Tests if a valid service implementation is set.
@@ -102,14 +102,10 @@ struct ServiceLocator final {
     }
 
 private:
-    static std::shared_ptr<Service> service;
+    inline static std::shared_ptr<Service> service = nullptr;
 };
 
 
-template<typename Service>
-std::shared_ptr<Service> ServiceLocator<Service>::service{};
-
-
 }
 
 

+ 47 - 45
src/entt/process/process.hpp

@@ -3,7 +3,6 @@
 
 
 #include <type_traits>
-#include <functional>
 #include <utility>
 #include "../config/config.h"
 
@@ -64,14 +63,14 @@ namespace entt {
  * `succeed` and `fail` protected member functions and even pause or unpause the
  * process itself.
  *
- * @sa Scheduler
+ * @sa scheduler
  *
  * @tparam Derived Actual type of process that extends the class template.
  * @tparam Delta Type to use to provide elapsed time.
  */
 template<typename Derived, typename Delta>
-class Process {
-    enum class State: unsigned int {
+class process {
+    enum class state: unsigned int {
         UNINITIALIZED = 0,
         RUNNING,
         PAUSED,
@@ -81,41 +80,44 @@ class Process {
         FINISHED
     };
 
-    template<State state>
-    using tag = std::integral_constant<State, state>;
+    template<state value>
+    using state_value_t = std::integral_constant<state, value>;
+
+    template<state value>
+    inline static state_value_t<value> state_value{};
 
     template<typename Target = Derived>
-    auto tick(int, tag<State::UNINITIALIZED>, void *data)
+    auto tick(int, state_value_t<state::UNINITIALIZED>, void *data)
     -> decltype(std::declval<Target>().init(data)) {
         static_cast<Target *>(this)->init(data);
     }
 
     template<typename Target = Derived>
-    auto tick(int, tag<State::RUNNING>, Delta delta, void *data)
+    auto tick(int, state_value_t<state::RUNNING>, Delta delta, void *data)
     -> decltype(std::declval<Target>().update(delta, data)) {
         static_cast<Target *>(this)->update(delta, data);
     }
 
     template<typename Target = Derived>
-    auto tick(int, tag<State::SUCCEEDED>)
+    auto tick(int, state_value_t<state::SUCCEEDED>)
     -> decltype(std::declval<Target>().succeeded()) {
         static_cast<Target *>(this)->succeeded();
     }
 
     template<typename Target = Derived>
-    auto tick(int, tag<State::FAILED>)
+    auto tick(int, state_value_t<state::FAILED>)
     -> decltype(std::declval<Target>().failed()) {
         static_cast<Target *>(this)->failed();
     }
 
     template<typename Target = Derived>
-    auto tick(int, tag<State::ABORTED>)
+    auto tick(int, state_value_t<state::ABORTED>)
     -> decltype(std::declval<Target>().aborted()) {
         static_cast<Target *>(this)->aborted();
     }
 
-    template<State S, typename... Args>
-    void tick(char, tag<S>, Args &&...) const ENTT_NOEXCEPT {}
+    template<state value, typename... Args>
+    void tick(char, state_value_t<value>, Args &&...) const ENTT_NOEXCEPT {}
 
 protected:
     /**
@@ -126,7 +128,7 @@ protected:
      */
     void succeed() ENTT_NOEXCEPT {
         if(alive()) {
-            current = State::SUCCEEDED;
+            current = state::SUCCEEDED;
         }
     }
 
@@ -138,7 +140,7 @@ protected:
      */
     void fail() ENTT_NOEXCEPT {
         if(alive()) {
-            current = State::FAILED;
+            current = state::FAILED;
         }
     }
 
@@ -149,8 +151,8 @@ protected:
      * running.
      */
     void pause() ENTT_NOEXCEPT {
-        if(current == State::RUNNING) {
-            current = State::PAUSED;
+        if(current == state::RUNNING) {
+            current = state::PAUSED;
         }
     }
 
@@ -161,8 +163,8 @@ protected:
      * paused.
      */
     void unpause() ENTT_NOEXCEPT {
-        if(current  == State::PAUSED) {
-            current  = State::RUNNING;
+        if(current  == state::PAUSED) {
+            current  = state::RUNNING;
         }
     }
 
@@ -171,8 +173,8 @@ public:
     using delta_type = Delta;
 
     /*! @brief Default destructor. */
-    virtual ~Process() ENTT_NOEXCEPT {
-        static_assert(std::is_base_of<Process, Derived>::value, "!");
+    virtual ~process() ENTT_NOEXCEPT {
+        static_assert(std::is_base_of_v<process, Derived>);
     }
 
     /**
@@ -185,7 +187,7 @@ public:
      */
     void abort(const bool immediately = false) ENTT_NOEXCEPT {
         if(alive()) {
-            current = State::ABORTED;
+            current = state::ABORTED;
 
             if(immediately) {
                 tick(0);
@@ -198,7 +200,7 @@ public:
      * @return True if the process is still alive, false otherwise.
      */
     bool alive() const ENTT_NOEXCEPT {
-        return current == State::RUNNING || current == State::PAUSED;
+        return current == state::RUNNING || current == state::PAUSED;
     }
 
     /**
@@ -206,7 +208,7 @@ public:
      * @return True if the process is terminated, false otherwise.
      */
     bool dead() const ENTT_NOEXCEPT {
-        return current == State::FINISHED;
+        return current == state::FINISHED;
     }
 
     /**
@@ -214,7 +216,7 @@ public:
      * @return True if the process is paused, false otherwise.
      */
     bool paused() const ENTT_NOEXCEPT {
-        return current == State::PAUSED;
+        return current == state::PAUSED;
     }
 
     /**
@@ -232,12 +234,12 @@ public:
      */
     void tick(const Delta delta, void *data = nullptr) {
         switch (current) {
-        case State::UNINITIALIZED:
-            tick(0, tag<State::UNINITIALIZED>{}, data);
-            current = State::RUNNING;
-            // no break on purpose, tasks are executed immediately
-        case State::RUNNING:
-            tick(0, tag<State::RUNNING>{}, delta, data);
+        case state::UNINITIALIZED:
+            tick(0, state_value_t<state::UNINITIALIZED>{}, data);
+            current = state::RUNNING;
+            [[fallthrough]];
+        case state::RUNNING:
+            tick(0, state_value_t<state::RUNNING>{}, delta, data);
         default:
             // suppress warnings
             break;
@@ -245,18 +247,18 @@ public:
 
         // if it's dead, it must be notified and removed immediately
         switch(current) {
-        case State::SUCCEEDED:
-            tick(0, tag<State::SUCCEEDED>{});
-            current = State::FINISHED;
+        case state::SUCCEEDED:
+            tick(0, state_value_t<state::SUCCEEDED>{});
+            current = state::FINISHED;
             break;
-        case State::FAILED:
-            tick(0, tag<State::FAILED>{});
-            current = State::FINISHED;
+        case state::FAILED:
+            tick(0, state_value_t<state::FAILED>{});
+            current = state::FINISHED;
             stopped = true;
             break;
-        case State::ABORTED:
-            tick(0, tag<State::ABORTED>{});
-            current = State::FINISHED;
+        case state::ABORTED:
+            tick(0, state_value_t<state::ABORTED>{});
+            current = state::FINISHED;
             stopped = true;
             break;
         default:
@@ -266,7 +268,7 @@ public:
     }
 
 private:
-    State current{State::UNINITIALIZED};
+    state current{state::UNINITIALIZED};
     bool stopped{false};
 };
 
@@ -304,21 +306,21 @@ private:
  * create them internally each and avery time a lambda or a functor is used as
  * a process.
  *
- * @sa Process
- * @sa Scheduler
+ * @sa process
+ * @sa scheduler
  *
  * @tparam Func Actual type of process.
  * @tparam Delta Type to use to provide elapsed time.
  */
 template<typename Func, typename Delta>
-struct ProcessAdaptor: Process<ProcessAdaptor<Func, Delta>, Delta>, private Func {
+struct process_adaptor: process<process_adaptor<Func, Delta>, Delta>, private Func {
     /**
      * @brief Constructs a process adaptor from a lambda or a functor.
      * @tparam Args Types of arguments to use to initialize the actual process.
      * @param args Parameters to use to initialize the actual process.
      */
     template<typename... Args>
-    ProcessAdaptor(Args &&... args)
+    process_adaptor(Args &&... args)
         : Func{std::forward<Args>(args)...}
     {}
 

+ 37 - 38
src/entt/process/scheduler.hpp

@@ -30,23 +30,23 @@ namespace entt {
  * @code{.cpp}
  * scheduler.attach([](auto delta, void *, auto succeed, auto fail) {
  *     // code
- * }).then<MyProcess>(arguments...);
+ * }).then<my_process>(arguments...);
  * @endcode
  *
  * In order to invoke all scheduled processes, call the `update` member function
  * passing it the elapsed time to forward to the tasks.
  *
- * @sa Process
+ * @sa process
  *
  * @tparam Delta Type to use to provide elapsed time.
  */
 template<typename Delta>
-class Scheduler final {
-    struct ProcessHandler final {
+class scheduler final {
+    struct process_handler final {
         using instance_type = std::unique_ptr<void, void(*)(void *)>;
-        using update_fn_type = bool(ProcessHandler &, Delta, void *);
-        using abort_fn_type = void(ProcessHandler &, bool);
-        using next_type = std::unique_ptr<ProcessHandler>;
+        using update_fn_type = bool(process_handler &, Delta, void *);
+        using abort_fn_type = void(process_handler &, bool);
+        using next_type = std::unique_ptr<process_handler>;
 
         instance_type instance;
         update_fn_type *update;
@@ -54,30 +54,29 @@ class Scheduler final {
         next_type next;
     };
 
-    struct Then final {
-        Then(ProcessHandler *handler)
+    struct continuation final {
+        continuation(process_handler *handler)
             : handler{handler}
         {}
 
         template<typename Proc, typename... Args>
-        decltype(auto) then(Args &&... args) && {
-            static_assert(std::is_base_of<Process<Proc, Delta>, Proc>::value, "!");
-            handler = Scheduler::then<Proc>(handler, std::forward<Args>(args)...);
-            return std::move(*this);
+        continuation then(Args &&... args) {
+            static_assert(std::is_base_of_v<process<Proc, Delta>, Proc>);
+            handler = scheduler::then<Proc>(handler, std::forward<Args>(args)...);
+            return *this;
         }
 
         template<typename Func>
-        decltype(auto) then(Func &&func) && {
-            using Proc = ProcessAdaptor<std::decay_t<Func>, Delta>;
-            return std::move(*this).template then<Proc>(std::forward<Func>(func));
+        continuation then(Func &&func) {
+            return then<process_adaptor<std::decay_t<Func>, Delta>>(std::forward<Func>(func));
         }
 
     private:
-        ProcessHandler *handler;
+        process_handler *handler;
     };
 
     template<typename Proc>
-    static bool update(ProcessHandler &handler, const Delta delta, void *data) {
+    static bool update(process_handler &handler, const Delta delta, void *data) {
         auto *process = static_cast<Proc *>(handler.instance.get());
         process->tick(delta, data);
 
@@ -96,7 +95,7 @@ class Scheduler final {
     }
 
     template<typename Proc>
-    static void abort(ProcessHandler &handler, const bool immediately) {
+    static void abort(process_handler &handler, const bool immediately) {
         static_cast<Proc *>(handler.instance.get())->abort(immediately);
     }
 
@@ -106,10 +105,10 @@ class Scheduler final {
     }
 
     template<typename Proc, typename... Args>
-    static auto then(ProcessHandler *handler, Args &&... args) {
+    static auto then(process_handler *handler, Args &&... args) {
         if(handler) {
-            auto proc = typename ProcessHandler::instance_type{new Proc{std::forward<Args>(args)...}, &Scheduler::deleter<Proc>};
-            handler->next.reset(new ProcessHandler{std::move(proc), &Scheduler::update<Proc>, &Scheduler::abort<Proc>, nullptr});
+            auto proc = typename process_handler::instance_type{new Proc{std::forward<Args>(args)...}, &scheduler::deleter<Proc>};
+            handler->next.reset(new process_handler{std::move(proc), &scheduler::update<Proc>, &scheduler::abort<Proc>, nullptr});
             handler = handler->next.get();
         }
 
@@ -118,20 +117,20 @@ class Scheduler final {
 
 public:
     /*! @brief Unsigned integer type. */
-    using size_type = typename std::vector<ProcessHandler>::size_type;
+    using size_type = typename std::vector<process_handler>::size_type;
 
     /*! @brief Default constructor. */
-    Scheduler() ENTT_NOEXCEPT = default;
+    scheduler() ENTT_NOEXCEPT = default;
 
     /*! @brief Copying a scheduler isn't allowed. */
-    Scheduler(const Scheduler &) = delete;
+    scheduler(const scheduler &) = delete;
     /*! @brief Default move constructor. */
-    Scheduler(Scheduler &&) = default;
+    scheduler(scheduler &&) = default;
 
     /*! @brief Copying a scheduler isn't allowed. @return This scheduler. */
-    Scheduler & operator=(const Scheduler &) = delete;
+    scheduler & operator=(const scheduler &) = delete;
     /*! @brief Default move assignment operator. @return This scheduler. */
-    Scheduler & operator=(Scheduler &&) = default;
+    scheduler & operator=(scheduler &&) = default;
 
     /**
      * @brief Number of processes currently scheduled.
@@ -170,13 +169,13 @@ public:
      *
      * @code{.cpp}
      * // schedules a task in the form of a process class
-     * scheduler.attach<MyProcess>(arguments...)
+     * scheduler.attach<my_process>(arguments...)
      * // appends a child in the form of a lambda function
      * .then([](auto delta, void *, auto succeed, auto fail) {
      *     // code
      * })
      * // appends a child in the form of another process class
-     * .then<MyOtherProcess>();
+     * .then<my_other_process>();
      * @endcode
      *
      * @tparam Proc Type of process to schedule.
@@ -186,13 +185,13 @@ public:
      */
     template<typename Proc, typename... Args>
     auto attach(Args &&... args) {
-        static_assert(std::is_base_of<Process<Proc, Delta>, Proc>::value, "!");
+        static_assert(std::is_base_of_v<process<Proc, Delta>, Proc>);
 
-        auto proc = typename ProcessHandler::instance_type{new Proc{std::forward<Args>(args)...}, &Scheduler::deleter<Proc>};
-        ProcessHandler handler{std::move(proc), &Scheduler::update<Proc>, &Scheduler::abort<Proc>, nullptr};
+        auto proc = typename process_handler::instance_type{new Proc{std::forward<Args>(args)...}, &scheduler::deleter<Proc>};
+        process_handler handler{std::move(proc), &scheduler::update<Proc>, &scheduler::abort<Proc>, nullptr};
         handlers.push_back(std::move(handler));
 
-        return Then{&handlers.back()};
+        return continuation{&handlers.back()};
     }
 
     /**
@@ -236,10 +235,10 @@ public:
      *     // code
      * })
      * // appends a child in the form of a process class
-     * .then<MyProcess>(arguments...);
+     * .then<my_process>(arguments...);
      * @endcode
      *
-     * @sa ProcessAdaptor
+     * @sa process_adaptor
      *
      * @tparam Func Type of process to schedule.
      * @param func Either a lambda or a functor to use as a process.
@@ -247,7 +246,7 @@ public:
      */
     template<typename Func>
     auto attach(Func &&func) {
-        using Proc = ProcessAdaptor<std::decay_t<Func>, Delta>;
+        using Proc = process_adaptor<std::decay_t<Func>, Delta>;
         return attach<Proc>(std::forward<Func>(func));
     }
 
@@ -301,7 +300,7 @@ public:
     }
 
 private:
-    std::vector<ProcessHandler> handlers{};
+    std::vector<process_handler> handlers{};
 };
 
 

+ 12 - 12
src/entt/resource/cache.hpp

@@ -26,27 +26,27 @@ namespace entt {
  * @tparam Resource Type of resources managed by a cache.
  */
 template<typename Resource>
-class ResourceCache {
-    using container_type = std::unordered_map<HashedString::hash_type, std::shared_ptr<Resource>>;
+class resource_cache {
+    using container_type = std::unordered_map<hashed_string::hash_type, std::shared_ptr<Resource>>;
 
 public:
     /*! @brief Unsigned integer type. */
     using size_type = typename container_type::size_type;
     /*! @brief Type of resources managed by a cache. */
-    using resource_type = HashedString;
+    using resource_type = hashed_string;
 
     /*! @brief Default constructor. */
-    ResourceCache() = default;
+    resource_cache() = default;
 
     /*! @brief Copying a cache isn't allowed. */
-    ResourceCache(const ResourceCache &) ENTT_NOEXCEPT = delete;
+    resource_cache(const resource_cache &) ENTT_NOEXCEPT = delete;
     /*! @brief Default move constructor. */
-    ResourceCache(ResourceCache &&) ENTT_NOEXCEPT = default;
+    resource_cache(resource_cache &&) ENTT_NOEXCEPT = default;
 
     /*! @brief Copying a cache isn't allowed. @return This cache. */
-    ResourceCache & operator=(const ResourceCache &) ENTT_NOEXCEPT = delete;
+    resource_cache & operator=(const resource_cache &) ENTT_NOEXCEPT = delete;
     /*! @brief Default move assignment operator. @return This cache. */
-    ResourceCache & operator=(ResourceCache &&) ENTT_NOEXCEPT = default;
+    resource_cache & operator=(resource_cache &&) ENTT_NOEXCEPT = default;
 
     /**
      * @brief Number of resources managed by a cache.
@@ -94,7 +94,7 @@ public:
      */
     template<typename Loader, typename... Args>
     bool load(const resource_type id, Args &&... args) {
-        static_assert(std::is_base_of<ResourceLoader<Loader, Resource>, Loader>::value, "!");
+        static_assert(std::is_base_of_v<resource_loader<Loader, Resource>, Loader>);
 
         bool loaded = true;
 
@@ -143,7 +143,7 @@ public:
      * @return A handle for the given resource.
      */
     template<typename Loader, typename... Args>
-    ResourceHandle<Resource> temp(Args &&... args) const {
+    resource_handle<Resource> temp(Args &&... args) const {
         return { Loader{}.get(std::forward<Args>(args)...) };
     }
 
@@ -155,12 +155,12 @@ public:
      * cache contains the resource itself. Otherwise the returned handle is
      * uninitialized and accessing it results in undefined behavior.
      *
-     * @sa ResourceHandle
+     * @sa resource_handle
      *
      * @param id Unique resource identifier.
      * @return A handle for the given resource.
      */
-    ResourceHandle<Resource> handle(const resource_type id) const {
+    resource_handle<Resource> handle(const resource_type id) const {
         auto it = resources.find(id);
         return { it == resources.end() ? nullptr : it->second };
     }

+ 8 - 8
src/entt/resource/handle.hpp

@@ -12,7 +12,7 @@ namespace entt {
 
 
 template<typename Resource>
-class ResourceCache;
+class resource_cache;
 
 
 /**
@@ -28,24 +28,24 @@ class ResourceCache;
  * @tparam Resource Type of resource managed by a handle.
  */
 template<typename Resource>
-class ResourceHandle final {
+class resource_handle final {
     /*! @brief Resource handles are friends of their caches. */
-    friend class ResourceCache<Resource>;
+    friend class resource_cache<Resource>;
 
-    ResourceHandle(std::shared_ptr<Resource> res) ENTT_NOEXCEPT
+    resource_handle(std::shared_ptr<Resource> res) ENTT_NOEXCEPT
         : resource{std::move(res)}
     {}
 
 public:
     /*! @brief Default copy constructor. */
-    ResourceHandle(const ResourceHandle &) ENTT_NOEXCEPT = default;
+    resource_handle(const resource_handle &) ENTT_NOEXCEPT = default;
     /*! @brief Default move constructor. */
-    ResourceHandle(ResourceHandle &&) ENTT_NOEXCEPT = default;
+    resource_handle(resource_handle &&) ENTT_NOEXCEPT = default;
 
     /*! @brief Default copy assignment operator. @return This handle. */
-    ResourceHandle & operator=(const ResourceHandle &) ENTT_NOEXCEPT = default;
+    resource_handle & operator=(const resource_handle &) ENTT_NOEXCEPT = default;
     /*! @brief Default move assignment operator. @return This handle. */
-    ResourceHandle & operator=(ResourceHandle &&) ENTT_NOEXCEPT = default;
+    resource_handle & operator=(resource_handle &&) ENTT_NOEXCEPT = default;
 
     /**
      * @brief Gets a reference to the managed resource.

+ 7 - 7
src/entt/resource/loader.hpp

@@ -9,7 +9,7 @@ namespace entt {
 
 
 template<typename Resource>
-class ResourceCache;
+class resource_cache;
 
 
 /**
@@ -22,12 +22,12 @@ class ResourceCache;
  * As an example:
  *
  * @code{.cpp}
- * struct MyResource {};
+ * struct my_resource {};
  *
- * struct MyLoader: entt::ResourceLoader<MyLoader, MyResource> {
- *     std::shared_ptr<MyResource> load(int) const {
+ * struct my_loader: entt::resource_loader<my_loader, my_resource> {
+ *     std::shared_ptr<my_resource> load(int) const {
  *         // use the integer value somehow
- *         return std::make_shared<MyResource>();
+ *         return std::make_shared<my_resource>();
  *     }
  * };
  * @endcode
@@ -45,9 +45,9 @@ class ResourceCache;
  * @tparam Resource Type of resource for which to use the loader.
  */
 template<typename Loader, typename Resource>
-class ResourceLoader {
+class resource_loader {
     /*! @brief Resource loaders are friends of their caches. */
-    friend class ResourceCache<Resource>;
+    friend class resource_cache<Resource>;
 
     template<typename... Args>
     std::shared_ptr<Resource> get(Args &&... args) const {

+ 67 - 33
src/entt/signal/delegate.hpp

@@ -3,12 +3,24 @@
 
 
 #include <utility>
+#include <functional>
+#include <type_traits>
 #include "../config/config.h"
 
 
 namespace entt {
 
 
+/*! @brief Used to wrap a function or a member function of a specified type. */
+template<auto>
+struct connect_arg_t {};
+
+
+/*! @brief Constant of type connect_arg_t used to disambiguate calls. */
+template<auto Func>
+inline static connect_arg_t<Func> connect_arg{};
+
+
 /**
  * @brief Basic delegate implementation.
  *
@@ -16,7 +28,7 @@ namespace entt {
  * compile-time error unless the template parameter is a function type.
  */
 template<typename>
-class Delegate;
+class delegate;
 
 
 /**
@@ -33,31 +45,50 @@ class Delegate;
  * @tparam Args Types of arguments of a function type.
  */
 template<typename Ret, typename... Args>
-class Delegate<Ret(Args...)> final {
+class delegate<Ret(Args...)> final {
     using proto_fn_type = Ret(void *, Args...);
     using stub_type = std::pair<void *, proto_fn_type *>;
 
-    template<Ret(*Function)(Args...)>
+    template<auto Function>
     static Ret proto(void *, Args... args) {
-        return (Function)(args...);
+        return std::invoke(Function, args...);
     }
 
-    template<typename Class, Ret(Class:: *Member)(Args...) const>
+    template<typename Class, auto Member>
     static Ret proto(void *instance, Args... args) {
-        return (static_cast<const Class *>(instance)->*Member)(args...);
-    }
-
-    template<typename Class, Ret(Class:: *Member)(Args...)>
-    static Ret proto(void *instance, Args... args) {
-        return (static_cast<Class *>(instance)->*Member)(args...);
+        return std::invoke(Member, static_cast<Class *>(instance), args...);
     }
 
 public:
     /*! @brief Default constructor. */
-    Delegate() ENTT_NOEXCEPT
+    delegate() ENTT_NOEXCEPT
         : stub{}
     {}
 
+    /**
+     * @brief Constructs a delegate and binds a free function to it.
+     * @tparam Function A valid free function pointer.
+     */
+    template<auto Function>
+    delegate(connect_arg_t<Function>) ENTT_NOEXCEPT
+        : stub{}
+    {
+        connect<Function>();
+    }
+
+    /**
+     * @brief Constructs a delegate and binds a member function to it.
+     * @tparam Member Member function to connect to the delegate.
+     * @tparam Class Type of class to which the member function belongs.
+     * @param instance A valid instance of type pointer to `Class`.
+     */
+    template<auto Member, typename Class>
+    delegate(connect_arg_t<Member>, Class *instance) ENTT_NOEXCEPT
+        : stub{}
+    {
+        connect<Member>(instance);
+    }
+
     /**
      * @brief Checks whether a delegate actually stores a listener.
      * @return True if the delegate is empty, false otherwise.
@@ -71,8 +102,9 @@ public:
      * @brief Binds a free function to a delegate.
      * @tparam Function A valid free function pointer.
      */
-    template<Ret(*Function)(Args...)>
+    template<auto Function>
     void connect() ENTT_NOEXCEPT {
+        static_assert(std::is_invocable_r_v<Ret, decltype(Function), Args...>);
         stub = std::make_pair(nullptr, &proto<Function>);
     }
 
@@ -83,28 +115,13 @@ public:
      * guarantee that the lifetime of the instance overcomes the one of the
      * delegate.
      *
-     * @tparam Class Type of class to which the member function belongs.
      * @tparam Member Member function to connect to the delegate.
-     * @param instance A valid instance of type pointer to `Class`.
-     */
-    template<typename Class, Ret(Class:: *Member)(Args...) const>
-    void connect(Class *instance) ENTT_NOEXCEPT {
-        stub = std::make_pair(instance, &proto<Class, Member>);
-    }
-
-    /**
-     * @brief Connects a member function for a given instance to a delegate.
-     *
-     * The delegate isn't responsible for the connected object. Users must
-     * guarantee that the lifetime of the instance overcomes the one of the
-     * delegate.
-     *
      * @tparam Class Type of class to which the member function belongs.
-     * @tparam Member Member function to connect to the delegate.
      * @param instance A valid instance of type pointer to `Class`.
      */
-    template<typename Class, Ret(Class:: *Member)(Args...)>
+    template<auto Member, typename Class>
     void connect(Class *instance) ENTT_NOEXCEPT {
+        static_assert(std::is_invocable_r_v<Ret, decltype(Member), Class, Args...>);
         stub = std::make_pair(instance, &proto<Class, Member>);
     }
 
@@ -117,8 +134,25 @@ public:
         stub.second = nullptr;
     }
 
+    /**
+     * @brief Returns the instance bound to a delegate, if any.
+     * @return An opaque pointer to the instance bound to the delegate, if any.
+     */
+    const void * instance() const ENTT_NOEXCEPT {
+        return stub.first;
+    }
+
     /**
      * @brief Triggers a delegate.
+     *
+     * The delegate invokes the underlying function and returns the result.
+     *
+     * @warning
+     * Attempting to trigger an invalid delegate results in undefined
+     * behavior.<br/>
+     * An assertion will abort the execution at runtime in debug mode if the
+     * delegate has not yet been set.
+     *
      * @param args Arguments to use to invoke the underlying function.
      * @return The value returned by the underlying function.
      */
@@ -134,12 +168,12 @@ public:
      * @param other Delegate with which to compare.
      * @return True if the two delegates are identical, false otherwise.
      */
-    bool operator==(const Delegate<Ret(Args...)> &other) const ENTT_NOEXCEPT {
+    bool operator==(const delegate<Ret(Args...)> &other) const ENTT_NOEXCEPT {
         return stub.first == other.stub.first && stub.second == other.stub.second;
     }
 
 private:
-    stub_type stub;
+    stub_type stub{};
 };
 
 
@@ -155,7 +189,7 @@ private:
  * @return True if the two delegates are different, false otherwise.
  */
 template<typename Ret, typename... Args>
-bool operator!=(const Delegate<Ret(Args...)> &lhs, const Delegate<Ret(Args...)> &rhs) ENTT_NOEXCEPT {
+bool operator!=(const delegate<Ret(Args...)> &lhs, const delegate<Ret(Args...)> &rhs) ENTT_NOEXCEPT {
     return !(lhs == rhs);
 }
 

+ 17 - 20
src/entt/signal/dispatcher.hpp

@@ -5,7 +5,6 @@
 #include <vector>
 #include <memory>
 #include <utility>
-#include <cstdint>
 #include <algorithm>
 #include <type_traits>
 #include "../config/config.h"
@@ -22,30 +21,28 @@ namespace entt {
  * A dispatcher can be used either to trigger an immediate event or to enqueue
  * events to be published all together once per tick.<br/>
  * Listeners are provided in the form of member functions. For each event of
- * type `Event`, listeners must have the following function type:
- * @code{.cpp}
- * void(const Event &)
- * @endcode
+ * type `Event`, listeners are such that they can be invoked with an argument of
+ * type `const Event &`, no matter what the return type is.
  *
  * Member functions named `receive` are automatically detected and registered or
  * unregistered by the dispatcher. The type of the instances is `Class *` (a
  * naked pointer). It means that users must guarantee that the lifetimes of the
  * instances overcome the one of the dispatcher itself to avoid crashes.
  */
-class Dispatcher final {
-    using event_family = Family<struct InternalDispatcherEventFamily>;
+class dispatcher final {
+    using event_family = family<struct internal_dispatcher_event_family>;
 
     template<typename Class, typename Event>
-    using instance_type = typename SigH<void(const Event &)>::template instance_type<Class>;
+    using instance_type = typename sigh<void(const Event &)>::template instance_type<Class>;
 
-    struct BaseSignalWrapper {
-        virtual ~BaseSignalWrapper() = default;
+    struct base_wrapper {
+        virtual ~base_wrapper() = default;
         virtual void publish() = 0;
     };
 
     template<typename Event>
-    struct SignalWrapper final: BaseSignalWrapper {
-        using sink_type = typename SigH<void(const Event &)>::sink_type;
+    struct signal_wrapper final: base_wrapper {
+        using sink_type = typename sigh<void(const Event &)>::sink_type;
 
         void publish() override {
             const auto &curr = current++;
@@ -69,30 +66,30 @@ class Dispatcher final {
         }
 
     private:
-        SigH<void(const Event &)> signal{};
+        sigh<void(const Event &)> signal{};
         std::vector<Event> events[2];
         int current{};
     };
 
     template<typename Event>
-    SignalWrapper<Event> & wrapper() {
-        const auto type = event_family::type<Event>();
+    signal_wrapper<Event> & wrapper() {
+        const auto type = event_family::type<Event>;
 
         if(!(type < wrappers.size())) {
             wrappers.resize(type + 1);
         }
 
         if(!wrappers[type]) {
-            wrappers[type] = std::make_unique<SignalWrapper<Event>>();
+            wrappers[type] = std::make_unique<signal_wrapper<Event>>();
         }
 
-        return static_cast<SignalWrapper<Event> &>(*wrappers[type]);
+        return static_cast<signal_wrapper<Event> &>(*wrappers[type]);
     }
 
 public:
     /*! @brief Type of sink for the given event. */
     template<typename Event>
-    using sink_type = typename SignalWrapper<Event>::sink_type;
+    using sink_type = typename signal_wrapper<Event>::sink_type;
 
     /**
      * @brief Returns a sink object for the given event.
@@ -106,7 +103,7 @@ public:
      *
      * The order of invocation of the listeners isn't guaranteed.
      *
-     * @sa SigH::Sink
+     * @sa sink
      *
      * @tparam Event Type of event of which to get the sink.
      * @return A temporary sink object.
@@ -178,7 +175,7 @@ public:
     }
 
 private:
-    std::vector<std::unique_ptr<BaseSignalWrapper>> wrappers;
+    std::vector<std::unique_ptr<base_wrapper>> wrappers;
 };
 
 

+ 51 - 51
src/entt/signal/emitter.hpp

@@ -6,7 +6,7 @@
 #include <functional>
 #include <algorithm>
 #include <utility>
-#include <cstdint>
+#include <cstddef>
 #include <memory>
 #include <vector>
 #include <list>
@@ -24,7 +24,7 @@ namespace entt {
  * type, derived classes must inherit directly from the base class as:
  *
  * ```cpp
- * struct MyEmitter: Emitter<MyEmitter> {
+ * struct my_emitter: emitter<my_emitter> {
  *     // ...
  * }
  * ```
@@ -39,17 +39,17 @@ namespace entt {
  * @tparam Derived Actual type of emitter that extends the class template.
  */
 template<typename Derived>
-class Emitter {
-    using handler_family = Family<struct InternalEmitterHandlerFamily>;
+class emitter {
+    using handler_family = family<struct internal_emitter_handler_family>;
 
-    struct BaseHandler {
-        virtual ~BaseHandler() = default;
+    struct base_handler {
+        virtual ~base_handler() = default;
         virtual bool empty() const ENTT_NOEXCEPT = 0;
         virtual void clear() ENTT_NOEXCEPT = 0;
     };
 
     template<typename Event>
-    struct Handler final: BaseHandler {
+    struct event_handler final: base_handler {
         using listener_type = std::function<void(const Event &, Derived &)>;
         using element_type = std::pair<bool, listener_type>;
         using container_type = std::list<element_type>;
@@ -58,27 +58,27 @@ class Emitter {
         bool empty() const ENTT_NOEXCEPT override {
             auto pred = [](auto &&element) { return element.first; };
 
-            return std::all_of(onceL.cbegin(), onceL.cend(), pred) &&
-                    std::all_of(onL.cbegin(), onL.cend(), pred);
+            return std::all_of(once_list.cbegin(), once_list.cend(), pred) &&
+                    std::all_of(on_list.cbegin(), on_list.cend(), pred);
         }
 
         void clear() ENTT_NOEXCEPT override {
             if(publishing) {
                 auto func = [](auto &&element) { element.first = true; };
-                std::for_each(onceL.begin(), onceL.end(), func);
-                std::for_each(onL.begin(), onL.end(), func);
+                std::for_each(once_list.begin(), once_list.end(), func);
+                std::for_each(on_list.begin(), on_list.end(), func);
             } else {
-                onceL.clear();
-                onL.clear();
+                once_list.clear();
+                on_list.clear();
             }
         }
 
         inline connection_type once(listener_type listener) {
-            return onceL.emplace(onceL.cend(), false, std::move(listener));
+            return once_list.emplace(once_list.cend(), false, std::move(listener));
         }
 
         inline connection_type on(listener_type listener) {
-            return onL.emplace(onL.cend(), false, std::move(listener));
+            return on_list.emplace(on_list.cend(), false, std::move(listener));
         }
 
         void erase(connection_type conn) ENTT_NOEXCEPT {
@@ -86,14 +86,14 @@ class Emitter {
 
             if(!publishing) {
                 auto pred = [](auto &&element) { return element.first; };
-                onceL.remove_if(pred);
-                onL.remove_if(pred);
+                once_list.remove_if(pred);
+                on_list.remove_if(pred);
             }
         }
 
         void publish(const Event &event, Derived &ref) {
-            container_type currentL;
-            onceL.swap(currentL);
+            container_type swap_list;
+            once_list.swap(swap_list);
 
             auto func = [&event, &ref](auto &&element) {
                 return element.first ? void() : element.second(event, ref);
@@ -101,39 +101,39 @@ class Emitter {
 
             publishing = true;
 
-            std::for_each(onL.rbegin(), onL.rend(), func);
-            std::for_each(currentL.rbegin(), currentL.rend(), func);
+            std::for_each(on_list.rbegin(), on_list.rend(), func);
+            std::for_each(swap_list.rbegin(), swap_list.rend(), func);
 
             publishing = false;
 
-            onL.remove_if([](auto &&element) { return element.first; });
+            on_list.remove_if([](auto &&element) { return element.first; });
         }
 
     private:
         bool publishing{false};
-        container_type onceL{};
-        container_type onL{};
+        container_type once_list{};
+        container_type on_list{};
     };
 
     template<typename Event>
-    Handler<Event> & handler() ENTT_NOEXCEPT {
-        const std::size_t family = handler_family::type<Event>();
+    event_handler<Event> & handler() ENTT_NOEXCEPT {
+        const std::size_t family = handler_family::type<Event>;
 
         if(!(family < handlers.size())) {
             handlers.resize(family+1);
         }
 
         if(!handlers[family]) {
-            handlers[family] = std::make_unique<Handler<Event>>();
+            handlers[family] = std::make_unique<event_handler<Event>>();
         }
 
-        return static_cast<Handler<Event> &>(*handlers[family]);
+        return static_cast<event_handler<Event> &>(*handlers[family]);
     }
 
 public:
     /** @brief Type of listeners accepted for the given event. */
     template<typename Event>
-    using Listener = typename Handler<Event>::listener_type;
+    using listener = typename event_handler<Event>::listener_type;
 
     /**
      * @brief Generic connection type for events.
@@ -145,56 +145,56 @@ public:
      * @tparam Event Type of event for which the connection is created.
      */
     template<typename Event>
-    struct Connection final: private Handler<Event>::connection_type {
+    struct connection final: private event_handler<Event>::connection_type {
         /** @brief Event emitters are friend classes of connections. */
-        friend class Emitter;
+        friend class emitter;
 
         /*! @brief Default constructor. */
-        Connection() ENTT_NOEXCEPT = default;
+        connection() ENTT_NOEXCEPT = default;
 
         /**
          * @brief Creates a connection that wraps its underlying instance.
          * @param conn A connection object to wrap.
          */
-        Connection(typename Handler<Event>::connection_type conn)
-            : Handler<Event>::connection_type{std::move(conn)}
+        connection(typename event_handler<Event>::connection_type conn)
+            : event_handler<Event>::connection_type{std::move(conn)}
         {}
 
         /*! @brief Default copy constructor. */
-        Connection(const Connection &) = default;
+        connection(const connection &) = default;
         /*! @brief Default move constructor. */
-        Connection(Connection &&) = default;
+        connection(connection &&) = default;
 
         /**
          * @brief Default copy assignment operator.
          * @return This connection.
          */
-        Connection & operator=(const Connection &) = default;
+        connection & operator=(const connection &) = default;
 
         /**
          * @brief Default move assignment operator.
          * @return This connection.
          */
-        Connection & operator=(Connection &&) = default;
+        connection & operator=(connection &&) = default;
     };
 
     /*! @brief Default constructor. */
-    Emitter() ENTT_NOEXCEPT = default;
+    emitter() ENTT_NOEXCEPT = default;
 
     /*! @brief Default destructor. */
-    virtual ~Emitter() ENTT_NOEXCEPT {
-        static_assert(std::is_base_of<Emitter<Derived>, Derived>::value, "!");
+    virtual ~emitter() ENTT_NOEXCEPT {
+        static_assert(std::is_base_of_v<emitter<Derived>, Derived>);
     }
 
     /*! @brief Copying an emitter isn't allowed. */
-    Emitter(const Emitter &) = delete;
+    emitter(const emitter &) = delete;
     /*! @brief Default move constructor. */
-    Emitter(Emitter &&) = default;
+    emitter(emitter &&) = default;
 
     /*! @brief Copying an emitter isn't allowed. @return This emitter. */
-    Emitter & operator=(const Emitter &) = delete;
+    emitter & operator=(const emitter &) = delete;
     /*! @brief Default move assignment operator. @return This emitter. */
-    Emitter & operator=(Emitter &&) = default;
+    emitter & operator=(emitter &&) = default;
 
     /**
      * @brief Emits the given event.
@@ -233,7 +233,7 @@ public:
      * @return Connection object that can be used to disconnect the listener.
      */
     template<typename Event>
-    Connection<Event> on(Listener<Event> listener) {
+    connection<Event> on(listener<Event> listener) {
         return handler<Event>().on(std::move(listener));
     }
 
@@ -258,7 +258,7 @@ public:
      * @return Connection object that can be used to disconnect the listener.
      */
     template<typename Event>
-    Connection<Event> once(Listener<Event> listener) {
+    connection<Event> once(listener<Event> listener) {
         return handler<Event>().once(std::move(listener));
     }
 
@@ -272,7 +272,7 @@ public:
      * @param conn A valid connection.
      */
     template<typename Event>
-    void erase(Connection<Event> conn) ENTT_NOEXCEPT {
+    void erase(connection<Event> conn) ENTT_NOEXCEPT {
         handler<Event>().erase(std::move(conn));
     }
 
@@ -308,11 +308,11 @@ public:
      */
     template<typename Event>
     bool empty() const ENTT_NOEXCEPT {
-        const std::size_t family = handler_family::type<Event>();
+        const std::size_t family = handler_family::type<Event>;
 
         return (!(family < handlers.size()) ||
                 !handlers[family] ||
-                static_cast<Handler<Event> &>(*handlers[family]).empty());
+                static_cast<event_handler<Event> &>(*handlers[family]).empty());
     }
 
     /**
@@ -326,7 +326,7 @@ public:
     }
 
 private:
-    std::vector<std::unique_ptr<BaseHandler>> handlers{};
+    std::vector<std::unique_ptr<base_handler>> handlers{};
 };
 
 

+ 69 - 110
src/entt/signal/sigh.hpp

@@ -5,7 +5,10 @@
 #include <algorithm>
 #include <utility>
 #include <vector>
+#include <functional>
+#include <type_traits>
 #include "../config/config.h"
+#include "delegate.hpp"
 
 
 namespace entt {
@@ -20,71 +23,56 @@ namespace entt {
 namespace internal {
 
 
-template<typename>
-struct sigh_traits;
-
-
-template<typename Ret, typename... Args>
-struct sigh_traits<Ret(Args...)> {
-    using proto_fn_type = Ret(void *, Args...);
-    using call_type = std::pair<void *, proto_fn_type *>;
-};
-
-
 template<typename, typename>
-struct Invoker;
+struct invoker;
 
 
 template<typename Ret, typename... Args, typename Collector>
-struct Invoker<Ret(Args...), Collector> {
-    using proto_fn_type = typename sigh_traits<Ret(Args...)>::proto_fn_type;
+struct invoker<Ret(Args...), Collector> {
+    virtual ~invoker() = default;
 
-    virtual ~Invoker() = default;
-
-    bool invoke(Collector &collector, proto_fn_type *proto, void *instance, Args... args) const {
-        return collector(proto(instance, args...));
+    bool invoke(Collector &collector, const delegate<Ret(Args...)> &delegate, Args... args) const {
+        return collector(delegate(args...));
     }
 };
 
 
 template<typename... Args, typename Collector>
-struct Invoker<void(Args...), Collector> {
-    using proto_fn_type = typename sigh_traits<void(Args...)>::proto_fn_type;
-
-    virtual ~Invoker() = default;
+struct invoker<void(Args...), Collector> {
+    virtual ~invoker() = default;
 
-    bool invoke(Collector &, proto_fn_type *proto, void *instance, Args... args) const {
-        return (proto(instance, args...), true);
+    bool invoke(Collector &, const delegate<void(Args...)> &delegate, Args... args) const {
+        return (delegate(args...), true);
     }
 };
 
 
 template<typename Ret>
-struct NullCollector final {
+struct null_collector final {
     using result_type = Ret;
     bool operator()(result_type) const ENTT_NOEXCEPT { return true; }
 };
 
 
 template<>
-struct NullCollector<void> final {
+struct null_collector<void> final {
     using result_type = void;
     bool operator()() const ENTT_NOEXCEPT { return true; }
 };
 
 
 template<typename>
-struct DefaultCollector;
+struct default_collector;
 
 
 template<typename Ret, typename... Args>
-struct DefaultCollector<Ret(Args...)> final {
-    using collector_type = NullCollector<Ret>;
+struct default_collector<Ret(Args...)> final {
+    using collector_type = null_collector<Ret>;
 };
 
 
 template<typename Function>
-using DefaultCollectorType = typename DefaultCollector<Function>::collector_type;
+using default_collector_type = typename default_collector<Function>::collector_type;
 
 
 }
@@ -105,7 +93,7 @@ using DefaultCollectorType = typename DefaultCollector<Function>::collector_type
  * @tparam Function A valid function type.
  */
 template<typename Function>
-class Sink;
+class sink;
 
 
 /**
@@ -117,8 +105,8 @@ class Sink;
  * @tparam Function A valid function type.
  * @tparam Collector Type of collector to use, if any.
  */
-template<typename Function, typename Collector = internal::DefaultCollectorType<Function>>
-class SigH;
+template<typename Function, typename Collector = internal::default_collector_type<Function>>
+struct sigh;
 
 
 /**
@@ -128,37 +116,20 @@ class SigH;
  * The function type for a listener is the one of the signal to which it
  * belongs.
  *
- * The clear separation between a signal and a sink permits to store the
- * former as private data member without exposing the publish functionality
- * to the users of a class.
+ * The clear separation between a signal and a sink permits to store the former
+ * as private data member without exposing the publish functionality to the
+ * users of a class.
  *
  * @tparam Ret Return type of a function type.
  * @tparam Args Types of arguments of a function type.
  */
 template<typename Ret, typename... Args>
-class Sink<Ret(Args...)> final {
+class sink<Ret(Args...)> final {
     /*! @brief A signal is allowed to create sinks. */
     template<typename, typename>
-    friend class SigH;
+    friend struct sigh;
 
-    using call_type = typename internal::sigh_traits<Ret(Args...)>::call_type;
-
-    template<Ret(*Function)(Args...)>
-    static Ret proto(void *, Args... args) {
-        return (Function)(args...);
-    }
-
-    template<typename Class, Ret(Class:: *Member)(Args... args) const>
-    static Ret proto(void *instance, Args... args) {
-        return (static_cast<const Class *>(instance)->*Member)(args...);
-    }
-
-    template<typename Class, Ret(Class:: *Member)(Args... args)>
-    static Ret proto(void *instance, Args... args) {
-        return (static_cast<Class *>(instance)->*Member)(args...);
-    }
-
-    Sink(std::vector<call_type> *calls) ENTT_NOEXCEPT
+    sink(std::vector<delegate<Ret(Args...)>> *calls) ENTT_NOEXCEPT
         : calls{calls}
     {}
 
@@ -166,15 +137,17 @@ public:
     /**
      * @brief Connects a free function to a signal.
      *
-     * The signal handler performs checks to avoid multiple connections for
-     * free functions.
+     * The signal handler performs checks to avoid multiple connections for free
+     * functions.
      *
      * @tparam Function A valid free function pointer.
      */
-    template<Ret(*Function)(Args...)>
+    template<auto Function>
     void connect() {
         disconnect<Function>();
-        calls->emplace_back(nullptr, &proto<Function>);
+        delegate<Ret(Args...)> delegate{};
+        delegate.template connect<Function>();
+        calls->emplace_back(std::move(delegate));
     }
 
     /**
@@ -182,71 +155,60 @@ public:
      *
      * The signal isn't responsible for the connected object. Users must
      * guarantee that the lifetime of the instance overcomes the one of the
-     * signal. On the other side, the signal handler performs checks to
-     * avoid multiple connections for the same member function of a given
-     * instance.
+     * signal. On the other side, the signal handler performs checks to avoid
+     * multiple connections for the same member function of a given instance.
      *
-     * @tparam Class Type of class to which the member function belongs.
      * @tparam Member Member function to connect to the signal.
+     * @tparam Class Type of class to which the member function belongs.
      * @param instance A valid instance of type pointer to `Class`.
      */
-    template<typename Class, Ret(Class:: *Member)(Args...) const = &Class::receive>
+    template<auto Member, typename Class>
     void connect(Class *instance) {
-        disconnect<Class, Member>(instance);
-        calls->emplace_back(instance, &proto<Class, Member>);
+        disconnect<Member>(instance);
+        delegate<Ret(Args...)> delegate{};
+        delegate.template connect<Member>(instance);
+        calls->emplace_back(std::move(delegate));
     }
 
     /**
-     * @brief Connects a member function for a given instance to a signal.
+     * @brief Connects the `receive` member function for a given instance to a
+     * signal.
      *
      * The signal isn't responsible for the connected object. Users must
      * guarantee that the lifetime of the instance overcomes the one of the
-     * signal. On the other side, the signal handler performs checks to
-     * avoid multiple connections for the same member function of a given
-     * instance.
+     * signal. On the other side, the signal handler performs checks to avoid
+     * multiple connections for the same member function of a given instance.
      *
      * @tparam Class Type of class to which the member function belongs.
-     * @tparam Member Member function to connect to the signal.
      * @param instance A valid instance of type pointer to `Class`.
      */
-    template<typename Class, Ret(Class:: *Member)(Args...) = &Class::receive>
-    void connect(Class *instance) {
-        disconnect<Class, Member>(instance);
-        calls->emplace_back(instance, &proto<Class, Member>);
+    template<typename Class>
+    inline void connect(Class *instance) {
+        connect<&Class::receive>(instance);
     }
 
     /**
      * @brief Disconnects a free function from a signal.
      * @tparam Function A valid free function pointer.
      */
-    template<Ret(*Function)(Args...)>
+    template<auto Function>
     void disconnect() {
-        call_type target{nullptr, &proto<Function>};
-        calls->erase(std::remove(calls->begin(), calls->end(), std::move(target)), calls->end());
+        delegate<Ret(Args...)> delegate{};
+        delegate.template connect<Function>();
+        calls->erase(std::remove(calls->begin(), calls->end(), std::move(delegate)), calls->end());
     }
 
     /**
      * @brief Disconnects the given member function from a signal.
-     * @tparam Class Type of class to which the member function belongs.
      * @tparam Member Member function to connect to the signal.
-     * @param instance A valid instance of type pointer to `Class`.
-     */
-    template<typename Class, Ret(Class:: *Member)(Args...) const>
-    void disconnect(Class *instance) {
-        call_type target{instance, &proto<Class, Member>};
-        calls->erase(std::remove(calls->begin(), calls->end(), std::move(target)), calls->end());
-    }
-
-    /**
-     * @brief Disconnects the given member function from a signal.
      * @tparam Class Type of class to which the member function belongs.
-     * @tparam Member Member function to connect to the signal.
      * @param instance A valid instance of type pointer to `Class`.
      */
-    template<typename Class, Ret(Class:: *Member)(Args...)>
+    template<auto Member, typename Class>
     void disconnect(Class *instance) {
-        call_type target{instance, &proto<Class, Member>};
-        calls->erase(std::remove(calls->begin(), calls->end(), std::move(target)), calls->end());
+        delegate<Ret(Args...)> delegate{};
+        delegate.template connect<Member>(instance);
+        calls->erase(std::remove(calls->begin(), calls->end(), std::move(delegate)), calls->end());
     }
 
     /**
@@ -256,7 +218,7 @@ public:
      */
     template<typename Class>
     void disconnect(Class *instance) {
-        auto func = [instance](const call_type &call) { return call.first == instance; };
+        auto func = [instance](const auto &delegate) { return delegate.instance() == instance; };
         calls->erase(std::remove_if(calls->begin(), calls->end(), std::move(func)), calls->end());
     }
 
@@ -268,7 +230,7 @@ public:
     }
 
 private:
-    std::vector<call_type> *calls;
+    std::vector<delegate<Ret(Args...)>> *calls;
 };
 
 
@@ -296,16 +258,13 @@ private:
  * @tparam Collector Type of collector to use, if any.
  */
 template<typename Ret, typename... Args, typename Collector>
-class SigH<Ret(Args...), Collector> final: private internal::Invoker<Ret(Args...), Collector> {
-    using call_type = typename internal::sigh_traits<Ret(Args...)>::call_type;
-
-public:
+struct sigh<Ret(Args...), Collector> final: private internal::invoker<Ret(Args...), Collector> {
     /*! @brief Unsigned integer type. */
-    using size_type = typename std::vector<call_type>::size_type;
+    using size_type = typename std::vector<delegate<Ret(Args...)>>::size_type;
     /*! @brief Collector type. */
     using collector_type = Collector;
     /*! @brief Sink type. */
-    using sink_type = Sink<Ret(Args...)>;
+    using sink_type = entt::sink<Ret(Args...)>;
 
     /**
      * @brief Instance type when it comes to connecting member functions.
@@ -353,7 +312,7 @@ public:
     void publish(Args... args) const {
         for(auto pos = calls.size(); pos; --pos) {
             auto &call = calls[pos-1];
-            call.second(call.first, args...);
+            call(args...);
         }
     }
 
@@ -366,7 +325,7 @@ public:
         collector_type collector;
 
         for(auto &&call: calls) {
-            if(!this->invoke(collector, call.second, call.first, args...)) {
+            if(!this->invoke(collector, call, args...)) {
                 break;
             }
         }
@@ -379,7 +338,7 @@ public:
      * @param lhs A valid signal object.
      * @param rhs A valid signal object.
      */
-    friend void swap(SigH &lhs, SigH &rhs) {
+    friend void swap(sigh &lhs, sigh &rhs) {
         using std::swap;
         swap(lhs.calls, rhs.calls);
     }
@@ -393,20 +352,20 @@ public:
      * @param other Signal with which to compare.
      * @return True if the two signals are identical, false otherwise.
      */
-    bool operator==(const SigH &other) const ENTT_NOEXCEPT {
+    bool operator==(const sigh &other) const ENTT_NOEXCEPT {
         return std::equal(calls.cbegin(), calls.cend(), other.calls.cbegin(), other.calls.cend());
     }
 
 private:
-    std::vector<call_type> calls;
+    std::vector<delegate<Ret(Args...)>> calls;
 };
 
 
 /**
  * @brief Checks if the contents of the two signals are different.
  *
- * Two signals are identical if they have the same size and the same
- * listeners registered exactly in the same order.
+ * Two signals are identical if they have the same size and the same listeners
+ * registered exactly in the same order.
  *
  * @tparam Ret Return type of a function type.
  * @tparam Args Types of arguments of a function type.
@@ -415,7 +374,7 @@ private:
  * @return True if the two signals are different, false otherwise.
  */
 template<typename Ret, typename... Args>
-bool operator!=(const SigH<Ret(Args...)> &lhs, const SigH<Ret(Args...)> &rhs) ENTT_NOEXCEPT {
+bool operator!=(const sigh<Ret(Args...)> &lhs, const sigh<Ret(Args...)> &rhs) ENTT_NOEXCEPT {
     return !(lhs == rhs);
 }
 

+ 0 - 1
test/CMakeLists.txt

@@ -67,7 +67,6 @@ SETUP_AND_ADD_TEST(monostate entt/core/monostate.cpp)
 # Test entity
 
 SETUP_AND_ADD_TEST(actor entt/entity/actor.cpp)
-SETUP_AND_ADD_TEST(attachee entt/entity/attachee.cpp)
 SETUP_AND_ADD_TEST(entity entt/entity/entity.cpp)
 SETUP_AND_ADD_TEST(helper entt/entity/helper.cpp)
 SETUP_AND_ADD_TEST(prototype entt/entity/prototype.cpp)

File diff suppressed because it is too large
+ 342 - 370
test/benchmark/benchmark.cpp


+ 3 - 3
test/entt/core/algorithm.cpp

@@ -5,7 +5,7 @@
 TEST(Algorithm, StdSort) {
     // well, I'm pretty sure it works, it's std::sort!!
     std::array<int, 5> arr{{4, 1, 3, 2, 0}};
-    entt::StdSort sort;
+    entt::std_sort sort;
 
     sort(arr.begin(), arr.end());
 
@@ -16,7 +16,7 @@ TEST(Algorithm, StdSort) {
 
 TEST(Algorithm, InsertionSort) {
     std::array<int, 5> arr{{4, 1, 3, 2, 0}};
-    entt::InsertionSort sort;
+    entt::insertion_sort sort;
 
     sort(arr.begin(), arr.end());
 
@@ -27,7 +27,7 @@ TEST(Algorithm, InsertionSort) {
 
 TEST(Algorithm, OneShotBubbleSort) {
     std::array<int, 5> arr{{4, 1, 3, 2, 0}};
-    entt::OneShotBubbleSort sort;
+    entt::one_shot_bubble_sort sort;
 
     sort(arr.begin(), arr.end());
     sort(arr.begin(), arr.end());

+ 12 - 12
test/entt/core/family.cpp

@@ -1,22 +1,22 @@
 #include <gtest/gtest.h>
 #include <entt/core/family.hpp>
 
-using my_family = entt::Family<struct MyFamily>;
-using your_family = entt::Family<struct YourFamily>;
+using my_family = entt::family<struct my_family_type>;
+using your_family = entt::family<struct your_family_type>;
 
 TEST(Family, Functionalities) {
-    auto myFamilyType = my_family::type<struct MyFamilyType>();
-    auto mySameFamilyType = my_family::type<struct MyFamilyType>();
-    auto myOtherFamilyType = my_family::type<struct MyOtherFamilyType>();
-    auto yourFamilyType = your_family::type<struct YourFamilyType>();
+    auto a_family_type = my_family::type<struct family_type_a>;
+    auto same_family_type = my_family::type<struct family_type_a>;
+    auto another_family_type = my_family::type<struct family_type_b>;
+    auto your_family_type = your_family::type<struct family_type_c>;
 
-    ASSERT_EQ(myFamilyType, mySameFamilyType);
-    ASSERT_NE(myFamilyType, myOtherFamilyType);
-    ASSERT_EQ(myFamilyType, yourFamilyType);
+    ASSERT_EQ(a_family_type, same_family_type);
+    ASSERT_NE(a_family_type, another_family_type);
+    ASSERT_EQ(a_family_type, your_family_type);
 }
 
 TEST(Family, Uniqueness) {
-    ASSERT_EQ(my_family::type<int>(), my_family::type<int &>());
-    ASSERT_EQ(my_family::type<int>(), my_family::type<int &&>());
-    ASSERT_EQ(my_family::type<int>(), my_family::type<const int &>());
+    ASSERT_EQ(my_family::type<int>, my_family::type<int &>);
+    ASSERT_EQ(my_family::type<int>, my_family::type<int &&>);
+    ASSERT_EQ(my_family::type<int>, my_family::type<const int &>);
 }

+ 16 - 13
test/entt/core/hashed_string.cpp

@@ -3,32 +3,35 @@
 #include <entt/core/hashed_string.hpp>
 
 TEST(HashedString, Functionalities) {
-    using hash_type = entt::HashedString::hash_type;
+    using hash_type = entt::hashed_string::hash_type;
 
     const char *bar = "bar";
 
-    auto fooHs = entt::HashedString{"foo"};
-    auto barHs = entt::HashedString{bar};
+    auto foo_hs = entt::hashed_string{"foo"};
+    auto bar_hs = entt::hashed_string{bar};
 
-    ASSERT_NE(static_cast<hash_type>(fooHs), static_cast<hash_type>(barHs));
-    ASSERT_STREQ(static_cast<const char *>(fooHs), "foo");
-    ASSERT_STREQ(static_cast<const char *>(barHs), bar);
+    ASSERT_NE(static_cast<hash_type>(foo_hs), static_cast<hash_type>(bar_hs));
+    ASSERT_STREQ(static_cast<const char *>(foo_hs), "foo");
+    ASSERT_STREQ(static_cast<const char *>(bar_hs), bar);
+    ASSERT_STREQ(foo_hs.data(), "foo");
+    ASSERT_STREQ(bar_hs.data(), bar);
 
-    ASSERT_EQ(fooHs, fooHs);
-    ASSERT_NE(fooHs, barHs);
+    ASSERT_EQ(foo_hs, foo_hs);
+    ASSERT_NE(foo_hs, bar_hs);
 
-    entt::HashedString hs{"foobar"};
+    entt::hashed_string hs{"foobar"};
 
     ASSERT_EQ(static_cast<hash_type>(hs), 0x85944171f73967e8);
+    ASSERT_EQ(hs.value(), 0x85944171f73967e8);
 
-    ASSERT_EQ(fooHs, "foo"_hs);
-    ASSERT_NE(barHs, "foo"_hs);
+    ASSERT_EQ(foo_hs, "foo"_hs);
+    ASSERT_NE(bar_hs, "foo"_hs);
 }
 
 TEST(HashedString, Constexprness) {
-    using hash_type = entt::HashedString::hash_type;
+    using hash_type = entt::hashed_string::hash_type;
     // how would you test a constexpr otherwise?
-    (void)std::integral_constant<hash_type, entt::HashedString{"quux"}>{};
+    (void)std::integral_constant<hash_type, entt::hashed_string{"quux"}>{};
     (void)std::integral_constant<hash_type, "quux"_hs>{};
     ASSERT_TRUE(true);
 }

+ 15 - 15
test/entt/core/ident.cpp

@@ -2,31 +2,31 @@
 #include <gtest/gtest.h>
 #include <entt/core/ident.hpp>
 
-struct AType {};
-struct AnotherType {};
+struct a_type {};
+struct another_type {};
 
 TEST(Identifier, Uniqueness) {
-    using ID = entt::Identifier<AType, AnotherType>;
-    constexpr AType anInstance;
-    constexpr AnotherType anotherInstance;
+    using id = entt::identifier<a_type, another_type>;
+    constexpr a_type an_instance;
+    constexpr another_type another_instance;
 
-    ASSERT_NE(ID::get<AType>(), ID::get<AnotherType>());
-    ASSERT_EQ(ID::get<AType>(), ID::get<decltype(anInstance)>());
-    ASSERT_NE(ID::get<AType>(), ID::get<decltype(anotherInstance)>());
-    ASSERT_EQ(ID::get<AType>(), ID::get<AType>());
-    ASSERT_EQ(ID::get<AnotherType>(), ID::get<AnotherType>());
+    ASSERT_NE(id::type<a_type>, id::type<another_type>);
+    ASSERT_EQ(id::type<a_type>, id::type<decltype(an_instance)>);
+    ASSERT_NE(id::type<a_type>, id::type<decltype(another_instance)>);
+    ASSERT_EQ(id::type<a_type>, id::type<a_type>);
+    ASSERT_EQ(id::type<another_type>, id::type<another_type>);
 
     // test uses in constant expressions
-    switch(ID::get<AnotherType>()) {
-    case ID::get<AType>():
+    switch(id::type<another_type>) {
+    case id::type<a_type>:
         FAIL();
-    case ID::get<AnotherType>():
+    case id::type<another_type>:
         SUCCEED();
     }
 }
 
 TEST(Identifier, SingleType) {
-    using ID = entt::Identifier<AType>;
-    std::integral_constant<ID::identifier_type, ID::get<AType>()> ic;
+    using id = entt::identifier<a_type>;
+    std::integral_constant<id::identifier_type, id::type<a_type>> ic;
     (void)ic;
 }

+ 10 - 10
test/entt/core/monostate.cpp

@@ -3,18 +3,18 @@
 #include <entt/core/monostate.hpp>
 
 TEST(Monostate, Functionalities) {
-    const bool bPre = entt::Monostate<entt::HashedString{"foobar"}>{};
-    const int iPre = entt::Monostate<"foobar"_hs>{};
+    const bool b_pre = entt::monostate<entt::hashed_string{"foobar"}>{};
+    const int i_pre = entt::monostate<"foobar"_hs>{};
 
-    ASSERT_FALSE(bPre);
-    ASSERT_EQ(iPre, int{});
+    ASSERT_FALSE(b_pre);
+    ASSERT_EQ(i_pre, int{});
 
-    entt::Monostate<"foobar"_hs>{} = true;
-    entt::Monostate<"foobar"_hs>{} = 42;
+    entt::monostate<"foobar"_hs>{} = true;
+    entt::monostate<"foobar"_hs>{} = 42;
 
-    const bool &bPost = entt::Monostate<"foobar"_hs>{};
-    const int &iPost = entt::Monostate<entt::HashedString{"foobar"}>{};
+    const bool &b_post = entt::monostate<"foobar"_hs>{};
+    const int &i_post = entt::monostate<entt::hashed_string{"foobar"}>{};
 
-    ASSERT_TRUE(bPost);
-    ASSERT_EQ(iPost, 42);
+    ASSERT_TRUE(b_post);
+    ASSERT_EQ(i_post, 42);
 }

+ 20 - 46
test/entt/entity/actor.cpp

@@ -3,66 +3,40 @@
 #include <entt/entity/actor.hpp>
 #include <entt/entity/registry.hpp>
 
-struct ActorComponent final {};
-struct ActorTag final {};
+struct actor_component final {};
 
 TEST(Actor, Component) {
-    entt::DefaultRegistry registry;
-    entt::DefaultActor actor{registry};
+    entt::registry<> registry;
+    entt::actor actor{registry};
     const auto &cactor = actor;
 
-    ASSERT_EQ(&registry, &actor.registry());
-    ASSERT_EQ(&registry, &cactor.registry());
-    ASSERT_TRUE(registry.empty<ActorComponent>());
+    ASSERT_EQ(&registry, &actor.backend());
+    ASSERT_EQ(&registry, &cactor.backend());
+    ASSERT_TRUE(registry.empty<actor_component>());
     ASSERT_FALSE(registry.empty());
-    ASSERT_FALSE(actor.has<ActorComponent>());
+    ASSERT_FALSE(actor.has<actor_component>());
 
-    const auto &component = actor.assign<ActorComponent>();
+    const auto &component = actor.assign<actor_component>();
 
-    ASSERT_EQ(&component, &actor.get<ActorComponent>());
-    ASSERT_EQ(&component, &cactor.get<ActorComponent>());
-    ASSERT_FALSE(registry.empty<ActorComponent>());
+    ASSERT_EQ(&component, &actor.get<actor_component>());
+    ASSERT_EQ(&component, &cactor.get<actor_component>());
+    ASSERT_FALSE(registry.empty<actor_component>());
     ASSERT_FALSE(registry.empty());
-    ASSERT_TRUE(actor.has<ActorComponent>());
+    ASSERT_TRUE(actor.has<actor_component>());
 
-    actor.remove<ActorComponent>();
+    actor.remove<actor_component>();
 
-    ASSERT_TRUE(registry.empty<ActorComponent>());
+    ASSERT_TRUE(registry.empty<actor_component>());
     ASSERT_FALSE(registry.empty());
-    ASSERT_FALSE(actor.has<ActorComponent>());
-}
-
-TEST(Actor, Tag) {
-    entt::DefaultRegistry registry;
-    entt::DefaultActor actor{registry};
-    const auto &cactor = actor;
-
-    ASSERT_EQ(&registry, &actor.registry());
-    ASSERT_EQ(&registry, &cactor.registry());
-    ASSERT_FALSE(registry.has<ActorTag>());
-    ASSERT_FALSE(actor.has<ActorTag>(entt::tag_t{}));
-
-    const auto &tag = actor.assign<ActorTag>(entt::tag_t{});
-
-    ASSERT_EQ(&tag, &actor.get<ActorTag>(entt::tag_t{}));
-    ASSERT_EQ(&tag, &cactor.get<ActorTag>(entt::tag_t{}));
-    ASSERT_TRUE(registry.has<ActorTag>());
-    ASSERT_FALSE(registry.empty());
-    ASSERT_TRUE(actor.has<ActorTag>(entt::tag_t{}));
-
-    actor.remove<ActorTag>(entt::tag_t{});
-
-    ASSERT_FALSE(registry.has<ActorTag>());
-    ASSERT_FALSE(registry.empty());
-    ASSERT_FALSE(actor.has<ActorTag>(entt::tag_t{}));
+    ASSERT_FALSE(actor.has<actor_component>());
 }
 
 TEST(Actor, EntityLifetime) {
-    entt::DefaultRegistry registry;
-    auto *actor = new entt::DefaultActor{registry};
-    actor->assign<ActorComponent>();
+    entt::registry<> registry;
+    auto *actor = new entt::actor{registry};
+    actor->assign<actor_component>();
 
-    ASSERT_FALSE(registry.empty<ActorComponent>());
+    ASSERT_FALSE(registry.empty<actor_component>());
     ASSERT_FALSE(registry.empty());
 
     registry.each([actor](const auto entity) {
@@ -71,6 +45,6 @@ TEST(Actor, EntityLifetime) {
 
     delete actor;
 
-    ASSERT_TRUE(registry.empty<ActorComponent>());
+    ASSERT_TRUE(registry.empty<actor_component>());
     ASSERT_TRUE(registry.empty());
 }

+ 0 - 69
test/entt/entity/attachee.cpp

@@ -1,69 +0,0 @@
-#include <unordered_set>
-#include <gtest/gtest.h>
-#include <entt/entity/attachee.hpp>
-
-TEST(AttacheeNoType, Functionalities) {
-    entt::Attachee<std::uint64_t> attachee;
-
-    attachee.construct(42u);
-
-    ASSERT_EQ(attachee.get(), 42u);
-
-    attachee.destroy();
-
-    ASSERT_NE(attachee.get(), 42u);
-
-    (void)entt::Attachee<std::uint64_t>{std::move(attachee)};
-    entt::Attachee<std::uint64_t> other;
-    other = std::move(attachee);
-}
-
-TEST(AttacheeWithType, Functionalities) {
-    entt::Attachee<std::uint64_t, int> attachee;
-    const auto &cattachee = attachee;
-
-    attachee.construct(42u, 3);
-
-    ASSERT_EQ(attachee.get(), 3);
-    ASSERT_EQ(cattachee.get(), 3);
-    ASSERT_EQ(attachee.Attachee<std::uint64_t>::get(), 42u);
-
-    attachee.move(0u);
-
-    ASSERT_EQ(attachee.get(), 3);
-    ASSERT_EQ(cattachee.get(), 3);
-    ASSERT_EQ(attachee.Attachee<std::uint64_t>::get(), 0u);
-
-    attachee.destroy();
-
-    ASSERT_NE(attachee.Attachee<std::uint64_t>::get(), 0u);
-    ASSERT_NE(attachee.Attachee<std::uint64_t>::get(), 42u);
-}
-
-TEST(AttacheeWithType, AggregatesMustWork) {
-    struct AggregateType { int value; };
-    // the goal of this test is to enforce the requirements for aggregate types
-    entt::Attachee<std::uint64_t, AggregateType>{}.construct(0, 42);
-}
-
-TEST(AttacheeWithType, TypesFromStandardTemplateLibraryMustWork) {
-    // see #37 - this test shouldn't crash, that's all
-    entt::Attachee<std::uint64_t, std::unordered_set<int>> attachee;
-    attachee.construct(0).insert(42);
-    attachee.destroy();
-}
-
-TEST(AttacheeWithType, MoveOnlyComponent) {
-    struct MoveOnlyComponent {
-        MoveOnlyComponent() = default;
-        ~MoveOnlyComponent() = default;
-        MoveOnlyComponent(const MoveOnlyComponent &) = delete;
-        MoveOnlyComponent(MoveOnlyComponent &&) = default;
-        MoveOnlyComponent & operator=(const MoveOnlyComponent &) = delete;
-        MoveOnlyComponent & operator=(MoveOnlyComponent &&) = default;
-    };
-
-    // it's purpose is to ensure that move only components are always accepted
-    entt::Attachee<std::uint64_t, MoveOnlyComponent> attachee;
-    (void)attachee;
-}

+ 2 - 5
test/entt/entity/entity.cpp

@@ -3,16 +3,13 @@
 #include <entt/entity/entity.hpp>
 #include <entt/entity/registry.hpp>
 
-template<bool>
-struct S {};
-
 TEST(Traits, Null) {
-    entt::DefaultRegistry registry{};
+    entt::registry<> registry{};
 
     const auto entity = registry.create();
     registry.assign<int>(entity, 42);
 
-    ASSERT_TRUE(~typename entt::DefaultRegistry::entity_type{} == entt::null);
+    ASSERT_TRUE(~typename entt::registry<>::entity_type{} == entt::null);
 
     ASSERT_TRUE(entt::null == entt::null);
     ASSERT_FALSE(entt::null != entt::null);

+ 2 - 2
test/entt/entity/helper.cpp

@@ -4,7 +4,7 @@
 #include <entt/entity/registry.hpp>
 
 TEST(Helper, Dependency) {
-    entt::DefaultRegistry registry;
+    entt::registry<> registry;
     const auto entity = registry.create();
     entt::connect<double, float>(registry.construction<int>());
 
@@ -50,7 +50,7 @@ TEST(Helper, Dependency) {
 }
 
 TEST(Helper, Label) {
-    entt::DefaultRegistry registry;
+    entt::registry<> registry;
     const auto entity = registry.create();
     registry.assign<entt::label<"foobar"_hs>>(entity);
     registry.assign<int>(entity, 42);

+ 11 - 11
test/entt/entity/prototype.cpp

@@ -3,8 +3,8 @@
 #include <entt/entity/registry.hpp>
 
 TEST(Prototype, SameRegistry) {
-    entt::DefaultRegistry registry;
-    entt::DefaultPrototype prototype{registry};
+    entt::registry<> registry;
+    entt::prototype prototype{registry};
     const auto &cprototype = prototype;
 
     ASSERT_FALSE(registry.empty());
@@ -62,9 +62,9 @@ TEST(Prototype, SameRegistry) {
 }
 
 TEST(Prototype, OtherRegistry) {
-    entt::DefaultRegistry registry;
-    entt::DefaultRegistry repository;
-    entt::DefaultPrototype prototype{repository};
+    entt::registry<> registry;
+    entt::registry<> repository;
+    entt::prototype prototype{repository};
     const auto &cprototype = prototype;
 
     ASSERT_TRUE(registry.empty());
@@ -122,10 +122,10 @@ TEST(Prototype, OtherRegistry) {
 }
 
 TEST(Prototype, RAII) {
-    entt::DefaultRegistry registry;
+    entt::registry<> registry;
 
     {
-        entt::DefaultPrototype prototype{registry};
+        entt::prototype prototype{registry};
         prototype.set<int>(0);
 
         ASSERT_FALSE(registry.empty());
@@ -135,19 +135,19 @@ TEST(Prototype, RAII) {
 }
 
 TEST(Prototype, MoveConstructionAssignment) {
-    entt::DefaultRegistry registry;
+    entt::registry<> registry;
 
-    entt::DefaultPrototype prototype{registry};
+    entt::prototype prototype{registry};
     prototype.set<int>(0);
     auto other{std::move(prototype)};
     const auto e0 = other();
 
-    ASSERT_EQ(registry.size(), entt::DefaultRegistry::size_type{2});
+    ASSERT_EQ(registry.size(), entt::registry<>::size_type{2});
     ASSERT_TRUE(registry.has<int>(e0));
 
     prototype = std::move(other);
     const auto e1 = prototype();
 
-    ASSERT_EQ(registry.size(), entt::DefaultRegistry::size_type{3});
+    ASSERT_EQ(registry.size(), entt::registry<>::size_type{3});
     ASSERT_TRUE(registry.has<int>(e1));
 }

+ 122 - 258
test/entt/entity/registry.cpp

@@ -6,70 +6,48 @@
 #include <entt/entity/entt_traits.hpp>
 #include <entt/entity/registry.hpp>
 
-struct Listener {
+struct listener {
     template<typename Component>
-    void incrComponent(entt::DefaultRegistry &registry, entt::DefaultRegistry::entity_type entity) {
+    void incr(entt::registry<> &registry, entt::registry<>::entity_type entity) {
         ASSERT_TRUE(registry.valid(entity));
         ASSERT_TRUE(registry.has<Component>(entity));
         last = entity;
         ++counter;
     }
 
-    template<typename Tag>
-    void incrTag(entt::DefaultRegistry &registry, entt::DefaultRegistry::entity_type entity) {
-        ASSERT_TRUE(registry.valid(entity));
-        ASSERT_TRUE(registry.has<Tag>());
-        ASSERT_EQ(registry.attachee<Tag>(), entity);
-        last = entity;
-        ++counter;
-    }
-
     template<typename Component>
-    void decrComponent(entt::DefaultRegistry &registry, entt::DefaultRegistry::entity_type entity) {
+    void decr(entt::registry<> &registry, entt::registry<>::entity_type entity) {
         ASSERT_TRUE(registry.valid(entity));
         ASSERT_TRUE(registry.has<Component>(entity));
         last = entity;
         --counter;
     }
 
-    template<typename Tag>
-    void decrTag(entt::DefaultRegistry &registry, entt::DefaultRegistry::entity_type entity) {
-        ASSERT_TRUE(registry.valid(entity));
-        ASSERT_TRUE(registry.has<Tag>());
-        ASSERT_EQ(registry.attachee<Tag>(), entity);
-        last = entity;
-        --counter;
-    }
-
-    entt::DefaultRegistry::entity_type last;
+    entt::registry<>::entity_type last;
     int counter{0};
 };
 
-TEST(DefaultRegistry, Types) {
-    entt::DefaultRegistry registry;
-
-    ASSERT_EQ(registry.type<int>(entt::tag_t{}), registry.type<int>(entt::tag_t{}));
+TEST(Registry, Types) {
+    entt::registry<> registry;
     ASSERT_EQ(registry.type<int>(), registry.type<int>());
-
-    ASSERT_NE(registry.type<int>(entt::tag_t{}), registry.type<double>(entt::tag_t{}));
-    ASSERT_NE(registry.type<int>(), registry.type<double>(entt::tag_t{}));
+    ASSERT_NE(registry.type<double>(), registry.type<int>());
 }
 
-TEST(DefaultRegistry, Functionalities) {
-    entt::DefaultRegistry registry;
+TEST(Registry, Functionalities) {
+    entt::registry<> registry;
 
-    ASSERT_EQ(registry.size(), entt::DefaultRegistry::size_type{0});
-    ASSERT_EQ(registry.alive(), entt::DefaultRegistry::size_type{0});
+    ASSERT_EQ(registry.size(), entt::registry<>::size_type{0});
+    ASSERT_EQ(registry.alive(), entt::registry<>::size_type{0});
     ASSERT_NO_THROW(registry.reserve(42));
     ASSERT_NO_THROW(registry.reserve<int>(8));
     ASSERT_NO_THROW(registry.reserve<char>(8));
     ASSERT_TRUE(registry.empty());
 
-    ASSERT_EQ(registry.capacity(), entt::DefaultRegistry::size_type{42});
-    ASSERT_EQ(registry.capacity<int>(), entt::DefaultRegistry::size_type{8});
-    ASSERT_EQ(registry.capacity<char>(), entt::DefaultRegistry::size_type{8});
-    ASSERT_EQ(registry.size<int>(), entt::DefaultRegistry::size_type{0});
-    ASSERT_EQ(registry.size<char>(), entt::DefaultRegistry::size_type{0});
+    ASSERT_EQ(registry.capacity(), entt::registry<>::size_type{42});
+    ASSERT_EQ(registry.capacity<int>(), entt::registry<>::size_type{8});
+    ASSERT_EQ(registry.capacity<char>(), entt::registry<>::size_type{8});
+    ASSERT_EQ(registry.size<int>(), entt::registry<>::size_type{0});
+    ASSERT_EQ(registry.size<char>(), entt::registry<>::size_type{0});
     ASSERT_TRUE(registry.empty<int>());
     ASSERT_TRUE(registry.empty<char>());
 
@@ -82,8 +60,8 @@ TEST(DefaultRegistry, Functionalities) {
     ASSERT_TRUE(registry.has<>(e0));
     ASSERT_TRUE(registry.has<>(e1));
 
-    ASSERT_EQ(registry.size<int>(), entt::DefaultRegistry::size_type{1});
-    ASSERT_EQ(registry.size<char>(), entt::DefaultRegistry::size_type{1});
+    ASSERT_EQ(registry.size<int>(), entt::registry<>::size_type{1});
+    ASSERT_EQ(registry.size<char>(), entt::registry<>::size_type{1});
     ASSERT_FALSE(registry.empty<int>());
     ASSERT_FALSE(registry.empty<char>());
 
@@ -119,7 +97,7 @@ TEST(DefaultRegistry, Functionalities) {
     ASSERT_EQ(registry.get<char>(e0), 'c');
 
     ASSERT_EQ(std::get<0>(registry.get<int, char>(e0)), 42);
-    ASSERT_EQ(std::get<1>(static_cast<const entt::DefaultRegistry &>(registry).get<int, char>(e0)), 'c');
+    ASSERT_EQ(std::get<1>(static_cast<const entt::registry<> &>(registry).get<int, char>(e0)), 'c');
 
     ASSERT_EQ(registry.get<int>(e0), registry.get<int>(e2));
     ASSERT_EQ(registry.get<char>(e0), registry.get<char>(e2));
@@ -131,18 +109,18 @@ TEST(DefaultRegistry, Functionalities) {
 
     ASSERT_NO_THROW(registry.accommodate<int>(e0, 1));
     ASSERT_NO_THROW(registry.accommodate<int>(e1, 1));
-    ASSERT_EQ(static_cast<const entt::DefaultRegistry &>(registry).get<int>(e0), 1);
-    ASSERT_EQ(static_cast<const entt::DefaultRegistry &>(registry).get<int>(e1), 1);
+    ASSERT_EQ(static_cast<const entt::registry<> &>(registry).get<int>(e0), 1);
+    ASSERT_EQ(static_cast<const entt::registry<> &>(registry).get<int>(e1), 1);
 
-    ASSERT_EQ(registry.size(), entt::DefaultRegistry::size_type{3});
-    ASSERT_EQ(registry.alive(), entt::DefaultRegistry::size_type{3});
+    ASSERT_EQ(registry.size(), entt::registry<>::size_type{3});
+    ASSERT_EQ(registry.alive(), entt::registry<>::size_type{3});
     ASSERT_FALSE(registry.empty());
 
-    ASSERT_EQ(registry.version(e2), entt::DefaultRegistry::version_type{0});
-    ASSERT_EQ(registry.current(e2), entt::DefaultRegistry::version_type{0});
+    ASSERT_EQ(registry.version(e2), entt::registry<>::version_type{0});
+    ASSERT_EQ(registry.current(e2), entt::registry<>::version_type{0});
     ASSERT_NO_THROW(registry.destroy(e2));
-    ASSERT_EQ(registry.version(e2), entt::DefaultRegistry::version_type{0});
-    ASSERT_EQ(registry.current(e2), entt::DefaultRegistry::version_type{1});
+    ASSERT_EQ(registry.version(e2), entt::registry<>::version_type{0});
+    ASSERT_EQ(registry.current(e2), entt::registry<>::version_type{1});
 
     ASSERT_TRUE(registry.valid(e0));
     ASSERT_TRUE(registry.fast(e0));
@@ -151,14 +129,14 @@ TEST(DefaultRegistry, Functionalities) {
     ASSERT_FALSE(registry.valid(e2));
     ASSERT_FALSE(registry.fast(e2));
 
-    ASSERT_EQ(registry.size(), entt::DefaultRegistry::size_type{3});
-    ASSERT_EQ(registry.alive(), entt::DefaultRegistry::size_type{2});
+    ASSERT_EQ(registry.size(), entt::registry<>::size_type{3});
+    ASSERT_EQ(registry.alive(), entt::registry<>::size_type{2});
     ASSERT_FALSE(registry.empty());
 
     ASSERT_NO_THROW(registry.reset());
 
-    ASSERT_EQ(registry.size(), entt::DefaultRegistry::size_type{3});
-    ASSERT_EQ(registry.alive(), entt::DefaultRegistry::size_type{0});
+    ASSERT_EQ(registry.size(), entt::registry<>::size_type{3});
+    ASSERT_EQ(registry.alive(), entt::registry<>::size_type{0});
     ASSERT_TRUE(registry.empty());
 
     const auto e3 = registry.create();
@@ -166,22 +144,22 @@ TEST(DefaultRegistry, Functionalities) {
     registry.assign<int>(e3);
     registry.assign<char>(e3);
 
-    ASSERT_EQ(registry.size<int>(), entt::DefaultRegistry::size_type{1});
-    ASSERT_EQ(registry.size<char>(), entt::DefaultRegistry::size_type{1});
+    ASSERT_EQ(registry.size<int>(), entt::registry<>::size_type{1});
+    ASSERT_EQ(registry.size<char>(), entt::registry<>::size_type{1});
     ASSERT_FALSE(registry.empty<int>());
     ASSERT_FALSE(registry.empty<char>());
 
     ASSERT_NO_THROW(registry.reset<int>());
 
-    ASSERT_EQ(registry.size<int>(), entt::DefaultRegistry::size_type{0});
-    ASSERT_EQ(registry.size<char>(), entt::DefaultRegistry::size_type{1});
+    ASSERT_EQ(registry.size<int>(), entt::registry<>::size_type{0});
+    ASSERT_EQ(registry.size<char>(), entt::registry<>::size_type{1});
     ASSERT_TRUE(registry.empty<int>());
     ASSERT_FALSE(registry.empty<char>());
 
     ASSERT_NO_THROW(registry.reset());
 
-    ASSERT_EQ(registry.size<int>(), entt::DefaultRegistry::size_type{0});
-    ASSERT_EQ(registry.size<char>(), entt::DefaultRegistry::size_type{0});
+    ASSERT_EQ(registry.size<int>(), entt::registry<>::size_type{0});
+    ASSERT_EQ(registry.size<char>(), entt::registry<>::size_type{0});
     ASSERT_TRUE(registry.empty<int>());
     ASSERT_TRUE(registry.empty<char>());
 
@@ -193,13 +171,13 @@ TEST(DefaultRegistry, Functionalities) {
     ASSERT_NO_THROW(registry.reset<int>(e4));
     ASSERT_NO_THROW(registry.reset<int>(e5));
 
-    ASSERT_EQ(registry.size<int>(), entt::DefaultRegistry::size_type{0});
-    ASSERT_EQ(registry.size<char>(), entt::DefaultRegistry::size_type{0});
+    ASSERT_EQ(registry.size<int>(), entt::registry<>::size_type{0});
+    ASSERT_EQ(registry.size<char>(), entt::registry<>::size_type{0});
     ASSERT_TRUE(registry.empty<int>());
 }
 
-TEST(DefaultRegistry, Identifiers) {
-    entt::DefaultRegistry registry;
+TEST(Registry, Identifiers) {
+    entt::registry<> registry;
     const auto pre = registry.create();
 
     ASSERT_EQ(pre, registry.entity(pre));
@@ -214,9 +192,9 @@ TEST(DefaultRegistry, Identifiers) {
     ASSERT_EQ(registry.version(post), registry.current(post));
 }
 
-TEST(DefaultRegistry, RawData) {
-    entt::DefaultRegistry registry;
-    const entt::DefaultRegistry &cregistry = registry;
+TEST(Registry, RawData) {
+    entt::registry<> registry;
+    const entt::registry<> &cregistry = registry;
     const auto entity = registry.create();
 
     ASSERT_EQ(registry.raw<int>(), nullptr);
@@ -234,8 +212,8 @@ TEST(DefaultRegistry, RawData) {
     ASSERT_EQ(*cregistry.data<int>(), entity);
 }
 
-TEST(DefaultRegistry, CreateDestroyCornerCase) {
-    entt::DefaultRegistry registry;
+TEST(Registry, CreateDestroyCornerCase) {
+    entt::registry<> registry;
 
     const auto e0 = registry.create();
     const auto e1 = registry.create();
@@ -245,19 +223,19 @@ TEST(DefaultRegistry, CreateDestroyCornerCase) {
 
     registry.each([](auto) { FAIL(); });
 
-    ASSERT_EQ(registry.current(e0), entt::DefaultRegistry::version_type{1});
-    ASSERT_EQ(registry.current(e1), entt::DefaultRegistry::version_type{1});
+    ASSERT_EQ(registry.current(e0), entt::registry<>::version_type{1});
+    ASSERT_EQ(registry.current(e1), entt::registry<>::version_type{1});
 }
 
-TEST(DefaultRegistry, VersionOverflow) {
-    entt::DefaultRegistry registry;
+TEST(Registry, VersionOverflow) {
+    entt::registry<> registry;
 
     const auto entity = registry.create();
     registry.destroy(entity);
 
-    ASSERT_EQ(registry.version(entity), entt::DefaultRegistry::version_type{});
+    ASSERT_EQ(registry.version(entity), entt::registry<>::version_type{});
 
-    for(auto i = entt::entt_traits<entt::DefaultRegistry::entity_type>::version_mask; i; --i) {
+    for(auto i = entt::entt_traits<entt::registry<>::entity_type>::version_mask; i; --i) {
         ASSERT_NE(registry.current(entity), registry.version(entity));
         registry.destroy(registry.create());
     }
@@ -265,10 +243,10 @@ TEST(DefaultRegistry, VersionOverflow) {
     ASSERT_EQ(registry.current(entity), registry.version(entity));
 }
 
-TEST(DefaultRegistry, Each) {
-    entt::DefaultRegistry registry;
-    entt::DefaultRegistry::size_type tot;
-    entt::DefaultRegistry::size_type match;
+TEST(Registry, Each) {
+    entt::registry<> registry;
+    entt::registry<>::size_type tot;
+    entt::registry<>::size_type match;
 
     registry.create();
     registry.assign<int>(registry.create());
@@ -318,33 +296,31 @@ TEST(DefaultRegistry, Each) {
     registry.each([&](auto) { FAIL(); });
 }
 
-TEST(DefaultRegistry, Orphans) {
-    entt::DefaultRegistry registry;
-    entt::DefaultRegistry::size_type tot{};
+TEST(Registry, Orphans) {
+    entt::registry<> registry;
+    entt::registry<>::size_type tot{};
 
     registry.assign<int>(registry.create());
     registry.create();
     registry.assign<int>(registry.create());
-    registry.create();
-    registry.assign<double>(entt::tag_t{}, registry.create());
 
     registry.orphans([&](auto) { ++tot; });
-    ASSERT_EQ(tot, 2u);
-    tot = 0u;
+    ASSERT_EQ(tot, 1u);
+    tot = {};
 
     registry.each([&](auto entity) { registry.reset<int>(entity); });
     registry.orphans([&](auto) { ++tot; });
-    ASSERT_EQ(tot, 4u);
+    ASSERT_EQ(tot, 3u);
     registry.reset();
-    tot = 0u;
+    tot = {};
 
     registry.orphans([&](auto) { ++tot; });
     ASSERT_EQ(tot, 0u);
 }
 
-TEST(DefaultRegistry, CreateDestroyEntities) {
-    entt::DefaultRegistry registry;
-    entt::DefaultRegistry::entity_type pre{}, post{};
+TEST(Registry, CreateDestroyEntities) {
+    entt::registry<> registry;
+    entt::registry<>::entity_type pre{}, post{};
 
     for(int i = 0; i < 10; ++i) {
         const auto entity = registry.create();
@@ -373,58 +349,8 @@ TEST(DefaultRegistry, CreateDestroyEntities) {
     ASSERT_EQ(registry.current(pre), registry.current(post));
 }
 
-TEST(DefaultRegistry, AttachSetRemoveTags) {
-    entt::DefaultRegistry registry;
-    const auto &cregistry = registry;
-    const typename decltype(registry)::entity_type null = entt::null;
-
-    ASSERT_FALSE(registry.has<int>());
-    ASSERT_EQ(registry.attachee<int>(), null);
-
-    const auto entity = registry.create();
-    registry.assign<int>(entt::tag_t{}, entity, 42);
-
-    ASSERT_TRUE(registry.has<int>());
-    ASSERT_TRUE(registry.has<int>(entt::tag_t{}, entity));
-    ASSERT_EQ(registry.get<int>(), 42);
-    ASSERT_EQ(cregistry.get<int>(), 42);
-    ASSERT_EQ(registry.attachee<int>(), entity);
-
-    registry.replace<int>(entt::tag_t{}, 3);
-
-    ASSERT_TRUE(registry.has<int>());
-    ASSERT_TRUE(registry.has<int>(entt::tag_t{}, entity));
-    ASSERT_EQ(registry.get<int>(), 3);
-    ASSERT_EQ(cregistry.get<int>(), 3);
-    ASSERT_EQ(registry.attachee<int>(), entity);
-
-    const auto other = registry.create();
-    registry.move<int>(other);
-
-    ASSERT_TRUE(registry.has<int>());
-    ASSERT_FALSE(registry.has<int>(entt::tag_t{}, entity));
-    ASSERT_TRUE(registry.has<int>(entt::tag_t{}, other));
-    ASSERT_EQ(registry.get<int>(), 3);
-    ASSERT_EQ(cregistry.get<int>(), 3);
-    ASSERT_EQ(registry.attachee<int>(), other);
-
-    registry.remove<int>();
-
-    ASSERT_FALSE(registry.has<int>());
-    ASSERT_FALSE(registry.has<int>(entt::tag_t{}, entity));
-    ASSERT_FALSE(registry.has<int>(entt::tag_t{}, other));
-    ASSERT_EQ(registry.attachee<int>(), null);
-
-    registry.assign<int>(entt::tag_t{}, entity, 42);
-    registry.destroy(entity);
-
-    ASSERT_FALSE(registry.has<int>());
-    ASSERT_FALSE(registry.has<int>(entt::tag_t{}, entity));
-    ASSERT_FALSE(registry.has<int>(entt::tag_t{}, other));
-}
-
-TEST(DefaultRegistry, StandardView) {
-    entt::DefaultRegistry registry;
+TEST(Registry, StandardView) {
+    entt::registry<> registry;
     auto mview = registry.view<int, char>();
     auto iview = registry.view<int>();
     auto cview = registry.view<char>();
@@ -449,20 +375,20 @@ TEST(DefaultRegistry, StandardView) {
     ASSERT_EQ(cnt, decltype(mview)::size_type{2});
 }
 
-TEST(DefaultRegistry, PersistentView) {
-    entt::DefaultRegistry registry;
-    auto view = registry.view<int, char>(entt::persistent_t{});
+TEST(Registry, PersistentView) {
+    entt::registry<> registry;
+    auto view = registry.persistent_view<int, char>();
 
-    ASSERT_TRUE((registry.contains<int, char>()));
-    ASSERT_FALSE((registry.contains<int, double>()));
+    ASSERT_TRUE((registry.has_persistent_view<int, char>()));
+    ASSERT_FALSE((registry.has_persistent_view<int, double>()));
 
-    registry.prepare<int, double>();
+    registry.prepare_persistent_view<int, double>();
 
-    ASSERT_TRUE((registry.contains<int, double>()));
+    ASSERT_TRUE((registry.has_persistent_view<int, double>()));
 
-    registry.discard<int, double>();
+    registry.discard_persistent_view<int, double>();
 
-    ASSERT_FALSE((registry.contains<int, double>()));
+    ASSERT_FALSE((registry.has_persistent_view<int, double>()));
 
     const auto e0 = registry.create();
     registry.assign<int>(e0, 0);
@@ -481,9 +407,9 @@ TEST(DefaultRegistry, PersistentView) {
     ASSERT_EQ(cnt, decltype(view)::size_type{2});
 }
 
-TEST(DefaultRegistry, RawView) {
-    entt::DefaultRegistry registry;
-    auto view = registry.view<int>(entt::raw_t{});
+TEST(Registry, RawView) {
+    entt::registry<> registry;
+    auto view = registry.raw_view<int>();
 
     const auto e0 = registry.create();
     registry.assign<int>(e0, 0);
@@ -499,59 +425,47 @@ TEST(DefaultRegistry, RawView) {
     ASSERT_EQ(cnt, decltype(view)::size_type{2});
 }
 
-TEST(DefaultRegistry, CleanStandardViewAfterReset) {
-    entt::DefaultRegistry registry;
+TEST(Registry, CleanStandardViewAfterReset) {
+    entt::registry<> registry;
     auto view = registry.view<int>();
     registry.assign<int>(registry.create(), 0);
 
-    ASSERT_EQ(view.size(), entt::DefaultRegistry::size_type{1});
+    ASSERT_EQ(view.size(), entt::registry<>::size_type{1});
 
     registry.reset();
 
-    ASSERT_EQ(view.size(), entt::DefaultRegistry::size_type{0});
+    ASSERT_EQ(view.size(), entt::registry<>::size_type{0});
 }
 
-TEST(DefaultRegistry, CleanPersistentViewAfterReset) {
-    entt::DefaultRegistry registry;
-    auto view = registry.view<int, char>(entt::persistent_t{});
+TEST(Registry, CleanPersistentViewAfterReset) {
+    entt::registry<> registry;
+    auto view = registry.persistent_view<int, char>();
 
     const auto entity = registry.create();
     registry.assign<int>(entity, 0);
     registry.assign<char>(entity, 'c');
 
-    ASSERT_EQ(view.size(), entt::DefaultRegistry::size_type{1});
+    ASSERT_EQ(view.size(), entt::registry<>::size_type{1});
 
     registry.reset();
 
-    ASSERT_EQ(view.size(), entt::DefaultRegistry::size_type{0});
+    ASSERT_EQ(view.size(), entt::registry<>::size_type{0});
 }
 
-TEST(DefaultRegistry, CleanRawViewAfterReset) {
-    entt::DefaultRegistry registry;
-    auto view = registry.view<int>(entt::raw_t{});
+TEST(Registry, CleanRawViewAfterReset) {
+    entt::registry<> registry;
+    auto view = registry.raw_view<int>();
     registry.assign<int>(registry.create(), 0);
 
-    ASSERT_EQ(view.size(), entt::DefaultRegistry::size_type{1});
+    ASSERT_EQ(view.size(), entt::registry<>::size_type{1});
 
     registry.reset();
 
-    ASSERT_EQ(view.size(), entt::DefaultRegistry::size_type{0});
+    ASSERT_EQ(view.size(), entt::registry<>::size_type{0});
 }
 
-TEST(DefaultRegistry, CleanTagsAfterReset) {
-    entt::DefaultRegistry registry;
-    const auto entity = registry.create();
-    registry.assign<int>(entt::tag_t{}, entity);
-
-    ASSERT_TRUE(registry.has<int>());
-
-    registry.reset();
-
-    ASSERT_FALSE(registry.has<int>());
-}
-
-TEST(DefaultRegistry, SortSingle) {
-    entt::DefaultRegistry registry;
+TEST(Registry, SortSingle) {
+    entt::registry<> registry;
 
     int val = 0;
 
@@ -570,8 +484,8 @@ TEST(DefaultRegistry, SortSingle) {
     }
 }
 
-TEST(DefaultRegistry, SortMulti) {
-    entt::DefaultRegistry registry;
+TEST(Registry, SortMulti) {
+    entt::registry<> registry;
 
     unsigned int uval = 0u;
     int ival = 0;
@@ -602,26 +516,26 @@ TEST(DefaultRegistry, SortMulti) {
     }
 }
 
-TEST(DefaultRegistry, ComponentsWithTypesFromStandardTemplateLibrary) {
+TEST(Registry, ComponentsWithTypesFromStandardTemplateLibrary) {
     // see #37 - the test shouldn't crash, that's all
-    entt::DefaultRegistry registry;
+    entt::registry<> registry;
     const auto entity = registry.create();
     registry.assign<std::unordered_set<int>>(entity).insert(42);
     registry.destroy(entity);
 }
 
-TEST(DefaultRegistry, ConstructWithComponents) {
+TEST(Registry, ConstructWithComponents) {
     // it should compile, that's all
-    entt::DefaultRegistry registry;
+    entt::registry<> registry;
     const auto value = 0;
     registry.assign<int>(registry.create(), value);
 }
 
-TEST(DefaultRegistry, MergeTwoRegistries) {
-    using entity_type = entt::DefaultRegistry::entity_type;
+TEST(Registry, MergeTwoRegistries) {
+    using entity_type = entt::registry<>::entity_type;
 
-    entt::DefaultRegistry src;
-    entt::DefaultRegistry dst;
+    entt::registry<> src;
+    entt::registry<> dst;
 
     std::unordered_map<entity_type, entity_type> ref;
 
@@ -672,12 +586,12 @@ TEST(DefaultRegistry, MergeTwoRegistries) {
     ne(dst.view<char, float, int>().begin(), dst.view<char, float, int>().end());
 }
 
-TEST(DefaultRegistry, ComponentSignals) {
-    entt::DefaultRegistry registry;
-    Listener listener;
+TEST(Registry, Signals) {
+    entt::registry<> registry;
+    listener listener;
 
-    registry.construction<int>().connect<Listener, &Listener::incrComponent<int>>(&listener);
-    registry.destruction<int>().connect<Listener, &Listener::decrComponent<int>>(&listener);
+    registry.construction<int>().connect<&listener::incr<int>>(&listener);
+    registry.destruction<int>().connect<&listener::decr<int>>(&listener);
 
     auto e0 = registry.create();
     auto e1 = registry.create();
@@ -693,20 +607,20 @@ TEST(DefaultRegistry, ComponentSignals) {
     ASSERT_EQ(listener.counter, 1);
     ASSERT_EQ(listener.last, e0);
 
-    registry.destruction<int>().disconnect<Listener, &Listener::decrComponent<int>>(&listener);
+    registry.destruction<int>().disconnect<&listener::decr<int>>(&listener);
     registry.remove<int>(e1);
 
     ASSERT_EQ(listener.counter, 1);
     ASSERT_EQ(listener.last, e0);
 
-    registry.construction<int>().disconnect<Listener, &Listener::incrComponent<int>>(&listener);
+    registry.construction<int>().disconnect<&listener::incr<int>>(&listener);
     registry.assign<int>(e1);
 
     ASSERT_EQ(listener.counter, 1);
     ASSERT_EQ(listener.last, e0);
 
-    registry.construction<int>().connect<Listener, &Listener::incrComponent<int>>(&listener);
-    registry.destruction<int>().connect<Listener, &Listener::decrComponent<int>>(&listener);
+    registry.construction<int>().connect<&listener::incr<int>>(&listener);
+    registry.destruction<int>().connect<&listener::decr<int>>(&listener);
     registry.assign<int>(e0);
     registry.reset<int>(e1);
 
@@ -726,51 +640,12 @@ TEST(DefaultRegistry, ComponentSignals) {
     ASSERT_EQ(listener.last, e1);
 }
 
-TEST(DefaultRegistry, TagSignals) {
-    entt::DefaultRegistry registry;
-    Listener listener;
-
-    registry.construction<int>(entt::tag_t{}).connect<Listener, &Listener::incrTag<int>>(&listener);
-    registry.destruction<int>(entt::tag_t{}).connect<Listener, &Listener::decrTag<int>>(&listener);
-
-    auto e0 = registry.create();
-    registry.assign<int>(entt::tag_t{}, e0);
-
-    ASSERT_EQ(listener.counter, 1);
-    ASSERT_EQ(listener.last, e0);
-
-    auto e1 = registry.create();
-    registry.move<int>(e1);
-    registry.remove<int>();
-
-    ASSERT_EQ(listener.counter, 0);
-    ASSERT_EQ(listener.last, e1);
-
-    registry.construction<int>(entt::tag_t{}).disconnect<Listener, &Listener::incrTag<int>>(&listener);
-    registry.destruction<int>(entt::tag_t{}).disconnect<Listener, &Listener::decrTag<int>>(&listener);
-    registry.assign<int>(entt::tag_t{}, e0);
-    registry.remove<int>();
-
-    ASSERT_EQ(listener.counter, 0);
-    ASSERT_EQ(listener.last, e1);
-
-    registry.construction<int>(entt::tag_t{}).connect<Listener, &Listener::incrTag<int>>(&listener);
-    registry.destruction<int>(entt::tag_t{}).connect<Listener, &Listener::decrTag<int>>(&listener);
-
-    registry.assign<int>(entt::tag_t{}, e0);
-    registry.destroy(e0);
-
-    ASSERT_EQ(listener.counter, 0);
-    ASSERT_EQ(listener.last, e0);
-}
-
-TEST(DefaultRegistry, DestroyByTagAndComponents) {
-    entt::DefaultRegistry registry;
+TEST(Registry, DestroyByComponents) {
+    entt::registry<> registry;
 
     const auto e0 = registry.create();
     const auto e1 = registry.create();
     const auto e2 = registry.create();
-    const auto e3 = registry.create();
 
     registry.assign<int>(e0);
     registry.assign<char>(e0);
@@ -781,47 +656,36 @@ TEST(DefaultRegistry, DestroyByTagAndComponents) {
 
     registry.assign<int>(e2);
 
-    registry.assign<float>(entt::tag_t{}, e3);
-
     ASSERT_TRUE(registry.valid(e0));
     ASSERT_TRUE(registry.valid(e1));
     ASSERT_TRUE(registry.valid(e2));
-    ASSERT_TRUE(registry.valid(e3));
 
-    registry.destroy<int, char, double>(entt::persistent_t{});
+    registry.destroy<int, char, double>();
 
     ASSERT_FALSE(registry.valid(e0));
     ASSERT_TRUE(registry.valid(e1));
     ASSERT_TRUE(registry.valid(e2));
-    ASSERT_TRUE(registry.valid(e3));
 
     registry.destroy<int, char>();
 
     ASSERT_FALSE(registry.valid(e0));
     ASSERT_FALSE(registry.valid(e1));
     ASSERT_TRUE(registry.valid(e2));
-    ASSERT_TRUE(registry.valid(e3));
 
     registry.destroy<int>();
 
     ASSERT_FALSE(registry.valid(e0));
     ASSERT_FALSE(registry.valid(e1));
     ASSERT_FALSE(registry.valid(e2));
-    ASSERT_TRUE(registry.valid(e3));
-
-    registry.destroy<int>(entt::tag_t{});
-    registry.destroy<char>(entt::tag_t{});
-    registry.destroy<double>(entt::tag_t{});
-    registry.destroy<float>(entt::tag_t{});
 }
 
-TEST(DefaultRegistry, SignalsOnAccommodate) {
-    entt::DefaultRegistry registry;
+TEST(Registry, SignalsOnAccommodate) {
+    entt::registry<> registry;
     const auto entity = registry.create();
 
-    registry.prepare<int, char>();
+    registry.prepare_persistent_view<int, char>();
     registry.assign<int>(entity);
     registry.accommodate<char>(entity);
 
-    ASSERT_FALSE((registry.view<int, char>(entt::persistent_t{}).empty()));
+    ASSERT_FALSE((registry.persistent_view<int, char>().empty()));
 }

+ 119 - 198
test/entt/entity/snapshot.cpp

@@ -5,16 +5,14 @@
 #include <entt/entity/registry.hpp>
 
 template<typename Storage>
-struct OutputArchive {
-    OutputArchive(Storage &storage)
+struct output_archive {
+    output_archive(Storage &storage)
         : storage{storage}
     {}
 
     template<typename... Value>
     void operator()(const Value &... value) {
-        using accumulator_type = int[];
-        accumulator_type accumulator = { (std::get<std::queue<Value>>(storage).push(value), 0)... };
-        (void)accumulator;
+        (std::get<std::queue<Value>>(storage).push(value), ...);
     }
 
 private:
@@ -22,8 +20,8 @@ private:
 };
 
 template<typename Storage>
-struct InputArchive {
-    InputArchive(Storage &storage)
+struct input_archive {
+    input_archive(Storage &storage)
         : storage{storage}
     {}
 
@@ -35,29 +33,27 @@ struct InputArchive {
             queue.pop();
         };
 
-        using accumulator_type = int[];
-        accumulator_type accumulator = { (assign(value), 0)... };
-        (void)accumulator;
+        (assign(value), ...);
     }
 
 private:
     Storage &storage;
 };
 
-struct AComponent {};
+struct a_component {};
 
-struct AnotherComponent {
+struct another_component {
     int key;
     int value;
 };
 
-struct WhatAComponent {
-    entt::DefaultRegistry::entity_type bar;
-    std::vector<entt::DefaultRegistry::entity_type> quux;
+struct what_a_component {
+    entt::registry<>::entity_type bar;
+    std::vector<entt::registry<>::entity_type> quux;
 };
 
 TEST(Snapshot, Dump) {
-    entt::DefaultRegistry registry;
+    entt::registry<> registry;
 
     const auto e0 = registry.create();
     registry.assign<int>(e0, 42);
@@ -71,35 +67,26 @@ TEST(Snapshot, Dump) {
 
     const auto e3 = registry.create();
     registry.assign<char>(e3, '0');
-    registry.assign<float>(entt::tag_t{}, e3, .3f);
-
-    const auto e4 = registry.create();
-    registry.assign<AComponent>(entt::tag_t{}, e4);
 
     registry.destroy(e1);
     auto v1 = registry.current(e1);
 
     using storage_type = std::tuple<
-        std::queue<entt::DefaultRegistry::entity_type>,
+        std::queue<entt::registry<>::entity_type>,
         std::queue<int>,
         std::queue<char>,
         std::queue<double>,
-        std::queue<float>,
-        std::queue<bool>,
-        std::queue<AComponent>,
-        std::queue<AnotherComponent>,
-        std::queue<WhatAComponent>
+        std::queue<another_component>
     >;
 
     storage_type storage;
-    OutputArchive<storage_type> output{storage};
-    InputArchive<storage_type> input{storage};
+    output_archive<storage_type> output{storage};
+    input_archive<storage_type> input{storage};
 
     registry.snapshot()
             .entities(output)
             .destroyed(output)
-            .component<int, char, AnotherComponent, double>(output)
-            .tag<float, bool, AComponent>(output);
+            .component<int, char, another_component, double>(output);
 
     registry.reset();
 
@@ -107,25 +94,21 @@ TEST(Snapshot, Dump) {
     ASSERT_FALSE(registry.valid(e1));
     ASSERT_FALSE(registry.valid(e2));
     ASSERT_FALSE(registry.valid(e3));
-    ASSERT_FALSE(registry.valid(e4));
 
-    registry.restore()
+    registry.loader()
             .entities(input)
             .destroyed(input)
-            .component<int, char, AnotherComponent, double>(input)
-            .tag<float, bool, AComponent>(input)
+            .component<int, char, another_component, double>(input)
             .orphans();
 
     ASSERT_TRUE(registry.valid(e0));
     ASSERT_FALSE(registry.valid(e1));
     ASSERT_TRUE(registry.valid(e2));
     ASSERT_TRUE(registry.valid(e3));
-    ASSERT_TRUE(registry.valid(e4));
 
     ASSERT_FALSE(registry.orphan(e0));
     ASSERT_FALSE(registry.orphan(e2));
     ASSERT_FALSE(registry.orphan(e3));
-    ASSERT_FALSE(registry.orphan(e4));
 
     ASSERT_EQ(registry.get<int>(e0), 42);
     ASSERT_EQ(registry.get<char>(e0), 'c');
@@ -134,19 +117,11 @@ TEST(Snapshot, Dump) {
     ASSERT_EQ(registry.get<int>(e2), 3);
     ASSERT_EQ(registry.get<char>(e3), '0');
 
-    ASSERT_TRUE(registry.has<float>());
-    ASSERT_EQ(registry.attachee<float>(), e3);
-    ASSERT_EQ(registry.get<float>(), .3f);
-
-    ASSERT_TRUE(registry.has<AComponent>());
-    ASSERT_EQ(registry.attachee<AComponent>(), e4);
-
-    ASSERT_TRUE(registry.empty<AnotherComponent>());
-    ASSERT_FALSE(registry.has<long int>());
+    ASSERT_TRUE(registry.empty<another_component>());
 }
 
 TEST(Snapshot, Partial) {
-    entt::DefaultRegistry registry;
+    entt::registry<> registry;
 
     const auto e0 = registry.create();
     registry.assign<int>(e0, 42);
@@ -160,34 +135,25 @@ TEST(Snapshot, Partial) {
 
     const auto e3 = registry.create();
     registry.assign<char>(e3, '0');
-    registry.assign<float>(entt::tag_t{}, e3, .3f);
-
-    const auto e4 = registry.create();
-    registry.assign<AComponent>(entt::tag_t{}, e4);
 
     registry.destroy(e1);
     auto v1 = registry.current(e1);
 
     using storage_type = std::tuple<
-        std::queue<entt::DefaultRegistry::entity_type>,
+        std::queue<entt::registry<>::entity_type>,
         std::queue<int>,
         std::queue<char>,
-        std::queue<double>,
-        std::queue<float>,
-        std::queue<bool>,
-        std::queue<AComponent>,
-        std::queue<WhatAComponent>
+        std::queue<double>
     >;
 
     storage_type storage;
-    OutputArchive<storage_type> output{storage};
-    InputArchive<storage_type> input{storage};
+    output_archive<storage_type> output{storage};
+    input_archive<storage_type> input{storage};
 
     registry.snapshot()
             .entities(output)
             .destroyed(output)
-            .component<char, int>(output)
-            .tag<bool, float>(output);
+            .component<char, int>(output);
 
     registry.reset();
 
@@ -195,19 +161,16 @@ TEST(Snapshot, Partial) {
     ASSERT_FALSE(registry.valid(e1));
     ASSERT_FALSE(registry.valid(e2));
     ASSERT_FALSE(registry.valid(e3));
-    ASSERT_FALSE(registry.valid(e4));
 
-    registry.restore()
+    registry.loader()
             .entities(input)
             .destroyed(input)
-            .component<char, int>(input)
-            .tag<bool, float>(input);
+            .component<char, int>(input);
 
     ASSERT_TRUE(registry.valid(e0));
     ASSERT_FALSE(registry.valid(e1));
     ASSERT_TRUE(registry.valid(e2));
     ASSERT_TRUE(registry.valid(e3));
-    ASSERT_TRUE(registry.valid(e4));
 
     ASSERT_EQ(registry.get<int>(e0), 42);
     ASSERT_EQ(registry.get<char>(e0), 'c');
@@ -215,17 +178,10 @@ TEST(Snapshot, Partial) {
     ASSERT_EQ(registry.current(e1), v1);
     ASSERT_EQ(registry.get<int>(e2), 3);
     ASSERT_EQ(registry.get<char>(e3), '0');
-    ASSERT_TRUE(registry.orphan(e4));
-
-    ASSERT_TRUE(registry.has<float>());
-    ASSERT_EQ(registry.attachee<float>(), e3);
-    ASSERT_EQ(registry.get<float>(), .3f);
-    ASSERT_FALSE(registry.has<long int>());
 
     registry.snapshot()
-            .tag<float>(output)
-            .destroyed(output)
-            .entities(output);
+            .entities(output)
+            .destroyed(output);
 
     registry.reset();
 
@@ -233,78 +189,75 @@ TEST(Snapshot, Partial) {
     ASSERT_FALSE(registry.valid(e1));
     ASSERT_FALSE(registry.valid(e2));
     ASSERT_FALSE(registry.valid(e3));
-    ASSERT_FALSE(registry.valid(e4));
 
-    registry.restore()
-            .tag<float>(input)
-            .destroyed(input)
+    registry.loader()
             .entities(input)
+            .destroyed(input)
             .orphans();
 
     ASSERT_FALSE(registry.valid(e0));
     ASSERT_FALSE(registry.valid(e1));
     ASSERT_FALSE(registry.valid(e2));
-    ASSERT_TRUE(registry.valid(e3));
-    ASSERT_FALSE(registry.valid(e4));
+    ASSERT_FALSE(registry.valid(e3));
 }
 
 TEST(Snapshot, Iterator) {
-    entt::DefaultRegistry registry;
+    entt::registry<> registry;
 
     for(auto i = 0; i < 50; ++i) {
         const auto entity = registry.create();
-        registry.assign<AnotherComponent>(entity, i, i);
+        registry.assign<another_component>(entity, i, i);
 
         if(i % 2) {
-            registry.assign<AComponent>(entity);
+            registry.assign<a_component>(entity);
         }
     }
 
     using storage_type = std::tuple<
-        std::queue<entt::DefaultRegistry::entity_type>,
-        std::queue<AnotherComponent>
+        std::queue<entt::registry<>::entity_type>,
+        std::queue<another_component>
     >;
 
     storage_type storage;
-    OutputArchive<storage_type> output{storage};
-    InputArchive<storage_type> input{storage};
+    output_archive<storage_type> output{storage};
+    input_archive<storage_type> input{storage};
 
-    const auto view = registry.view<AComponent>();
+    const auto view = registry.view<a_component>();
     const auto size = view.size();
 
-    registry.snapshot().component<AnotherComponent>(output, view.cbegin(), view.cend());
+    registry.snapshot().component<another_component>(output, view.cbegin(), view.cend());
     registry.reset();
-    registry.restore().component<AnotherComponent>(input);
+    registry.loader().component<another_component>(input);
 
-    ASSERT_EQ(registry.view<AnotherComponent>().size(), size);
+    ASSERT_EQ(registry.view<another_component>().size(), size);
 
-    registry.view<AnotherComponent>().each([](const auto entity, auto &&...) {
+    registry.view<another_component>().each([](const auto entity, auto &&...) {
         ASSERT_TRUE(entity % 2);
     });
 }
 
 TEST(Snapshot, Continuous) {
-    using entity_type = entt::DefaultRegistry::entity_type;
+    using entity_type = entt::registry<>::entity_type;
 
-    entt::DefaultRegistry src;
-    entt::DefaultRegistry dst;
+    entt::registry<> src;
+    entt::registry<> dst;
 
-    entt::ContinuousLoader<entity_type> loader{dst};
+    entt::continuous_loader<entity_type> loader{dst};
 
     std::vector<entity_type> entities;
     entity_type entity;
 
     using storage_type = std::tuple<
         std::queue<entity_type>,
-        std::queue<AComponent>,
-        std::queue<AnotherComponent>,
-        std::queue<WhatAComponent>,
+        std::queue<a_component>,
+        std::queue<another_component>,
+        std::queue<what_a_component>,
         std::queue<double>
     >;
 
     storage_type storage;
-    OutputArchive<storage_type> output{storage};
-    InputArchive<storage_type> input{storage};
+    output_archive<storage_type> output{storage};
+    input_archive<storage_type> input{storage};
 
     for(int i = 0; i < 10; ++i) {
         src.create();
@@ -316,64 +269,57 @@ TEST(Snapshot, Continuous) {
         entity = src.create();
         entities.push_back(entity);
 
-        src.assign<AComponent>(entity);
-        src.assign<AnotherComponent>(entity, i, i);
+        src.assign<a_component>(entity);
+        src.assign<another_component>(entity, i, i);
 
         if(i % 2) {
-            src.assign<WhatAComponent>(entity, entity);
-        } else if(i == 2) {
-            src.assign<double>(entt::tag_t{}, entity, .3);
+            src.assign<what_a_component>(entity, entity);
         }
     }
 
-    src.view<WhatAComponent>().each([&entities](auto, auto &whatAComponent) {
-        whatAComponent.quux.insert(whatAComponent.quux.begin(), entities.begin(), entities.end());
+    src.view<what_a_component>().each([&entities](auto, auto &what_a_component) {
+        what_a_component.quux.insert(what_a_component.quux.begin(), entities.begin(), entities.end());
     });
 
     entity = dst.create();
-    dst.assign<AComponent>(entity);
-    dst.assign<AnotherComponent>(entity, -1, -1);
+    dst.assign<a_component>(entity);
+    dst.assign<another_component>(entity, -1, -1);
 
     src.snapshot()
             .entities(output)
             .destroyed(output)
-            .component<AComponent, AnotherComponent, WhatAComponent>(output)
-            .tag<double>(output);
+            .component<a_component, another_component, what_a_component>(output);
 
     loader.entities(input)
             .destroyed(input)
-            .component<AComponent, AnotherComponent, WhatAComponent>(input, &WhatAComponent::bar, &WhatAComponent::quux)
-            .tag<double>(input)
+            .component<a_component, another_component, what_a_component>(input, &what_a_component::bar, &what_a_component::quux)
             .orphans();
 
-    decltype(dst.size()) aComponentCnt{};
-    decltype(dst.size()) anotherComponentCnt{};
-    decltype(dst.size()) whatAComponentCnt{};
+    decltype(dst.size()) a_component_cnt{};
+    decltype(dst.size()) another_component_cnt{};
+    decltype(dst.size()) what_a_component_cnt{};
 
-    dst.each([&dst, &aComponentCnt](auto entity) {
-        ASSERT_TRUE(dst.has<AComponent>(entity));
-        ++aComponentCnt;
+    dst.each([&dst, &a_component_cnt](auto entity) {
+        ASSERT_TRUE(dst.has<a_component>(entity));
+        ++a_component_cnt;
     });
 
-    dst.view<AnotherComponent>().each([&anotherComponentCnt](auto, const auto &component) {
+    dst.view<another_component>().each([&another_component_cnt](auto, const auto &component) {
         ASSERT_EQ(component.value, component.key < 0 ? -1 : component.key);
-        ++anotherComponentCnt;
+        ++another_component_cnt;
     });
 
-    dst.view<WhatAComponent>().each([&dst, &whatAComponentCnt](auto entity, const auto &component) {
+    dst.view<what_a_component>().each([&dst, &what_a_component_cnt](auto entity, const auto &component) {
         ASSERT_EQ(entity, component.bar);
 
         for(auto entity: component.quux) {
             ASSERT_TRUE(dst.valid(entity));
         }
 
-        ++whatAComponentCnt;
+        ++what_a_component_cnt;
     });
 
-    ASSERT_TRUE(dst.has<double>());
-    ASSERT_EQ(dst.get<double>(), .3);
-
-    src.view<AnotherComponent>().each([](auto, auto &component) {
+    src.view<another_component>().each([](auto, auto &component) {
         component.value = 2 * component.key;
     });
 
@@ -382,50 +328,45 @@ TEST(Snapshot, Continuous) {
     src.snapshot()
             .entities(output)
             .destroyed(output)
-            .component<AComponent, WhatAComponent, AnotherComponent>(output)
-            .tag<double>(output);
+            .component<a_component, what_a_component, another_component>(output);
 
     loader.entities(input)
             .destroyed(input)
-            .component<AComponent, WhatAComponent, AnotherComponent>(input, &WhatAComponent::bar, &WhatAComponent::quux)
-            .tag<double>(input)
+            .component<a_component, what_a_component, another_component>(input, &what_a_component::bar, &what_a_component::quux)
             .orphans();
 
     ASSERT_EQ(size, dst.size());
 
-    ASSERT_EQ(dst.size<AComponent>(), aComponentCnt);
-    ASSERT_EQ(dst.size<AnotherComponent>(), anotherComponentCnt);
-    ASSERT_EQ(dst.size<WhatAComponent>(), whatAComponentCnt);
-    ASSERT_TRUE(dst.has<double>());
+    ASSERT_EQ(dst.size<a_component>(), a_component_cnt);
+    ASSERT_EQ(dst.size<another_component>(), another_component_cnt);
+    ASSERT_EQ(dst.size<what_a_component>(), what_a_component_cnt);
 
-    dst.view<AnotherComponent>().each([](auto, auto &component) {
+    dst.view<another_component>().each([](auto, auto &component) {
         ASSERT_EQ(component.value, component.key < 0 ? -1 : (2 * component.key));
     });
 
     entity = src.create();
 
-    src.view<WhatAComponent>().each([entity](auto, auto &component) {
+    src.view<what_a_component>().each([entity](auto, auto &component) {
         component.bar = entity;
     });
 
     src.snapshot()
             .entities(output)
             .destroyed(output)
-            .component<WhatAComponent, AComponent, AnotherComponent>(output)
-            .tag<double>(output);
+            .component<what_a_component, a_component, another_component>(output);
 
     loader.entities(input)
             .destroyed(input)
-            .component<WhatAComponent, AComponent, AnotherComponent>(input, &WhatAComponent::bar, &WhatAComponent::quux)
-            .tag<double>(input)
+            .component<what_a_component, a_component, another_component>(input, &what_a_component::bar, &what_a_component::quux)
             .orphans();
 
-    dst.view<WhatAComponent>().each([&loader, entity](auto, auto &component) {
+    dst.view<what_a_component>().each([&loader, entity](auto, auto &component) {
         ASSERT_EQ(component.bar, loader.map(entity));
     });
 
     entities.clear();
-    for(auto entity: src.view<AComponent>()) {
+    for(auto entity: src.view<a_component>()) {
         entities.push_back(entity);
     }
 
@@ -435,17 +376,15 @@ TEST(Snapshot, Continuous) {
     src.snapshot()
             .entities(output)
             .destroyed(output)
-            .component<AComponent, AnotherComponent, WhatAComponent>(output)
-            .tag<double>(output);
+            .component<a_component, another_component, what_a_component>(output);
 
     loader.entities(input)
             .destroyed(input)
-            .component<AComponent, AnotherComponent, WhatAComponent>(input, &WhatAComponent::bar, &WhatAComponent::quux)
-            .tag<double>(input)
+            .component<a_component, another_component, what_a_component>(input, &what_a_component::bar, &what_a_component::quux)
             .orphans()
             .shrink();
 
-    dst.view<WhatAComponent>().each([&dst](auto, auto &component) {
+    dst.view<what_a_component>().each([&dst](auto, auto &component) {
         ASSERT_FALSE(dst.valid(component.bar));
     });
 
@@ -453,64 +392,57 @@ TEST(Snapshot, Continuous) {
 
     entity = src.create();
 
-    src.view<WhatAComponent>().each([entity](auto, auto &component) {
+    src.view<what_a_component>().each([entity](auto, auto &component) {
         component.bar = entity;
     });
 
-    dst.reset<AComponent>();
-    aComponentCnt = src.size<AComponent>();
+    dst.reset<a_component>();
+    a_component_cnt = src.size<a_component>();
 
     src.snapshot()
             .entities(output)
             .destroyed(output)
-            .component<AComponent, WhatAComponent, AnotherComponent>(output)
-            .tag<double>(output);
+            .component<a_component, what_a_component, another_component>(output);
 
     loader.entities(input)
             .destroyed(input)
-            .component<AComponent, WhatAComponent, AnotherComponent>(input, &WhatAComponent::bar, &WhatAComponent::quux)
-            .tag<double>(input)
+            .component<a_component, what_a_component, another_component>(input, &what_a_component::bar, &what_a_component::quux)
             .orphans();
 
-    ASSERT_EQ(dst.size<AComponent>(), aComponentCnt);
-    ASSERT_TRUE(dst.has<double>());
+    ASSERT_EQ(dst.size<a_component>(), a_component_cnt);
 
-    src.reset<AComponent>();
-    src.remove<double>();
-    aComponentCnt = {};
+    src.reset<a_component>();
+    a_component_cnt = {};
 
     src.snapshot()
             .entities(output)
             .destroyed(output)
-            .component<WhatAComponent, AComponent, AnotherComponent>(output)
-            .tag<double>(output);
+            .component<what_a_component, a_component, another_component>(output);
 
     loader.entities(input)
             .destroyed(input)
-            .component<WhatAComponent, AComponent, AnotherComponent>(input, &WhatAComponent::bar, &WhatAComponent::quux)
-            .tag<double>(input)
+            .component<what_a_component, a_component, another_component>(input, &what_a_component::bar, &what_a_component::quux)
             .orphans();
 
-    ASSERT_EQ(dst.size<AComponent>(), aComponentCnt);
-    ASSERT_FALSE(dst.has<double>());
+    ASSERT_EQ(dst.size<a_component>(), a_component_cnt);
 }
 
 TEST(Snapshot, ContinuousMoreOnShrink) {
-    using entity_type = entt::DefaultRegistry::entity_type;
+    using entity_type = entt::registry<>::entity_type;
 
-    entt::DefaultRegistry src;
-    entt::DefaultRegistry dst;
+    entt::registry<> src;
+    entt::registry<> dst;
 
-    entt::ContinuousLoader<entity_type> loader{dst};
+    entt::continuous_loader<entity_type> loader{dst};
 
     using storage_type = std::tuple<
         std::queue<entity_type>,
-        std::queue<AComponent>
+        std::queue<a_component>
     >;
 
     storage_type storage;
-    OutputArchive<storage_type> output{storage};
-    InputArchive<storage_type> input{storage};
+    output_archive<storage_type> output{storage};
+    input_archive<storage_type> input{storage};
 
     auto entity = src.create();
     src.snapshot().entities(output);
@@ -524,21 +456,21 @@ TEST(Snapshot, ContinuousMoreOnShrink) {
 }
 
 TEST(Snapshot, SyncDataMembers) {
-    using entity_type = entt::DefaultRegistry::entity_type;
+    using entity_type = entt::registry<>::entity_type;
 
-    entt::DefaultRegistry src;
-    entt::DefaultRegistry dst;
+    entt::registry<> src;
+    entt::registry<> dst;
 
-    entt::ContinuousLoader<entity_type> loader{dst};
+    entt::continuous_loader<entity_type> loader{dst};
 
     using storage_type = std::tuple<
         std::queue<entity_type>,
-        std::queue<WhatAComponent>
+        std::queue<what_a_component>
     >;
 
     storage_type storage;
-    OutputArchive<storage_type> output{storage};
-    InputArchive<storage_type> input{storage};
+    output_archive<storage_type> output{storage};
+    input_archive<storage_type> input{storage};
 
     src.create();
     src.create();
@@ -548,28 +480,17 @@ TEST(Snapshot, SyncDataMembers) {
     auto parent = src.create();
     auto child = src.create();
 
-    src.assign<WhatAComponent>(entt::tag_t{}, child, parent).quux.push_back(parent);
-    src.assign<WhatAComponent>(child, child).quux.push_back(child);
-
-    src.snapshot().entities(output)
-            .component<WhatAComponent>(output)
-            .tag<WhatAComponent>(output);
-
-    loader.entities(input)
-            .component<WhatAComponent>(input, &WhatAComponent::bar, &WhatAComponent::quux)
-            .tag<WhatAComponent>(input, &WhatAComponent::bar, &WhatAComponent::quux);
+    src.assign<what_a_component>(child, parent).quux.push_back(child);
+    src.snapshot().entities(output).component<what_a_component>(output);
+    loader.entities(input).component<what_a_component>(input, &what_a_component::bar, &what_a_component::quux);
 
     ASSERT_FALSE(dst.valid(parent));
     ASSERT_FALSE(dst.valid(child));
 
-    ASSERT_TRUE(dst.has<WhatAComponent>());
-    ASSERT_EQ(dst.attachee<WhatAComponent>(), loader.map(child));
-    ASSERT_EQ(dst.get<WhatAComponent>().bar, loader.map(parent));
-    ASSERT_EQ(dst.get<WhatAComponent>().quux[0], loader.map(parent));
-    ASSERT_TRUE(dst.has<WhatAComponent>(loader.map(child)));
+    ASSERT_TRUE(dst.has<what_a_component>(loader.map(child)));
 
-    const auto &component = dst.get<WhatAComponent>(loader.map(child));
+    const auto &component = dst.get<what_a_component>(loader.map(child));
 
-    ASSERT_EQ(component.bar, loader.map(child));
+    ASSERT_EQ(component.bar, loader.map(parent));
     ASSERT_EQ(component.quux[0], loader.map(child));
 }

+ 66 - 66
test/entt/entity/sparse_set.cpp

@@ -3,7 +3,7 @@
 #include <entt/entity/sparse_set.hpp>
 
 TEST(SparseSetNoType, Functionalities) {
-    entt::SparseSet<std::uint64_t> set;
+    entt::sparse_set<std::uint64_t> set;
     const auto &cset = set;
 
     set.reserve(42);
@@ -51,28 +51,28 @@ TEST(SparseSetNoType, Functionalities) {
     ASSERT_FALSE(set.has(0));
     ASSERT_FALSE(set.has(42));
 
-    (void)entt::SparseSet<std::uint64_t>{std::move(set)};
-    entt::SparseSet<std::uint64_t> other;
+    (void)entt::sparse_set<std::uint64_t>{std::move(set)};
+    entt::sparse_set<std::uint64_t> other;
     other = std::move(set);
 }
 
 TEST(SparseSetNoType, ElementAccess) {
-    entt::SparseSet<std::uint64_t> set;
+    entt::sparse_set<std::uint64_t> set;
     const auto &cset = set;
 
     set.construct(42);
     set.construct(3);
 
-    for(typename entt::SparseSet<std::uint64_t>::size_type i{}; i < set.size(); ++i) {
+    for(typename entt::sparse_set<std::uint64_t>::size_type i{}; i < set.size(); ++i) {
         ASSERT_EQ(set[i], i ? 42 : 3);
         ASSERT_EQ(cset[i], i ? 42 : 3);
     }
 }
 
 TEST(SparseSetNoType, Iterator) {
-    using iterator_type = typename entt::SparseSet<std::uint64_t>::iterator_type;
+    using iterator_type = typename entt::sparse_set<std::uint64_t>::iterator_type;
 
-    entt::SparseSet<std::uint64_t> set;
+    entt::sparse_set<std::uint64_t> set;
     set.construct(3);
 
     iterator_type end{set.begin()};
@@ -115,9 +115,9 @@ TEST(SparseSetNoType, Iterator) {
 }
 
 TEST(SparseSetNoType, ConstIterator) {
-    using iterator_type = typename entt::SparseSet<std::uint64_t>::const_iterator_type;
+    using iterator_type = typename entt::sparse_set<std::uint64_t>::const_iterator_type;
 
-    entt::SparseSet<std::uint64_t> set;
+    entt::sparse_set<std::uint64_t> set;
     set.construct(3);
 
     iterator_type cend{set.cbegin()};
@@ -160,7 +160,7 @@ TEST(SparseSetNoType, ConstIterator) {
 }
 
 TEST(SparseSetNoType, Data) {
-    entt::SparseSet<std::uint64_t> set;
+    entt::sparse_set<std::uint64_t> set;
 
     set.construct(3);
     set.construct(12);
@@ -176,8 +176,8 @@ TEST(SparseSetNoType, Data) {
 }
 
 TEST(SparseSetNoType, RespectDisjoint) {
-    entt::SparseSet<std::uint64_t> lhs;
-    entt::SparseSet<std::uint64_t> rhs;
+    entt::sparse_set<std::uint64_t> lhs;
+    entt::sparse_set<std::uint64_t> rhs;
     const auto &clhs = lhs;
 
     lhs.construct(3);
@@ -196,8 +196,8 @@ TEST(SparseSetNoType, RespectDisjoint) {
 }
 
 TEST(SparseSetNoType, RespectOverlap) {
-    entt::SparseSet<std::uint64_t> lhs;
-    entt::SparseSet<std::uint64_t> rhs;
+    entt::sparse_set<std::uint64_t> lhs;
+    entt::sparse_set<std::uint64_t> rhs;
     const auto &clhs = lhs;
 
     lhs.construct(3);
@@ -218,8 +218,8 @@ TEST(SparseSetNoType, RespectOverlap) {
 }
 
 TEST(SparseSetNoType, RespectOrdered) {
-    entt::SparseSet<std::uint64_t> lhs;
-    entt::SparseSet<std::uint64_t> rhs;
+    entt::sparse_set<std::uint64_t> lhs;
+    entt::sparse_set<std::uint64_t> rhs;
 
     lhs.construct(1);
     lhs.construct(2);
@@ -258,8 +258,8 @@ TEST(SparseSetNoType, RespectOrdered) {
 }
 
 TEST(SparseSetNoType, RespectReverse) {
-    entt::SparseSet<std::uint64_t> lhs;
-    entt::SparseSet<std::uint64_t> rhs;
+    entt::sparse_set<std::uint64_t> lhs;
+    entt::sparse_set<std::uint64_t> rhs;
 
     lhs.construct(1);
     lhs.construct(2);
@@ -298,8 +298,8 @@ TEST(SparseSetNoType, RespectReverse) {
 }
 
 TEST(SparseSetNoType, RespectUnordered) {
-    entt::SparseSet<std::uint64_t> lhs;
-    entt::SparseSet<std::uint64_t> rhs;
+    entt::sparse_set<std::uint64_t> lhs;
+    entt::sparse_set<std::uint64_t> rhs;
 
     lhs.construct(1);
     lhs.construct(2);
@@ -338,15 +338,15 @@ TEST(SparseSetNoType, RespectUnordered) {
 }
 
 TEST(SparseSetNoType, CanModifyDuringIteration) {
-    entt::SparseSet<std::uint64_t> set;
+    entt::sparse_set<std::uint64_t> set;
     set.construct(0);
 
-    ASSERT_EQ(set.capacity(), entt::SparseSet<std::uint64_t>::size_type{1});
+    ASSERT_EQ(set.capacity(), entt::sparse_set<std::uint64_t>::size_type{1});
 
     const auto it = set.cbegin();
-    set.reserve(entt::SparseSet<std::uint64_t>::size_type{2});
+    set.reserve(entt::sparse_set<std::uint64_t>::size_type{2});
 
-    ASSERT_EQ(set.capacity(), entt::SparseSet<std::uint64_t>::size_type{2});
+    ASSERT_EQ(set.capacity(), entt::sparse_set<std::uint64_t>::size_type{2});
 
     // this should crash with asan enabled if we break the constraint
     const auto entity = *it;
@@ -354,7 +354,7 @@ TEST(SparseSetNoType, CanModifyDuringIteration) {
 }
 
 TEST(SparseSetWithType, Functionalities) {
-    entt::SparseSet<std::uint64_t, int> set;
+    entt::sparse_set<std::uint64_t, int> set;
     const auto &cset = set;
 
     set.reserve(42);
@@ -400,43 +400,43 @@ TEST(SparseSetWithType, Functionalities) {
     ASSERT_FALSE(set.has(0));
     ASSERT_FALSE(set.has(42));
 
-    (void)entt::SparseSet<std::uint64_t, int>{std::move(set)};
-    entt::SparseSet<std::uint64_t, int> other;
+    (void)entt::sparse_set<std::uint64_t, int>{std::move(set)};
+    entt::sparse_set<std::uint64_t, int> other;
     other = std::move(set);
 }
 
 TEST(SparseSetWithType, ElementAccess) {
-    entt::SparseSet<std::uint64_t, int> set;
+    entt::sparse_set<std::uint64_t, int> set;
     const auto &cset = set;
 
     set.construct(42, 1);
     set.construct(3, 0);
 
-    for(typename entt::SparseSet<std::uint64_t, int>::size_type i{}; i < set.size(); ++i) {
+    for(typename entt::sparse_set<std::uint64_t, int>::size_type i{}; i < set.size(); ++i) {
         ASSERT_EQ(set[i], i);
         ASSERT_EQ(cset[i], i);
     }
 }
 
 TEST(SparseSetWithType, AggregatesMustWork) {
-    struct AggregateType { int value; };
+    struct aggregate_type { int value; };
     // the goal of this test is to enforce the requirements for aggregate types
-    entt::SparseSet<std::uint64_t, AggregateType>{}.construct(0, 42);
+    entt::sparse_set<std::uint64_t, aggregate_type>{}.construct(0, 42);
 }
 
 TEST(SparseSetWithType, TypesFromStandardTemplateLibraryMustWork) {
     // see #37 - this test shouldn't crash, that's all
-    entt::SparseSet<std::uint64_t, std::unordered_set<int>> set;
+    entt::sparse_set<std::uint64_t, std::unordered_set<int>> set;
     set.construct(0).insert(42);
     set.destroy(0);
 }
 
 TEST(SparseSetWithType, Iterator) {
-    struct InternalType { int value; };
+    struct internal_type { int value; };
 
-    using iterator_type = typename entt::SparseSet<std::uint64_t, InternalType>::iterator_type;
+    using iterator_type = typename entt::sparse_set<std::uint64_t, internal_type>::iterator_type;
 
-    entt::SparseSet<std::uint64_t, InternalType> set;
+    entt::sparse_set<std::uint64_t, internal_type> set;
     set.construct(3, 42);
 
     iterator_type end{set.begin()};
@@ -476,11 +476,11 @@ TEST(SparseSetWithType, Iterator) {
 }
 
 TEST(SparseSetWithType, ConstIterator) {
-    struct InternalType { int value; };
+    struct internal_type { int value; };
 
-    using iterator_type = typename entt::SparseSet<std::uint64_t, InternalType>::const_iterator_type;
+    using iterator_type = typename entt::sparse_set<std::uint64_t, internal_type>::const_iterator_type;
 
-    entt::SparseSet<std::uint64_t, InternalType> set;
+    entt::sparse_set<std::uint64_t, internal_type> set;
     set.construct(3, 42);
 
     iterator_type cend{set.cbegin()};
@@ -520,7 +520,7 @@ TEST(SparseSetWithType, ConstIterator) {
 }
 
 TEST(SparseSetWithType, Raw) {
-    entt::SparseSet<std::uint64_t, int> set;
+    entt::sparse_set<std::uint64_t, int> set;
 
     set.construct(3, 3);
     set.construct(12, 6);
@@ -536,7 +536,7 @@ TEST(SparseSetWithType, Raw) {
 }
 
 TEST(SparseSetWithType, SortOrdered) {
-    entt::SparseSet<std::uint64_t, int> set;
+    entt::sparse_set<std::uint64_t, int> set;
 
     set.construct(12, 12);
     set.construct(42, 9);
@@ -572,7 +572,7 @@ TEST(SparseSetWithType, SortOrdered) {
 }
 
 TEST(SparseSetWithType, SortReverse) {
-    entt::SparseSet<std::uint64_t, int> set;
+    entt::sparse_set<std::uint64_t, int> set;
 
     set.construct(12, 1);
     set.construct(42, 3);
@@ -608,7 +608,7 @@ TEST(SparseSetWithType, SortReverse) {
 }
 
 TEST(SparseSetWithType, SortUnordered) {
-    entt::SparseSet<std::uint64_t, int> set;
+    entt::sparse_set<std::uint64_t, int> set;
 
     set.construct(12, 6);
     set.construct(42, 3);
@@ -644,8 +644,8 @@ TEST(SparseSetWithType, SortUnordered) {
 }
 
 TEST(SparseSetWithType, RespectDisjoint) {
-    entt::SparseSet<std::uint64_t, int> lhs;
-    entt::SparseSet<std::uint64_t, int> rhs;
+    entt::sparse_set<std::uint64_t, int> lhs;
+    entt::sparse_set<std::uint64_t, int> rhs;
     const auto &clhs = lhs;
 
     lhs.construct(3, 3);
@@ -672,8 +672,8 @@ TEST(SparseSetWithType, RespectDisjoint) {
 }
 
 TEST(SparseSetWithType, RespectOverlap) {
-    entt::SparseSet<std::uint64_t, int> lhs;
-    entt::SparseSet<std::uint64_t, int> rhs;
+    entt::sparse_set<std::uint64_t, int> lhs;
+    entt::sparse_set<std::uint64_t, int> rhs;
     const auto &clhs = lhs;
 
     lhs.construct(3, 3);
@@ -702,8 +702,8 @@ TEST(SparseSetWithType, RespectOverlap) {
 }
 
 TEST(SparseSetWithType, RespectOrdered) {
-    entt::SparseSet<std::uint64_t, int> lhs;
-    entt::SparseSet<std::uint64_t, int> rhs;
+    entt::sparse_set<std::uint64_t, int> lhs;
+    entt::sparse_set<std::uint64_t, int> rhs;
 
     lhs.construct(1, 0);
     lhs.construct(2, 0);
@@ -748,8 +748,8 @@ TEST(SparseSetWithType, RespectOrdered) {
 }
 
 TEST(SparseSetWithType, RespectReverse) {
-    entt::SparseSet<std::uint64_t, int> lhs;
-    entt::SparseSet<std::uint64_t, int> rhs;
+    entt::sparse_set<std::uint64_t, int> lhs;
+    entt::sparse_set<std::uint64_t, int> rhs;
 
     lhs.construct(1, 0);
     lhs.construct(2, 0);
@@ -794,8 +794,8 @@ TEST(SparseSetWithType, RespectReverse) {
 }
 
 TEST(SparseSetWithType, RespectUnordered) {
-    entt::SparseSet<std::uint64_t, int> lhs;
-    entt::SparseSet<std::uint64_t, int> rhs;
+    entt::sparse_set<std::uint64_t, int> lhs;
+    entt::sparse_set<std::uint64_t, int> rhs;
 
     lhs.construct(1, 0);
     lhs.construct(2, 0);
@@ -840,15 +840,15 @@ TEST(SparseSetWithType, RespectUnordered) {
 }
 
 TEST(SparseSetWithType, CanModifyDuringIteration) {
-    entt::SparseSet<std::uint64_t, int> set;
+    entt::sparse_set<std::uint64_t, int> set;
     set.construct(0, 42);
 
-    ASSERT_EQ(set.capacity(), entt::SparseSet<std::uint64_t>::size_type{1});
+    ASSERT_EQ(set.capacity(), entt::sparse_set<std::uint64_t>::size_type{1});
 
     const auto it = set.cbegin();
-    set.reserve(entt::SparseSet<std::uint64_t>::size_type{2});
+    set.reserve(entt::sparse_set<std::uint64_t>::size_type{2});
 
-    ASSERT_EQ(set.capacity(), entt::SparseSet<std::uint64_t>::size_type{2});
+    ASSERT_EQ(set.capacity(), entt::sparse_set<std::uint64_t>::size_type{2});
 
     // this should crash with asan enabled if we break the constraint
     const auto entity = *it;
@@ -856,9 +856,9 @@ TEST(SparseSetWithType, CanModifyDuringIteration) {
 }
 
 TEST(SparseSetWithType, ReferencesGuaranteed) {
-    struct InternalType { int value; };
+    struct internal_type { int value; };
 
-    entt::SparseSet<std::uint64_t, InternalType> set;
+    entt::sparse_set<std::uint64_t, internal_type> set;
 
     set.construct(0, 0);
     set.construct(1, 1);
@@ -886,16 +886,16 @@ TEST(SparseSetWithType, ReferencesGuaranteed) {
 }
 
 TEST(SparseSetWithType, MoveOnlyComponent) {
-    struct MoveOnlyComponent {
-        MoveOnlyComponent() = default;
-        ~MoveOnlyComponent() = default;
-        MoveOnlyComponent(const MoveOnlyComponent &) = delete;
-        MoveOnlyComponent(MoveOnlyComponent &&) = default;
-        MoveOnlyComponent & operator=(const MoveOnlyComponent &) = delete;
-        MoveOnlyComponent & operator=(MoveOnlyComponent &&) = default;
+    struct move_only_component {
+        move_only_component() = default;
+        ~move_only_component() = default;
+        move_only_component(const move_only_component &) = delete;
+        move_only_component(move_only_component &&) = default;
+        move_only_component & operator=(const move_only_component &) = delete;
+        move_only_component & operator=(move_only_component &&) = default;
     };
 
     // it's purpose is to ensure that move only components are always accepted
-    entt::SparseSet<std::uint64_t, MoveOnlyComponent> set;
+    entt::sparse_set<std::uint64_t, move_only_component> set;
     (void)set;
 }

+ 68 - 68
test/entt/entity/view.cpp

@@ -5,9 +5,9 @@
 #include <entt/entity/view.hpp>
 
 TEST(PersistentView, Prepare) {
-    entt::DefaultRegistry registry;
-    registry.prepare<int, char>();
-    auto view = registry.view<int, char>(entt::persistent_t{});
+    entt::registry<> registry;
+    registry.prepare_persistent_view<int, char>();
+    auto view = registry.persistent_view<int, char>();
     const auto &cview = view;
 
     ASSERT_TRUE(view.empty());
@@ -20,8 +20,8 @@ TEST(PersistentView, Prepare) {
     registry.assign<char>(e1);
 
     ASSERT_FALSE(view.empty());
-    ASSERT_NO_THROW((registry.view<int, char>(entt::persistent_t{}).begin()++));
-    ASSERT_NO_THROW((++registry.view<int, char>(entt::persistent_t{}).begin()));
+    ASSERT_NO_THROW((registry.persistent_view<int, char>().begin()++));
+    ASSERT_NO_THROW((++registry.persistent_view<int, char>().begin()));
 
     ASSERT_NE(view.begin(), view.end());
     ASSERT_NE(cview.begin(), cview.end());
@@ -57,8 +57,8 @@ TEST(PersistentView, Prepare) {
 }
 
 TEST(PersistentView, NoPrepare) {
-    entt::DefaultRegistry registry;
-    auto view = registry.view<int, char>(entt::persistent_t{});
+    entt::registry<> registry;
+    auto view = registry.persistent_view<int, char>();
 
     ASSERT_TRUE(view.empty());
 
@@ -70,8 +70,8 @@ TEST(PersistentView, NoPrepare) {
     registry.assign<char>(e1);
 
     ASSERT_FALSE(view.empty());
-    ASSERT_NO_THROW((registry.view<int, char>(entt::persistent_t{}).begin()++));
-    ASSERT_NO_THROW((++registry.view<int, char>(entt::persistent_t{}).begin()));
+    ASSERT_NO_THROW((registry.persistent_view<int, char>().begin()++));
+    ASSERT_NO_THROW((++registry.persistent_view<int, char>().begin()));
 
     ASSERT_NE(view.begin(), view.end());
     ASSERT_EQ(view.size(), typename decltype(view)::size_type{1});
@@ -106,8 +106,8 @@ TEST(PersistentView, NoPrepare) {
 }
 
 TEST(PersistentView, ElementAccess) {
-    entt::DefaultRegistry registry;
-    auto view = registry.view<int, char>(entt::persistent_t{});
+    entt::registry<> registry;
+    auto view = registry.persistent_view<int, char>();
     const auto &cview = view;
 
     const auto e0 = registry.create();
@@ -125,7 +125,7 @@ TEST(PersistentView, ElementAccess) {
 }
 
 TEST(PersistentView, Contains) {
-    entt::DefaultRegistry registry;
+    entt::registry<> registry;
 
     const auto e0 = registry.create();
     registry.assign<int>(e0);
@@ -137,14 +137,14 @@ TEST(PersistentView, Contains) {
 
     registry.destroy(e0);
 
-    auto view = registry.view<int, char>(entt::persistent_t{});
+    auto view = registry.persistent_view<int, char>();
 
     ASSERT_FALSE(view.contains(e0));
     ASSERT_TRUE(view.contains(e1));
 }
 
 TEST(PersistentView, Empty) {
-    entt::DefaultRegistry registry;
+    entt::registry<> registry;
 
     const auto e0 = registry.create();
     registry.assign<double>(e0);
@@ -155,20 +155,20 @@ TEST(PersistentView, Empty) {
     registry.assign<char>(e1);
     registry.assign<float>(e1);
 
-    for(auto entity: registry.view<char, int, float>(entt::persistent_t{})) {
+    for(auto entity: registry.persistent_view<char, int, float>()) {
         (void)entity;
         FAIL();
     }
 
-    for(auto entity: registry.view<double, char, int, float>(entt::persistent_t{})) {
+    for(auto entity: registry.persistent_view<double, char, int, float>()) {
         (void)entity;
         FAIL();
     }
 }
 
 TEST(PersistentView, Each) {
-    entt::DefaultRegistry registry;
-    registry.prepare<int, char>();
+    entt::registry<> registry;
+    registry.prepare_persistent_view<int, char>();
 
     const auto e0 = registry.create();
     registry.assign<int>(e0);
@@ -178,7 +178,7 @@ TEST(PersistentView, Each) {
     registry.assign<int>(e1);
     registry.assign<char>(e1);
 
-    auto view = registry.view<int, char>(entt::persistent_t{});
+    auto view = registry.persistent_view<int, char>();
     const auto &cview = static_cast<const decltype(view) &>(view);
     std::size_t cnt = 0;
 
@@ -192,8 +192,8 @@ TEST(PersistentView, Each) {
 }
 
 TEST(PersistentView, Sort) {
-    entt::DefaultRegistry registry;
-    registry.prepare<int, unsigned int>();
+    entt::registry<> registry;
+    registry.prepare_persistent_view<int, unsigned int>();
 
     const auto e0 = registry.create();
     const auto e1 = registry.create();
@@ -210,7 +210,7 @@ TEST(PersistentView, Sort) {
     registry.assign<int>(e1, ival++);
     registry.assign<int>(e2, ival++);
 
-    auto view = registry.view<int, unsigned int>(entt::persistent_t{});
+    auto view = registry.persistent_view<int, unsigned int>();
 
     for(auto entity: view) {
         ASSERT_EQ(view.get<unsigned int>(entity), --uval);
@@ -227,7 +227,7 @@ TEST(PersistentView, Sort) {
 }
 
 TEST(SingleComponentView, Functionalities) {
-    entt::DefaultRegistry registry;
+    entt::registry<> registry;
     auto view = registry.view<char>();
     const auto &cview = view;
 
@@ -274,7 +274,7 @@ TEST(SingleComponentView, Functionalities) {
 }
 
 TEST(SingleComponentView, ElementAccess) {
-    entt::DefaultRegistry registry;
+    entt::registry<> registry;
     auto view = registry.view<int>();
     const auto &cview = view;
 
@@ -291,7 +291,7 @@ TEST(SingleComponentView, ElementAccess) {
 }
 
 TEST(SingleComponentView, Contains) {
-    entt::DefaultRegistry registry;
+    entt::registry<> registry;
 
     const auto e0 = registry.create();
     registry.assign<int>(e0);
@@ -308,7 +308,7 @@ TEST(SingleComponentView, Contains) {
 }
 
 TEST(SingleComponentView, Empty) {
-    entt::DefaultRegistry registry;
+    entt::registry<> registry;
 
     const auto e0 = registry.create();
     registry.assign<char>(e0);
@@ -319,7 +319,7 @@ TEST(SingleComponentView, Empty) {
 
     auto view = registry.view<int>();
 
-    ASSERT_EQ(view.size(), entt::DefaultRegistry::size_type{0});
+    ASSERT_EQ(view.size(), entt::registry<>::size_type{0});
 
     for(auto entity: view) {
         (void)entity;
@@ -328,7 +328,7 @@ TEST(SingleComponentView, Empty) {
 }
 
 TEST(SingleComponentView, Each) {
-    entt::DefaultRegistry registry;
+    entt::registry<> registry;
 
     registry.assign<int>(registry.create());
     registry.assign<int>(registry.create());
@@ -347,7 +347,7 @@ TEST(SingleComponentView, Each) {
 }
 
 TEST(MultipleComponentView, Functionalities) {
-    entt::DefaultRegistry registry;
+    entt::registry<> registry;
     auto view = registry.view<int, char>();
     const auto &cview = view;
 
@@ -388,7 +388,7 @@ TEST(MultipleComponentView, Functionalities) {
 }
 
 TEST(MultipleComponentView, Iterator) {
-    entt::DefaultRegistry registry;
+    entt::registry<> registry;
     const auto entity = registry.create();
     registry.assign<int>(entity);
     registry.assign<char>(entity);
@@ -410,7 +410,7 @@ TEST(MultipleComponentView, Iterator) {
 }
 
 TEST(MultipleComponentView, ConstIterator) {
-    entt::DefaultRegistry registry;
+    entt::registry<> registry;
     const auto entity = registry.create();
     registry.assign<int>(entity);
     registry.assign<char>(entity);
@@ -432,7 +432,7 @@ TEST(MultipleComponentView, ConstIterator) {
 }
 
 TEST(MultipleComponentView, Contains) {
-    entt::DefaultRegistry registry;
+    entt::registry<> registry;
 
     const auto e0 = registry.create();
     registry.assign<int>(e0);
@@ -451,7 +451,7 @@ TEST(MultipleComponentView, Contains) {
 }
 
 TEST(MultipleComponentView, Empty) {
-    entt::DefaultRegistry registry;
+    entt::registry<> registry;
 
     const auto e0 = registry.create();
     registry.assign<double>(e0);
@@ -471,7 +471,7 @@ TEST(MultipleComponentView, Empty) {
 }
 
 TEST(MultipleComponentView, Each) {
-    entt::DefaultRegistry registry;
+    entt::registry<> registry;
 
     const auto e0 = registry.create();
     registry.assign<int>(e0);
@@ -495,7 +495,7 @@ TEST(MultipleComponentView, Each) {
 }
 
 TEST(MultipleComponentView, EachWithHoles) {
-    entt::DefaultRegistry registry;
+    entt::registry<> registry;
 
     const auto e0 = registry.create();
     const auto e1 = registry.create();
@@ -520,8 +520,8 @@ TEST(MultipleComponentView, EachWithHoles) {
 }
 
 TEST(RawView, Functionalities) {
-    entt::DefaultRegistry registry;
-    auto view = registry.view<char>(entt::raw_t{});
+    entt::registry<> registry;
+    auto view = registry.raw_view<char>();
     const auto &cview = view;
 
     ASSERT_TRUE(view.empty());
@@ -533,8 +533,8 @@ TEST(RawView, Functionalities) {
     registry.assign<char>(e1);
 
     ASSERT_FALSE(view.empty());
-    ASSERT_NO_THROW(registry.view<char>(entt::raw_t{}).begin()++);
-    ASSERT_NO_THROW(++registry.view<char>(entt::raw_t{}).begin());
+    ASSERT_NO_THROW(registry.raw_view<char>().begin()++);
+    ASSERT_NO_THROW(++registry.raw_view<char>().begin());
 
     ASSERT_NE(view.begin(), view.end());
     ASSERT_NE(cview.begin(), cview.end());
@@ -575,8 +575,8 @@ TEST(RawView, Functionalities) {
 }
 
 TEST(RawView, ElementAccess) {
-    entt::DefaultRegistry registry;
-    auto view = registry.view<int>(entt::raw_t{});
+    entt::registry<> registry;
+    auto view = registry.raw_view<int>();
     const auto &cview = view;
 
     const auto e0 = registry.create();
@@ -592,7 +592,7 @@ TEST(RawView, ElementAccess) {
 }
 
 TEST(RawView, Empty) {
-    entt::DefaultRegistry registry;
+    entt::registry<> registry;
 
     const auto e0 = registry.create();
     registry.assign<char>(e0);
@@ -601,9 +601,9 @@ TEST(RawView, Empty) {
     const auto e1 = registry.create();
     registry.assign<char>(e1);
 
-    auto view = registry.view<int>(entt::raw_t{});
+    auto view = registry.raw_view<int>();
 
-    ASSERT_EQ(view.size(), entt::DefaultRegistry::size_type{0});
+    ASSERT_EQ(view.size(), entt::registry<>::size_type{0});
 
     for(auto &&component: view) {
         (void)component;
@@ -612,12 +612,12 @@ TEST(RawView, Empty) {
 }
 
 TEST(RawView, Each) {
-    entt::DefaultRegistry registry;
+    entt::registry<> registry;
 
     registry.assign<int>(registry.create(), 1);
     registry.assign<int>(registry.create(), 3);
 
-    auto view = registry.view<int>(entt::raw_t{});
+    auto view = registry.raw_view<int>();
     const auto &cview = static_cast<const decltype(view) &>(view);
     std::size_t cnt = 0;
 
@@ -631,7 +631,7 @@ TEST(RawView, Each) {
 }
 
 TEST(RuntimeView, Functionalities) {
-    entt::DefaultRegistry registry;
+    entt::registry<> registry;
     using component_type = typename decltype(registry)::component_type;
 
     // forces the creation of the pools
@@ -639,7 +639,7 @@ TEST(RuntimeView, Functionalities) {
     registry.reserve<char>(0);
 
     component_type types[] = { registry.type<int>(), registry.type<char>() };
-    auto view = registry.view(std::begin(types), std::end(types));
+    auto view = registry.runtime_view(std::begin(types), std::end(types));
     const auto &cview = view;
 
     ASSERT_TRUE(view.empty());
@@ -654,13 +654,13 @@ TEST(RuntimeView, Functionalities) {
 
     registry.assign<char>(e1);
 
-    auto it = registry.view(std::begin(types), std::end(types)).begin();
+    auto it = registry.runtime_view(std::begin(types), std::end(types)).begin();
 
     ASSERT_EQ(*it, e1);
-    ASSERT_EQ(++it, (registry.view(std::begin(types), std::end(types)).end()));
+    ASSERT_EQ(++it, (registry.runtime_view(std::begin(types), std::end(types)).end()));
 
-    ASSERT_NO_THROW((registry.view(std::begin(types), std::end(types)).begin()++));
-    ASSERT_NO_THROW((++registry.view(std::begin(types), std::end(types)).begin()));
+    ASSERT_NO_THROW((registry.runtime_view(std::begin(types), std::end(types)).begin()++));
+    ASSERT_NO_THROW((++registry.runtime_view(std::begin(types), std::end(types)).begin()));
 
     ASSERT_NE(view.begin(), view.end());
     ASSERT_NE(cview.begin(), cview.end());
@@ -677,7 +677,7 @@ TEST(RuntimeView, Functionalities) {
 }
 
 TEST(RuntimeView, Iterator) {
-    entt::DefaultRegistry registry;
+    entt::registry<> registry;
     using component_type = typename decltype(registry)::component_type;
 
     const auto entity = registry.create();
@@ -685,7 +685,7 @@ TEST(RuntimeView, Iterator) {
     registry.assign<char>(entity);
 
     component_type types[] = { registry.type<int>(), registry.type<char>() };
-    auto view = registry.view(std::begin(types), std::end(types));
+    auto view = registry.runtime_view(std::begin(types), std::end(types));
     using iterator_type = typename decltype(view)::iterator_type;
 
     iterator_type end{view.begin()};
@@ -702,7 +702,7 @@ TEST(RuntimeView, Iterator) {
 }
 
 TEST(RuntimeView, ConstIterator) {
-    entt::DefaultRegistry registry;
+    entt::registry<> registry;
     using component_type = typename decltype(registry)::component_type;
 
     const auto entity = registry.create();
@@ -710,7 +710,7 @@ TEST(RuntimeView, ConstIterator) {
     registry.assign<char>(entity);
 
     component_type types[] = { registry.type<int>(), registry.type<char>() };
-    auto view = registry.view(std::begin(types), std::end(types));
+    auto view = registry.runtime_view(std::begin(types), std::end(types));
     using iterator_type = typename decltype(view)::iterator_type;
 
     iterator_type cend{view.cbegin()};
@@ -727,7 +727,7 @@ TEST(RuntimeView, ConstIterator) {
 }
 
 TEST(RuntimeView, Contains) {
-    entt::DefaultRegistry registry;
+    entt::registry<> registry;
     using component_type = typename decltype(registry)::component_type;
 
     const auto e0 = registry.create();
@@ -741,14 +741,14 @@ TEST(RuntimeView, Contains) {
     registry.destroy(e0);
 
     component_type types[] = { registry.type<int>(), registry.type<char>() };
-    auto view = registry.view(std::begin(types), std::end(types));
+    auto view = registry.runtime_view(std::begin(types), std::end(types));
 
     ASSERT_FALSE(view.contains(e0));
     ASSERT_TRUE(view.contains(e1));
 }
 
 TEST(RuntimeView, Empty) {
-    entt::DefaultRegistry registry;
+    entt::registry<> registry;
     using component_type = typename decltype(registry)::component_type;
 
     const auto e0 = registry.create();
@@ -761,7 +761,7 @@ TEST(RuntimeView, Empty) {
     registry.assign<float>(e1);
 
     component_type types[] = { registry.type<char>(), registry.type<int>(), registry.type<float>() };
-    auto view = registry.view(std::begin(types), std::end(types));
+    auto view = registry.runtime_view(std::begin(types), std::end(types));
 
     for(auto entity: view) {
         (void)entity;
@@ -770,7 +770,7 @@ TEST(RuntimeView, Empty) {
 }
 
 TEST(RuntimeView, Each) {
-    entt::DefaultRegistry registry;
+    entt::registry<> registry;
     using component_type = typename decltype(registry)::component_type;
 
     const auto e0 = registry.create();
@@ -782,7 +782,7 @@ TEST(RuntimeView, Each) {
     registry.assign<char>(e1);
 
     component_type types[] = { registry.type<int>(), registry.type<char>() };
-    auto view = registry.view(std::begin(types), std::end(types));
+    auto view = registry.runtime_view(std::begin(types), std::end(types));
     std::size_t cnt = 0;
 
     view.each([&cnt](auto) { ++cnt; });
@@ -791,7 +791,7 @@ TEST(RuntimeView, Each) {
 }
 
 TEST(RuntimeView, EachWithHoles) {
-    entt::DefaultRegistry registry;
+    entt::registry<> registry;
     using component_type = typename decltype(registry)::component_type;
 
     const auto e0 = registry.create();
@@ -805,7 +805,7 @@ TEST(RuntimeView, EachWithHoles) {
     registry.assign<int>(e2, 2);
 
     component_type types[] = { registry.type<int>(), registry.type<char>() };
-    auto view = registry.view(std::begin(types), std::end(types));
+    auto view = registry.runtime_view(std::begin(types), std::end(types));
 
     view.each([e0](auto entity) {
         ASSERT_EQ(e0, entity);
@@ -813,14 +813,14 @@ TEST(RuntimeView, EachWithHoles) {
 }
 
 TEST(RuntimeView, MissingPool) {
-    entt::DefaultRegistry registry;
+    entt::registry<> registry;
     using component_type = typename decltype(registry)::component_type;
 
     const auto e0 = registry.create();
     registry.assign<int>(e0);
 
     component_type types[] = { registry.type<int>(), registry.type<char>() };
-    auto view = registry.view(std::begin(types), std::end(types));
+    auto view = registry.runtime_view(std::begin(types), std::end(types));
 
     ASSERT_TRUE(view.empty());
     ASSERT_EQ(view.size(), decltype(view.size()){0});
@@ -840,14 +840,14 @@ TEST(RuntimeView, MissingPool) {
 }
 
 TEST(RuntimeView, EmptyRange) {
-    entt::DefaultRegistry registry;
+    entt::registry<> registry;
     using component_type = typename decltype(registry)::component_type;
 
     const auto e0 = registry.create();
     registry.assign<int>(e0);
 
     const component_type *ptr = nullptr;
-    auto view = registry.view(ptr, ptr);
+    auto view = registry.runtime_view(ptr, ptr);
 
     ASSERT_TRUE(view.empty());
     ASSERT_EQ(view.size(), decltype(view.size()){0});

+ 23 - 25
test/entt/locator/locator.cpp

@@ -1,50 +1,48 @@
 #include <gtest/gtest.h>
 #include <entt/locator/locator.hpp>
 
-struct AService {};
+struct a_service {};
 
-struct AnotherService {
-    virtual ~AnotherService() = default;
+struct another_service {
+    virtual ~another_service() = default;
     virtual void f(bool) = 0;
     bool check{false};
 };
 
-struct DerivedService: AnotherService {
-    DerivedService(int): AnotherService{} {}
+struct derived_service: another_service {
+    derived_service(int): another_service{} {}
     void f(bool b) override { check = b; }
 };
 
 TEST(ServiceLocator, Functionalities) {
-    using entt::ServiceLocator;
+    ASSERT_TRUE(entt::service_locator<a_service>::empty());
+    ASSERT_TRUE(entt::service_locator<another_service>::empty());
 
-    ASSERT_TRUE(ServiceLocator<AService>::empty());
-    ASSERT_TRUE(ServiceLocator<AnotherService>::empty());
+    entt::service_locator<a_service>::set();
 
-    ServiceLocator<AService>::set();
+    ASSERT_FALSE(entt::service_locator<a_service>::empty());
+    ASSERT_TRUE(entt::service_locator<another_service>::empty());
 
-    ASSERT_FALSE(ServiceLocator<AService>::empty());
-    ASSERT_TRUE(ServiceLocator<AnotherService>::empty());
+    entt::service_locator<a_service>::reset();
 
-    ServiceLocator<AService>::reset();
+    ASSERT_TRUE(entt::service_locator<a_service>::empty());
+    ASSERT_TRUE(entt::service_locator<another_service>::empty());
 
-    ASSERT_TRUE(ServiceLocator<AService>::empty());
-    ASSERT_TRUE(ServiceLocator<AnotherService>::empty());
+    entt::service_locator<a_service>::set(std::make_shared<a_service>());
 
-    ServiceLocator<AService>::set(std::make_shared<AService>());
+    ASSERT_FALSE(entt::service_locator<a_service>::empty());
+    ASSERT_TRUE(entt::service_locator<another_service>::empty());
 
-    ASSERT_FALSE(ServiceLocator<AService>::empty());
-    ASSERT_TRUE(ServiceLocator<AnotherService>::empty());
+    entt::service_locator<another_service>::set<derived_service>(42);
 
-    ServiceLocator<AnotherService>::set<DerivedService>(42);
+    ASSERT_FALSE(entt::service_locator<a_service>::empty());
+    ASSERT_FALSE(entt::service_locator<another_service>::empty());
 
-    ASSERT_FALSE(ServiceLocator<AService>::empty());
-    ASSERT_FALSE(ServiceLocator<AnotherService>::empty());
+    entt::service_locator<another_service>::get().lock()->f(!entt::service_locator<another_service>::get().lock()->check);
 
-    ServiceLocator<AnotherService>::get().lock()->f(!ServiceLocator<AnotherService>::get().lock()->check);
+    ASSERT_TRUE(entt::service_locator<another_service>::get().lock()->check);
 
-    ASSERT_TRUE(ServiceLocator<AnotherService>::get().lock()->check);
+    entt::service_locator<another_service>::ref().f(!entt::service_locator<another_service>::get().lock()->check);
 
-    ServiceLocator<AnotherService>::ref().f(!ServiceLocator<AnotherService>::get().lock()->check);
-
-    ASSERT_FALSE(ServiceLocator<AnotherService>::get().lock()->check);
+    ASSERT_FALSE(entt::service_locator<another_service>::get().lock()->check);
 }

+ 46 - 46
test/entt/process/process.cpp

@@ -2,36 +2,36 @@
 #include <cstdint>
 #include <entt/process/process.hpp>
 
-struct FakeProcess: entt::Process<FakeProcess, int> {
-    using process_type = entt::Process<FakeProcess, int>;
+struct fake_process: entt::process<fake_process, int> {
+    using process_type = entt::process<fake_process, int>;
 
     void succeed() noexcept { process_type::succeed(); }
     void fail() noexcept { process_type::fail(); }
     void pause() noexcept { process_type::pause(); }
     void unpause() noexcept { process_type::unpause(); }
 
-    void init(void *) { initInvoked = true; }
-    void succeeded() { succeededInvoked = true; }
-    void failed() { failedInvoked = true; }
-    void aborted() { abortedInvoked = true; }
+    void init(void *) { init_invoked = true; }
+    void succeeded() { succeeded_invoked = true; }
+    void failed() { failed_invoked = true; }
+    void aborted() { aborted_invoked = true; }
 
     void update(delta_type, void *data) {
         if(data) {
             (*static_cast<int *>(data))++;
         }
 
-        updateInvoked = true;
+        update_invoked = true;
     }
 
-    bool initInvoked{false};
-    bool updateInvoked{false};
-    bool succeededInvoked{false};
-    bool failedInvoked{false};
-    bool abortedInvoked{false};
+    bool init_invoked{false};
+    bool update_invoked{false};
+    bool succeeded_invoked{false};
+    bool failed_invoked{false};
+    bool aborted_invoked{false};
 };
 
 TEST(Process, Basics) {
-    FakeProcess process;
+    fake_process process;
 
     ASSERT_FALSE(process.alive());
     ASSERT_FALSE(process.dead());
@@ -67,7 +67,7 @@ TEST(Process, Basics) {
 }
 
 TEST(Process, Succeeded) {
-    FakeProcess process;
+    fake_process process;
 
     process.tick(0);
     process.succeed();
@@ -77,15 +77,15 @@ TEST(Process, Succeeded) {
     ASSERT_TRUE(process.dead());
     ASSERT_FALSE(process.paused());
 
-    ASSERT_TRUE(process.initInvoked);
-    ASSERT_TRUE(process.updateInvoked);
-    ASSERT_TRUE(process.succeededInvoked);
-    ASSERT_FALSE(process.failedInvoked);
-    ASSERT_FALSE(process.abortedInvoked);
+    ASSERT_TRUE(process.init_invoked);
+    ASSERT_TRUE(process.update_invoked);
+    ASSERT_TRUE(process.succeeded_invoked);
+    ASSERT_FALSE(process.failed_invoked);
+    ASSERT_FALSE(process.aborted_invoked);
 }
 
 TEST(Process, Fail) {
-    FakeProcess process;
+    fake_process process;
 
     process.tick(0);
     process.fail();
@@ -95,15 +95,15 @@ TEST(Process, Fail) {
     ASSERT_TRUE(process.dead());
     ASSERT_FALSE(process.paused());
 
-    ASSERT_TRUE(process.initInvoked);
-    ASSERT_TRUE(process.updateInvoked);
-    ASSERT_FALSE(process.succeededInvoked);
-    ASSERT_TRUE(process.failedInvoked);
-    ASSERT_FALSE(process.abortedInvoked);
+    ASSERT_TRUE(process.init_invoked);
+    ASSERT_TRUE(process.update_invoked);
+    ASSERT_FALSE(process.succeeded_invoked);
+    ASSERT_TRUE(process.failed_invoked);
+    ASSERT_FALSE(process.aborted_invoked);
 }
 
 TEST(Process, Data) {
-    FakeProcess process;
+    fake_process process;
     int value = 0;
 
     process.tick(0, &value);
@@ -115,15 +115,15 @@ TEST(Process, Data) {
     ASSERT_FALSE(process.paused());
 
     ASSERT_EQ(value, 1);
-    ASSERT_TRUE(process.initInvoked);
-    ASSERT_TRUE(process.updateInvoked);
-    ASSERT_TRUE(process.succeededInvoked);
-    ASSERT_FALSE(process.failedInvoked);
-    ASSERT_FALSE(process.abortedInvoked);
+    ASSERT_TRUE(process.init_invoked);
+    ASSERT_TRUE(process.update_invoked);
+    ASSERT_TRUE(process.succeeded_invoked);
+    ASSERT_FALSE(process.failed_invoked);
+    ASSERT_FALSE(process.aborted_invoked);
 }
 
 TEST(Process, AbortNextTick) {
-    FakeProcess process;
+    fake_process process;
 
     process.tick(0);
     process.abort();
@@ -133,15 +133,15 @@ TEST(Process, AbortNextTick) {
     ASSERT_TRUE(process.dead());
     ASSERT_FALSE(process.paused());
 
-    ASSERT_TRUE(process.initInvoked);
-    ASSERT_TRUE(process.updateInvoked);
-    ASSERT_FALSE(process.succeededInvoked);
-    ASSERT_FALSE(process.failedInvoked);
-    ASSERT_TRUE(process.abortedInvoked);
+    ASSERT_TRUE(process.init_invoked);
+    ASSERT_TRUE(process.update_invoked);
+    ASSERT_FALSE(process.succeeded_invoked);
+    ASSERT_FALSE(process.failed_invoked);
+    ASSERT_TRUE(process.aborted_invoked);
 }
 
 TEST(Process, AbortImmediately) {
-    FakeProcess process;
+    fake_process process;
 
     process.tick(0);
     process.abort(true);
@@ -150,11 +150,11 @@ TEST(Process, AbortImmediately) {
     ASSERT_TRUE(process.dead());
     ASSERT_FALSE(process.paused());
 
-    ASSERT_TRUE(process.initInvoked);
-    ASSERT_TRUE(process.updateInvoked);
-    ASSERT_FALSE(process.succeededInvoked);
-    ASSERT_FALSE(process.failedInvoked);
-    ASSERT_TRUE(process.abortedInvoked);
+    ASSERT_TRUE(process.init_invoked);
+    ASSERT_TRUE(process.update_invoked);
+    ASSERT_FALSE(process.succeeded_invoked);
+    ASSERT_FALSE(process.failed_invoked);
+    ASSERT_TRUE(process.aborted_invoked);
 }
 
 TEST(ProcessAdaptor, Resolved) {
@@ -165,7 +165,7 @@ TEST(ProcessAdaptor, Resolved) {
         resolve();
     };
 
-    auto process = entt::ProcessAdaptor<decltype(lambda), std::uint64_t>{lambda};
+    auto process = entt::process_adaptor<decltype(lambda), std::uint64_t>{lambda};
 
     process.tick(0);
 
@@ -181,7 +181,7 @@ TEST(ProcessAdaptor, Rejected) {
         rejected();
     };
 
-    auto process = entt::ProcessAdaptor<decltype(lambda), std::uint64_t>{lambda};
+    auto process = entt::process_adaptor<decltype(lambda), std::uint64_t>{lambda};
 
     process.tick(0);
 
@@ -197,7 +197,7 @@ TEST(ProcessAdaptor, Data) {
         resolve();
     };
 
-    auto process = entt::ProcessAdaptor<decltype(lambda), std::uint64_t>{lambda};
+    auto process = entt::process_adaptor<decltype(lambda), std::uint64_t>{lambda};
 
     process.tick(0, &value);
 

+ 33 - 33
test/entt/process/scheduler.cpp

@@ -3,19 +3,19 @@
 #include <entt/process/scheduler.hpp>
 #include <entt/process/process.hpp>
 
-struct FooProcess: entt::Process<FooProcess, int> {
-    FooProcess(std::function<void()> onUpdate, std::function<void()> onAborted)
-        : onUpdate{onUpdate}, onAborted{onAborted}
+struct foo_process: entt::process<foo_process, int> {
+    foo_process(std::function<void()> on_update, std::function<void()> on_aborted)
+        : on_update{on_update}, on_aborted{on_aborted}
     {}
 
-    void update(delta_type, void *) { onUpdate(); }
-    void aborted() { onAborted(); }
+    void update(delta_type, void *) { on_update(); }
+    void aborted() { on_aborted(); }
 
-    std::function<void()> onUpdate;
-    std::function<void()> onAborted;
+    std::function<void()> on_update;
+    std::function<void()> on_aborted;
 };
 
-struct SucceededProcess: entt::Process<SucceededProcess, int> {
+struct succeeded_process: entt::process<succeeded_process, int> {
     void update(delta_type, void *) {
         ASSERT_FALSE(updated);
         updated = true;
@@ -27,9 +27,9 @@ struct SucceededProcess: entt::Process<SucceededProcess, int> {
     bool updated = false;
 };
 
-unsigned int SucceededProcess::invoked = 0;
+unsigned int succeeded_process::invoked = 0;
 
-struct FailedProcess: entt::Process<FailedProcess, int> {
+struct failed_process: entt::process<failed_process, int> {
     void update(delta_type, void *) {
         ASSERT_FALSE(updated);
         updated = true;
@@ -40,20 +40,20 @@ struct FailedProcess: entt::Process<FailedProcess, int> {
 };
 
 TEST(Scheduler, Functionalities) {
-    entt::Scheduler<int> scheduler{};
+    entt::scheduler<int> scheduler{};
 
     bool updated = false;
     bool aborted = false;
 
-    ASSERT_EQ(scheduler.size(), entt::Scheduler<int>::size_type{});
+    ASSERT_EQ(scheduler.size(), entt::scheduler<int>::size_type{});
     ASSERT_TRUE(scheduler.empty());
 
-    scheduler.attach<FooProcess>(
+    scheduler.attach<foo_process>(
                 [&updated](){ updated = true; },
                 [&aborted](){ aborted = true; }
     );
 
-    ASSERT_NE(scheduler.size(), entt::Scheduler<int>::size_type{});
+    ASSERT_NE(scheduler.size(), entt::scheduler<int>::size_type{});
     ASSERT_FALSE(scheduler.empty());
 
     scheduler.update(0);
@@ -62,43 +62,43 @@ TEST(Scheduler, Functionalities) {
     ASSERT_TRUE(updated);
     ASSERT_TRUE(aborted);
 
-    ASSERT_NE(scheduler.size(), entt::Scheduler<int>::size_type{});
+    ASSERT_NE(scheduler.size(), entt::scheduler<int>::size_type{});
     ASSERT_FALSE(scheduler.empty());
 
     scheduler.clear();
 
-    ASSERT_EQ(scheduler.size(), entt::Scheduler<int>::size_type{});
+    ASSERT_EQ(scheduler.size(), entt::scheduler<int>::size_type{});
     ASSERT_TRUE(scheduler.empty());
 }
 
 TEST(Scheduler, Then) {
-    entt::Scheduler<int> scheduler;
+    entt::scheduler<int> scheduler;
 
-    scheduler.attach<SucceededProcess>()
-            .then<SucceededProcess>()
-            .then<FailedProcess>()
-            .then<SucceededProcess>();
+    scheduler.attach<succeeded_process>()
+            .then<succeeded_process>()
+            .then<failed_process>()
+            .then<succeeded_process>();
 
     for(auto i = 0; i < 8; ++i) {
         scheduler.update(0);
     }
 
-    ASSERT_EQ(SucceededProcess::invoked, 2u);
+    ASSERT_EQ(succeeded_process::invoked, 2u);
 }
 
 TEST(Scheduler, Functor) {
-    entt::Scheduler<int> scheduler;
+    entt::scheduler<int> scheduler;
 
-    bool firstFunctor = false;
-    bool secondFunctor = false;
+    bool first_functor = false;
+    bool second_functor = false;
 
-    scheduler.attach([&firstFunctor](auto, void *, auto resolve, auto){
-        ASSERT_FALSE(firstFunctor);
-        firstFunctor = true;
+    scheduler.attach([&first_functor](auto, void *, auto resolve, auto){
+        ASSERT_FALSE(first_functor);
+        first_functor = true;
         resolve();
-    }).then([&secondFunctor](auto, void *, auto, auto reject){
-        ASSERT_FALSE(secondFunctor);
-        secondFunctor = true;
+    }).then([&second_functor](auto, void *, auto, auto reject){
+        ASSERT_FALSE(second_functor);
+        second_functor = true;
         reject();
     }).then([](auto...){
         FAIL();
@@ -108,6 +108,6 @@ TEST(Scheduler, Functor) {
         scheduler.update(0);
     }
 
-    ASSERT_TRUE(firstFunctor);
-    ASSERT_TRUE(secondFunctor);
+    ASSERT_TRUE(first_functor);
+    ASSERT_TRUE(second_functor);
 }

+ 25 - 25
test/entt/resource/resource.cpp

@@ -1,51 +1,51 @@
 #include <gtest/gtest.h>
 #include <entt/resource/cache.hpp>
 
-struct Resource { const int value; };
+struct resource { const int value; };
 
-struct Loader: entt::ResourceLoader<Loader, Resource> {
-    std::shared_ptr<Resource> load(int value) const {
-        return std::shared_ptr<Resource>(new Resource{ value });
+struct loader: entt::resource_loader<loader, resource> {
+    std::shared_ptr<resource> load(int value) const {
+        return std::shared_ptr<resource>(new resource{ value });
     }
 };
 
-struct BrokenLoader: entt::ResourceLoader<BrokenLoader, Resource> {
-    std::shared_ptr<Resource> load(int) const {
+struct broken_loader: entt::resource_loader<broken_loader, resource> {
+    std::shared_ptr<resource> load(int) const {
         return nullptr;
     }
 };
 
 TEST(ResourceCache, Functionalities) {
-    entt::ResourceCache<Resource> cache;
+    entt::resource_cache<resource> cache;
 
-    constexpr auto hs1 = entt::HashedString{"res1"};
-    constexpr auto hs2 = entt::HashedString{"res2"};
+    constexpr auto hs1 = entt::hashed_string{"res1"};
+    constexpr auto hs2 = entt::hashed_string{"res2"};
 
-    ASSERT_EQ(cache.size(), entt::ResourceCache<Resource>::size_type{});
+    ASSERT_EQ(cache.size(), entt::resource_cache<resource>::size_type{});
     ASSERT_TRUE(cache.empty());
     ASSERT_FALSE(cache.contains(hs1));
     ASSERT_FALSE(cache.contains(hs2));
 
-    ASSERT_FALSE(cache.load<BrokenLoader>(hs1, 42));
-    ASSERT_FALSE(cache.reload<BrokenLoader>(hs1, 42));
+    ASSERT_FALSE(cache.load<broken_loader>(hs1, 42));
+    ASSERT_FALSE(cache.reload<broken_loader>(hs1, 42));
 
-    ASSERT_EQ(cache.size(), entt::ResourceCache<Resource>::size_type{});
+    ASSERT_EQ(cache.size(), entt::resource_cache<resource>::size_type{});
     ASSERT_TRUE(cache.empty());
     ASSERT_FALSE(cache.contains(hs1));
     ASSERT_FALSE(cache.contains(hs2));
 
-    ASSERT_TRUE(cache.load<Loader>(hs1, 42));
-    ASSERT_TRUE(cache.reload<Loader>(hs1, 42));
+    ASSERT_TRUE(cache.load<loader>(hs1, 42));
+    ASSERT_TRUE(cache.reload<loader>(hs1, 42));
 
-    ASSERT_NE(cache.size(), entt::ResourceCache<Resource>::size_type{});
+    ASSERT_NE(cache.size(), entt::resource_cache<resource>::size_type{});
     ASSERT_FALSE(cache.empty());
     ASSERT_TRUE(cache.contains(hs1));
     ASSERT_FALSE(cache.contains(hs2));
     ASSERT_EQ((*cache.handle(hs1)).value, 42);
 
-    ASSERT_TRUE(cache.load<Loader>(hs2, 42));
+    ASSERT_TRUE(cache.load<loader>(hs2, 42));
 
-    ASSERT_NE(cache.size(), entt::ResourceCache<Resource>::size_type{});
+    ASSERT_NE(cache.size(), entt::resource_cache<resource>::size_type{});
     ASSERT_FALSE(cache.empty());
     ASSERT_TRUE(cache.contains(hs1));
     ASSERT_TRUE(cache.contains(hs2));
@@ -58,28 +58,28 @@ TEST(ResourceCache, Functionalities) {
     ASSERT_TRUE(cache.contains(hs2));
     ASSERT_EQ(cache.handle(hs2)->value, 42);
 
-    ASSERT_TRUE(cache.load<Loader>(hs1, 42));
+    ASSERT_TRUE(cache.load<loader>(hs1, 42));
     ASSERT_NO_THROW(cache.clear());
 
-    ASSERT_EQ(cache.size(), entt::ResourceCache<Resource>::size_type{});
+    ASSERT_EQ(cache.size(), entt::resource_cache<resource>::size_type{});
     ASSERT_TRUE(cache.empty());
     ASSERT_FALSE(cache.contains(hs1));
     ASSERT_FALSE(cache.contains(hs2));
 
-    ASSERT_TRUE(cache.load<Loader>(hs1, 42));
+    ASSERT_TRUE(cache.load<loader>(hs1, 42));
 
-    ASSERT_NE(cache.size(), entt::ResourceCache<Resource>::size_type{});
+    ASSERT_NE(cache.size(), entt::resource_cache<resource>::size_type{});
     ASSERT_FALSE(cache.empty());
     ASSERT_TRUE(cache.handle(hs1));
     ASSERT_FALSE(cache.handle(hs2));
 
     ASSERT_TRUE(cache.handle(hs1));
-    ASSERT_EQ(&cache.handle(hs1).get(), &static_cast<const Resource &>(cache.handle(hs1)));
+    ASSERT_EQ(&cache.handle(hs1).get(), &static_cast<const resource &>(cache.handle(hs1)));
     ASSERT_NO_THROW(cache.clear());
 
-    ASSERT_EQ(cache.size(), entt::ResourceCache<Resource>::size_type{});
+    ASSERT_EQ(cache.size(), entt::resource_cache<resource>::size_type{});
     ASSERT_TRUE(cache.empty());
 
-    ASSERT_TRUE(cache.temp<Loader>(42));
+    ASSERT_TRUE(cache.temp<loader>(42));
     ASSERT_TRUE(cache.empty());
 }

+ 35 - 21
test/entt/signal/delegate.cpp

@@ -1,17 +1,17 @@
 #include <gtest/gtest.h>
 #include <entt/signal/delegate.hpp>
 
-int delegateFunction(int i) {
+int delegate_function(const int &i) {
     return i*i;
 }
 
-struct DelegateFunctor {
+struct delegate_functor {
     int operator()(int i) {
         return i+i;
     }
 };
 
-struct ConstNonConstNoExcept {
+struct const_nonconst_noexcept {
     void f() { ++cnt; }
     void g() noexcept { ++cnt; }
     void h() const { ++cnt; }
@@ -20,15 +20,16 @@ struct ConstNonConstNoExcept {
 };
 
 TEST(Delegate, Functionalities) {
-    entt::Delegate<int(int)> ffdel;
-    entt::Delegate<int(int)> mfdel;
-    DelegateFunctor functor;
+    entt::delegate<int(int)> ffdel;
+    entt::delegate<int(int)> mfdel;
+    delegate_functor functor;
 
     ASSERT_TRUE(ffdel.empty());
     ASSERT_TRUE(mfdel.empty());
+    ASSERT_EQ(ffdel, mfdel);
 
-    ffdel.connect<&delegateFunction>();
-    mfdel.connect<DelegateFunctor, &DelegateFunctor::operator()>(&functor);
+    ffdel.connect<&delegate_function>();
+    mfdel.connect<&delegate_functor::operator()>(&functor);
 
     ASSERT_FALSE(ffdel.empty());
     ASSERT_FALSE(mfdel.empty());
@@ -37,39 +38,52 @@ TEST(Delegate, Functionalities) {
     ASSERT_EQ(mfdel(3), 6);
 
     ffdel.reset();
-    mfdel.reset();
 
     ASSERT_TRUE(ffdel.empty());
-    ASSERT_TRUE(mfdel.empty());
+    ASSERT_FALSE(mfdel.empty());
+
+    ASSERT_EQ(ffdel, entt::delegate<int(int)>{});
+    ASSERT_NE(ffdel, mfdel);
 }
 
 TEST(Delegate, Comparison) {
-    entt::Delegate<int(int)> delegate;
-    entt::Delegate<int(int)> def;
-    delegate.connect<&delegateFunction>();
+    entt::delegate<int(int)> delegate;
+    entt::delegate<int(int)> def;
+    delegate.connect<&delegate_function>();
 
-    ASSERT_EQ(def, entt::Delegate<int(int)>{});
+    ASSERT_EQ(def, entt::delegate<int(int)>{});
     ASSERT_NE(def, delegate);
 
-    ASSERT_TRUE(def == entt::Delegate<int(int)>{});
+    ASSERT_TRUE(def == entt::delegate<int(int)>{});
     ASSERT_TRUE (def != delegate);
 }
 
 TEST(Delegate, ConstNonConstNoExcept) {
-    entt::Delegate<void()> delegate;
-    ConstNonConstNoExcept functor;
+    entt::delegate<void()> delegate;
+    const_nonconst_noexcept functor;
 
-    delegate.connect<ConstNonConstNoExcept, &ConstNonConstNoExcept::f>(&functor);
+    delegate.connect<&const_nonconst_noexcept::f>(&functor);
     delegate();
 
-    delegate.connect<ConstNonConstNoExcept, &ConstNonConstNoExcept::g>(&functor);
+    delegate.connect<&const_nonconst_noexcept::g>(&functor);
     delegate();
 
-    delegate.connect<ConstNonConstNoExcept, &ConstNonConstNoExcept::h>(&functor);
+    delegate.connect<&const_nonconst_noexcept::h>(&functor);
     delegate();
 
-    delegate.connect<ConstNonConstNoExcept, &ConstNonConstNoExcept::i>(&functor);
+    delegate.connect<&const_nonconst_noexcept::i>(&functor);
     delegate();
 
     ASSERT_EQ(functor.cnt, 4);
 }
+
+TEST(Delegate, Constructors) {
+    delegate_functor functor;
+    entt::delegate<int(int)> empty{};
+    entt::delegate<int(int)> func{entt::connect_arg<&delegate_function>};
+    entt::delegate<int(int)> member{entt::connect_arg<&delegate_functor::operator()>, &functor};
+
+    ASSERT_TRUE(empty.empty());
+    ASSERT_FALSE(func.empty());
+    ASSERT_FALSE(member.empty());
+}

+ 17 - 17
test/entt/signal/dispatcher.cpp

@@ -2,39 +2,39 @@
 #include <gtest/gtest.h>
 #include <entt/signal/dispatcher.hpp>
 
-struct AnEvent {};
-struct AnotherEvent {};
+struct an_event {};
+struct another_event {};
 
-struct Receiver {
-    void receive(const AnEvent &) { ++cnt; }
+struct receiver {
+    void receive(const an_event &) { ++cnt; }
     void reset() { cnt = 0; }
     int cnt{0};
 };
 
 TEST(Dispatcher, Functionalities) {
-    entt::Dispatcher dispatcher;
-    Receiver receiver;
+    entt::dispatcher dispatcher;
+    receiver receiver;
 
-    dispatcher.template sink<AnEvent>().connect(&receiver);
-    dispatcher.template trigger<AnEvent>();
-    dispatcher.template enqueue<AnEvent>();
-    dispatcher.template enqueue<AnotherEvent>();
-    dispatcher.update<AnotherEvent>();
+    dispatcher.template sink<an_event>().connect(&receiver);
+    dispatcher.template trigger<an_event>();
+    dispatcher.template enqueue<an_event>();
+    dispatcher.template enqueue<another_event>();
+    dispatcher.update<another_event>();
 
     ASSERT_EQ(receiver.cnt, 1);
 
-    dispatcher.update<AnEvent>();
-    dispatcher.template trigger<AnEvent>();
+    dispatcher.update<an_event>();
+    dispatcher.template trigger<an_event>();
 
     ASSERT_EQ(receiver.cnt, 3);
 
     receiver.reset();
 
-    dispatcher.template sink<AnEvent>().disconnect(&receiver);
-    dispatcher.template trigger<AnEvent>();
-    dispatcher.template enqueue<AnEvent>();
+    dispatcher.template sink<an_event>().disconnect(&receiver);
+    dispatcher.template trigger<an_event>();
+    dispatcher.template enqueue<an_event>();
     dispatcher.update();
-    dispatcher.template trigger<AnEvent>();
+    dispatcher.template trigger<an_event>();
 
     ASSERT_EQ(receiver.cnt, 0);
 }

+ 40 - 40
test/entt/signal/emitter.cpp

@@ -1,117 +1,117 @@
 #include <gtest/gtest.h>
 #include <entt/signal/emitter.hpp>
 
-struct TestEmitter: entt::Emitter<TestEmitter> {};
+struct test_emitter: entt::emitter<test_emitter> {};
 
-struct FooEvent { int i; char c; };
-struct BarEvent {};
+struct foo_event { int i; char c; };
+struct bar_event {};
 
 TEST(Emitter, Clear) {
-    TestEmitter emitter;
+    test_emitter emitter;
 
     ASSERT_TRUE(emitter.empty());
 
-    emitter.on<FooEvent>([](const auto &, const auto &){});
+    emitter.on<foo_event>([](const auto &, const auto &){});
 
     ASSERT_FALSE(emitter.empty());
-    ASSERT_FALSE(emitter.empty<FooEvent>());
-    ASSERT_TRUE(emitter.empty<BarEvent>());
+    ASSERT_FALSE(emitter.empty<foo_event>());
+    ASSERT_TRUE(emitter.empty<bar_event>());
 
-    emitter.clear<BarEvent>();
+    emitter.clear<bar_event>();
 
     ASSERT_FALSE(emitter.empty());
-    ASSERT_FALSE(emitter.empty<FooEvent>());
-    ASSERT_TRUE(emitter.empty<BarEvent>());
+    ASSERT_FALSE(emitter.empty<foo_event>());
+    ASSERT_TRUE(emitter.empty<bar_event>());
 
-    emitter.clear<FooEvent>();
+    emitter.clear<foo_event>();
 
     ASSERT_TRUE(emitter.empty());
-    ASSERT_TRUE(emitter.empty<FooEvent>());
-    ASSERT_TRUE(emitter.empty<BarEvent>());
+    ASSERT_TRUE(emitter.empty<foo_event>());
+    ASSERT_TRUE(emitter.empty<bar_event>());
 
-    emitter.on<FooEvent>([](const auto &, const auto &){});
-    emitter.on<BarEvent>([](const auto &, const auto &){});
+    emitter.on<foo_event>([](const auto &, const auto &){});
+    emitter.on<bar_event>([](const auto &, const auto &){});
 
     ASSERT_FALSE(emitter.empty());
-    ASSERT_FALSE(emitter.empty<FooEvent>());
-    ASSERT_FALSE(emitter.empty<BarEvent>());
+    ASSERT_FALSE(emitter.empty<foo_event>());
+    ASSERT_FALSE(emitter.empty<bar_event>());
 
     emitter.clear();
 
     ASSERT_TRUE(emitter.empty());
-    ASSERT_TRUE(emitter.empty<FooEvent>());
-    ASSERT_TRUE(emitter.empty<BarEvent>());
+    ASSERT_TRUE(emitter.empty<foo_event>());
+    ASSERT_TRUE(emitter.empty<bar_event>());
 }
 
 TEST(Emitter, ClearPublishing) {
-    TestEmitter emitter;
+    test_emitter emitter;
     bool invoked = false;
 
     ASSERT_TRUE(emitter.empty());
 
-    emitter.on<BarEvent>([&invoked](const auto &, auto &em){
+    emitter.on<bar_event>([&invoked](const auto &, auto &em){
         invoked = true;
         em.clear();
     });
 
-    emitter.publish<BarEvent>();
+    emitter.publish<bar_event>();
 
     ASSERT_TRUE(emitter.empty());
     ASSERT_TRUE(invoked);
 }
 
 TEST(Emitter, On) {
-    TestEmitter emitter;
+    test_emitter emitter;
 
-    emitter.on<FooEvent>([](const auto &, const auto &){});
+    emitter.on<foo_event>([](const auto &, const auto &){});
 
     ASSERT_FALSE(emitter.empty());
-    ASSERT_FALSE(emitter.empty<FooEvent>());
+    ASSERT_FALSE(emitter.empty<foo_event>());
 
-    emitter.publish<FooEvent>(0, 'c');
+    emitter.publish<foo_event>(0, 'c');
 
     ASSERT_FALSE(emitter.empty());
-    ASSERT_FALSE(emitter.empty<FooEvent>());
+    ASSERT_FALSE(emitter.empty<foo_event>());
 }
 
 TEST(Emitter, Once) {
-    TestEmitter emitter;
+    test_emitter emitter;
 
-    emitter.once<BarEvent>([](const auto &, const auto &){});
+    emitter.once<bar_event>([](const auto &, const auto &){});
 
     ASSERT_FALSE(emitter.empty());
-    ASSERT_FALSE(emitter.empty<BarEvent>());
+    ASSERT_FALSE(emitter.empty<bar_event>());
 
-    emitter.publish<BarEvent>();
+    emitter.publish<bar_event>();
 
     ASSERT_TRUE(emitter.empty());
-    ASSERT_TRUE(emitter.empty<BarEvent>());
+    ASSERT_TRUE(emitter.empty<bar_event>());
 }
 
 TEST(Emitter, OnceAndErase) {
-    TestEmitter emitter;
+    test_emitter emitter;
 
-    auto conn = emitter.once<FooEvent>([](const auto &, const auto &){});
+    auto conn = emitter.once<foo_event>([](const auto &, const auto &){});
 
     ASSERT_FALSE(emitter.empty());
-    ASSERT_FALSE(emitter.empty<FooEvent>());
+    ASSERT_FALSE(emitter.empty<foo_event>());
 
     emitter.erase(conn);
 
     ASSERT_TRUE(emitter.empty());
-    ASSERT_TRUE(emitter.empty<FooEvent>());
+    ASSERT_TRUE(emitter.empty<foo_event>());
 }
 
 TEST(Emitter, OnAndErase) {
-    TestEmitter emitter;
+    test_emitter emitter;
 
-    auto conn = emitter.on<BarEvent>([](const auto &, const auto &){});
+    auto conn = emitter.on<bar_event>([](const auto &, const auto &){});
 
     ASSERT_FALSE(emitter.empty());
-    ASSERT_FALSE(emitter.empty<BarEvent>());
+    ASSERT_FALSE(emitter.empty<bar_event>());
 
     emitter.erase(conn);
 
     ASSERT_TRUE(emitter.empty());
-    ASSERT_TRUE(emitter.empty<BarEvent>());
+    ASSERT_TRUE(emitter.empty<bar_event>());
 }

+ 72 - 72
test/entt/signal/sigh.cpp

@@ -3,11 +3,11 @@
 #include <gtest/gtest.h>
 #include <entt/signal/sigh.hpp>
 
-struct SigHListener {
+struct sigh_listener {
     static void f(int &v) { v = 42; }
 
     bool g(int) { k = !k; return true; }
-    bool h(int) { return k; }
+    bool h(const int &) { return k; }
 
     void i() {}
     void l() {}
@@ -16,7 +16,7 @@ struct SigHListener {
 };
 
 template<typename Ret>
-struct TestCollectAll {
+struct test_collect_all {
     std::vector<Ret> vec{};
     static int f() { return 42; }
     static int g() { return 42; }
@@ -27,7 +27,7 @@ struct TestCollectAll {
 };
 
 template<>
-struct TestCollectAll<void> {
+struct test_collect_all<void> {
     std::vector<int> vec{};
     static void h() {}
     bool operator()() noexcept {
@@ -36,7 +36,7 @@ struct TestCollectAll<void> {
 };
 
 template<typename Ret>
-struct TestCollectFirst {
+struct test_collect_first {
     std::vector<Ret> vec{};
     static int f() { return 42; }
     bool operator()(Ret r) noexcept {
@@ -45,7 +45,7 @@ struct TestCollectFirst {
     }
 };
 
-struct ConstNonConstNoExcept {
+struct const_nonconst_noexcept {
     void f() { ++cnt; }
     void g() noexcept { ++cnt; }
     void h() const { ++cnt; }
@@ -54,7 +54,7 @@ struct ConstNonConstNoExcept {
 };
 
 TEST(SigH, Lifetime) {
-    using signal = entt::SigH<void(void)>;
+    using signal = entt::sigh<void(void)>;
 
     ASSERT_NO_THROW(signal{});
 
@@ -69,56 +69,56 @@ TEST(SigH, Lifetime) {
 }
 
 TEST(SigH, Comparison) {
-    entt::SigH<void()> sig1;
-    entt::SigH<void()> sig2;
+    entt::sigh<void()> sig1;
+    entt::sigh<void()> sig2;
 
-    SigHListener s1;
-    SigHListener s2;
+    sigh_listener s1;
+    sigh_listener s2;
 
-    sig1.sink().connect<SigHListener, &SigHListener::i>(&s1);
-    sig2.sink().connect<SigHListener, &SigHListener::i>(&s2);
+    sig1.sink().connect<&sigh_listener::i>(&s1);
+    sig2.sink().connect<&sigh_listener::i>(&s2);
 
     ASSERT_FALSE(sig1 == sig2);
     ASSERT_TRUE(sig1 != sig2);
 
-    sig1.sink().disconnect<SigHListener, &SigHListener::i>(&s1);
-    sig2.sink().disconnect<SigHListener, &SigHListener::i>(&s2);
+    sig1.sink().disconnect<&sigh_listener::i>(&s1);
+    sig2.sink().disconnect<&sigh_listener::i>(&s2);
 
-    sig1.sink().connect<SigHListener, &SigHListener::i>(&s1);
-    sig2.sink().connect<SigHListener, &SigHListener::l>(&s1);
+    sig1.sink().connect<&sigh_listener::i>(&s1);
+    sig2.sink().connect<&sigh_listener::l>(&s1);
 
     ASSERT_FALSE(sig1 == sig2);
     ASSERT_TRUE(sig1 != sig2);
 
-    sig1.sink().disconnect<SigHListener, &SigHListener::i>(&s1);
-    sig2.sink().disconnect<SigHListener, &SigHListener::l>(&s1);
+    sig1.sink().disconnect<&sigh_listener::i>(&s1);
+    sig2.sink().disconnect<&sigh_listener::l>(&s1);
 
     ASSERT_TRUE(sig1 == sig2);
     ASSERT_FALSE(sig1 != sig2);
 
-    sig1.sink().connect<SigHListener, &SigHListener::i>(&s1);
-    sig1.sink().connect<SigHListener, &SigHListener::l>(&s1);
-    sig2.sink().connect<SigHListener, &SigHListener::i>(&s1);
-    sig2.sink().connect<SigHListener, &SigHListener::l>(&s1);
+    sig1.sink().connect<&sigh_listener::i>(&s1);
+    sig1.sink().connect<&sigh_listener::l>(&s1);
+    sig2.sink().connect<&sigh_listener::i>(&s1);
+    sig2.sink().connect<&sigh_listener::l>(&s1);
 
     ASSERT_TRUE(sig1 == sig2);
 
-    sig1.sink().disconnect<SigHListener, &SigHListener::i>(&s1);
-    sig1.sink().disconnect<SigHListener, &SigHListener::l>(&s1);
-    sig2.sink().disconnect<SigHListener, &SigHListener::i>(&s1);
-    sig2.sink().disconnect<SigHListener, &SigHListener::l>(&s1);
+    sig1.sink().disconnect<&sigh_listener::i>(&s1);
+    sig1.sink().disconnect<&sigh_listener::l>(&s1);
+    sig2.sink().disconnect<&sigh_listener::i>(&s1);
+    sig2.sink().disconnect<&sigh_listener::l>(&s1);
 
-    sig1.sink().connect<SigHListener, &SigHListener::i>(&s1);
-    sig1.sink().connect<SigHListener, &SigHListener::l>(&s1);
-    sig2.sink().connect<SigHListener, &SigHListener::l>(&s1);
-    sig2.sink().connect<SigHListener, &SigHListener::i>(&s1);
+    sig1.sink().connect<&sigh_listener::i>(&s1);
+    sig1.sink().connect<&sigh_listener::l>(&s1);
+    sig2.sink().connect<&sigh_listener::l>(&s1);
+    sig2.sink().connect<&sigh_listener::i>(&s1);
 
     ASSERT_FALSE(sig1 == sig2);
 }
 
 TEST(SigH, Clear) {
-    entt::SigH<void(int &)> sigh;
-    sigh.sink().connect<&SigHListener::f>();
+    entt::sigh<void(int &)> sigh;
+    sigh.sink().connect<&sigh_listener::f>();
 
     ASSERT_FALSE(sigh.empty());
 
@@ -128,10 +128,10 @@ TEST(SigH, Clear) {
 }
 
 TEST(SigH, Swap) {
-    entt::SigH<void(int &)> sigh1;
-    entt::SigH<void(int &)> sigh2;
+    entt::sigh<void(int &)> sigh1;
+    entt::sigh<void(int &)> sigh2;
 
-    sigh1.sink().connect<&SigHListener::f>();
+    sigh1.sink().connect<&sigh_listener::f>();
 
     ASSERT_FALSE(sigh1.empty());
     ASSERT_TRUE(sigh2.empty());
@@ -143,72 +143,72 @@ TEST(SigH, Swap) {
 }
 
 TEST(SigH, Functions) {
-    entt::SigH<void(int &)> sigh;
+    entt::sigh<void(int &)> sigh;
     int v = 0;
 
-    sigh.sink().connect<&SigHListener::f>();
+    sigh.sink().connect<&sigh_listener::f>();
     sigh.publish(v);
 
     ASSERT_FALSE(sigh.empty());
-    ASSERT_EQ(static_cast<entt::SigH<bool(int)>::size_type>(1), sigh.size());
+    ASSERT_EQ(static_cast<entt::sigh<bool(int)>::size_type>(1), sigh.size());
     ASSERT_EQ(42, v);
 
     v = 0;
-    sigh.sink().disconnect<&SigHListener::f>();
+    sigh.sink().disconnect<&sigh_listener::f>();
     sigh.publish(v);
 
     ASSERT_TRUE(sigh.empty());
-    ASSERT_EQ(static_cast<entt::SigH<bool(int)>::size_type>(0), sigh.size());
+    ASSERT_EQ(static_cast<entt::sigh<bool(int)>::size_type>(0), sigh.size());
     ASSERT_EQ(0, v);
 
-    sigh.sink().connect<&SigHListener::f>();
+    sigh.sink().connect<&sigh_listener::f>();
 }
 
 TEST(SigH, Members) {
-    SigHListener s;
-    SigHListener *ptr = &s;
-    entt::SigH<bool(int)> sigh;
+    sigh_listener s;
+    sigh_listener *ptr = &s;
+    entt::sigh<bool(int)> sigh;
 
-    sigh.sink().connect<SigHListener, &SigHListener::g>(ptr);
+    sigh.sink().connect<&sigh_listener::g>(ptr);
     sigh.publish(42);
 
     ASSERT_TRUE(s.k);
     ASSERT_FALSE(sigh.empty());
-    ASSERT_EQ(static_cast<entt::SigH<bool(int)>::size_type>(1), sigh.size());
+    ASSERT_EQ(static_cast<entt::sigh<bool(int)>::size_type>(1), sigh.size());
 
-    sigh.sink().disconnect<SigHListener, &SigHListener::g>(ptr);
+    sigh.sink().disconnect<&sigh_listener::g>(ptr);
     sigh.publish(42);
 
     ASSERT_TRUE(s.k);
     ASSERT_TRUE(sigh.empty());
-    ASSERT_EQ(static_cast<entt::SigH<bool(int)>::size_type>(0), sigh.size());
+    ASSERT_EQ(static_cast<entt::sigh<bool(int)>::size_type>(0), sigh.size());
 
-    sigh.sink().connect<SigHListener, &SigHListener::g>(ptr);
-    sigh.sink().connect<SigHListener, &SigHListener::h>(ptr);
+    sigh.sink().connect<&sigh_listener::g>(ptr);
+    sigh.sink().connect<&sigh_listener::h>(ptr);
 
     ASSERT_FALSE(sigh.empty());
-    ASSERT_EQ(static_cast<entt::SigH<bool(int)>::size_type>(2), sigh.size());
+    ASSERT_EQ(static_cast<entt::sigh<bool(int)>::size_type>(2), sigh.size());
 
     sigh.sink().disconnect(ptr);
 
     ASSERT_TRUE(sigh.empty());
-    ASSERT_EQ(static_cast<entt::SigH<bool(int)>::size_type>(0), sigh.size());
+    ASSERT_EQ(static_cast<entt::sigh<bool(int)>::size_type>(0), sigh.size());
 }
 
 TEST(SigH, Collector) {
-    entt::SigH<void(), TestCollectAll<void>> sigh_void;
+    entt::sigh<void(), test_collect_all<void>> sigh_void;
 
-    sigh_void.sink().connect<&TestCollectAll<void>::h>();
+    sigh_void.sink().connect<&test_collect_all<void>::h>();
     auto collector_void = sigh_void.collect();
 
     ASSERT_FALSE(sigh_void.empty());
     ASSERT_TRUE(collector_void.vec.empty());
 
-    entt::SigH<int(), TestCollectAll<int>> sigh_all;
+    entt::sigh<int(), test_collect_all<int>> sigh_all;
 
-    sigh_all.sink().connect<&TestCollectAll<int>::f>();
-    sigh_all.sink().connect<&TestCollectAll<int>::f>();
-    sigh_all.sink().connect<&TestCollectAll<int>::g>();
+    sigh_all.sink().connect<&test_collect_all<int>::f>();
+    sigh_all.sink().connect<&test_collect_all<int>::f>();
+    sigh_all.sink().connect<&test_collect_all<int>::g>();
     auto collector_all = sigh_all.collect();
 
     ASSERT_FALSE(sigh_all.empty());
@@ -217,10 +217,10 @@ TEST(SigH, Collector) {
     ASSERT_EQ(42, collector_all.vec[0]);
     ASSERT_EQ(42, collector_all.vec[1]);
 
-    entt::SigH<int(), TestCollectFirst<int>> sigh_first;
+    entt::sigh<int(), test_collect_first<int>> sigh_first;
 
-    sigh_first.sink().connect<&TestCollectFirst<int>::f>();
-    sigh_first.sink().connect<&TestCollectFirst<int>::f>();
+    sigh_first.sink().connect<&test_collect_first<int>::f>();
+    sigh_first.sink().connect<&test_collect_first<int>::f>();
     auto collector_first = sigh_first.collect();
 
     ASSERT_FALSE(sigh_first.empty());
@@ -230,21 +230,21 @@ TEST(SigH, Collector) {
 }
 
 TEST(SigH, ConstNonConstNoExcept) {
-    entt::SigH<void()> sigh;
-    ConstNonConstNoExcept functor;
+    entt::sigh<void()> sigh;
+    const_nonconst_noexcept functor;
 
-    sigh.sink().connect<ConstNonConstNoExcept, &ConstNonConstNoExcept::f>(&functor);
-    sigh.sink().connect<ConstNonConstNoExcept, &ConstNonConstNoExcept::g>(&functor);
-    sigh.sink().connect<ConstNonConstNoExcept, &ConstNonConstNoExcept::h>(&functor);
-    sigh.sink().connect<ConstNonConstNoExcept, &ConstNonConstNoExcept::i>(&functor);
+    sigh.sink().connect<&const_nonconst_noexcept::f>(&functor);
+    sigh.sink().connect<&const_nonconst_noexcept::g>(&functor);
+    sigh.sink().connect<&const_nonconst_noexcept::h>(&functor);
+    sigh.sink().connect<&const_nonconst_noexcept::i>(&functor);
     sigh.publish();
 
     ASSERT_EQ(functor.cnt, 4);
 
-    sigh.sink().disconnect<ConstNonConstNoExcept, &ConstNonConstNoExcept::f>(&functor);
-    sigh.sink().disconnect<ConstNonConstNoExcept, &ConstNonConstNoExcept::g>(&functor);
-    sigh.sink().disconnect<ConstNonConstNoExcept, &ConstNonConstNoExcept::h>(&functor);
-    sigh.sink().disconnect<ConstNonConstNoExcept, &ConstNonConstNoExcept::i>(&functor);
+    sigh.sink().disconnect<&const_nonconst_noexcept::f>(&functor);
+    sigh.sink().disconnect<&const_nonconst_noexcept::g>(&functor);
+    sigh.sink().disconnect<&const_nonconst_noexcept::h>(&functor);
+    sigh.sink().disconnect<&const_nonconst_noexcept::i>(&functor);
     sigh.publish();
 
     ASSERT_EQ(functor.cnt, 4);

+ 139 - 158
test/mod/mod.cpp

@@ -1,4 +1,5 @@
 #include <gtest/gtest.h>
+#include <type_traits>
 #include <cassert>
 #include <map>
 #include <string>
@@ -8,143 +9,125 @@
 template<typename Type>
 struct tag { using type = Type; };
 
-struct Position {
+struct position {
     double x;
     double y;
 };
 
-struct Renderable {};
+struct renderable {};
 
-struct DuktapeRuntime {
+struct duktape_runtime {
     std::map<duk_uint_t, std::string> components;
 };
 
 template<typename Comp>
-duk_ret_t set(duk_context *ctx, entt::DefaultRegistry &registry) {
+duk_ret_t set(duk_context *ctx, entt::registry<> &registry) {
     const auto entity = duk_require_uint(ctx, 0);
-    registry.accommodate<Comp>(entity);
-    return 0;
-}
 
-template<>
-duk_ret_t set<Position>(duk_context *ctx, entt::DefaultRegistry &registry) {
-    const auto entity = duk_require_uint(ctx, 0);
-    const auto x = duk_require_number(ctx, 2);
-    const auto y = duk_require_number(ctx, 3);
-    registry.accommodate<Position>(entity, x, y);
-    return 0;
-}
+    if constexpr(std::is_same_v<Comp, position>) {
+        const auto x = duk_require_number(ctx, 2);
+        const auto y = duk_require_number(ctx, 3);
+        registry.accommodate<position>(entity, x, y);
+    } else if constexpr(std::is_same_v<Comp, duktape_runtime>) {
+        const auto type = duk_require_uint(ctx, 1);
 
-template<>
-duk_ret_t set<DuktapeRuntime>(duk_context *ctx, entt::DefaultRegistry &registry) {
-    const auto entity = duk_require_uint(ctx, 0);
-    const auto type = duk_require_uint(ctx, 1);
+        duk_dup(ctx, 2);
 
-    duk_dup(ctx, 2);
+        if(!registry.has<duktape_runtime>(entity)) {
+            registry.assign<duktape_runtime>(entity).components[type] = duk_json_encode(ctx, -1);
+        } else {
+            registry.get<duktape_runtime>(entity).components[type] = duk_json_encode(ctx, -1);
+        }
 
-    if(!registry.has<DuktapeRuntime>(entity)) {
-        registry.assign<DuktapeRuntime>(entity).components[type] = duk_json_encode(ctx, -1);
+        duk_pop(ctx);
     } else {
-        registry.get<DuktapeRuntime>(entity).components[type] = duk_json_encode(ctx, -1);
+        registry.accommodate<Comp>(entity);
     }
 
-    duk_pop(ctx);
-
     return 0;
 }
 
 template<typename Comp>
-duk_ret_t unset(duk_context *ctx, entt::DefaultRegistry &registry) {
+duk_ret_t unset(duk_context *ctx, entt::registry<> &registry) {
     const auto entity = duk_require_uint(ctx, 0);
-    registry.remove<Comp>(entity);
-    return 0;
-}
 
-template<>
-duk_ret_t unset<DuktapeRuntime>(duk_context *ctx, entt::DefaultRegistry &registry) {
-    const auto entity = duk_require_uint(ctx, 0);
-    const auto type = duk_require_uint(ctx, 1);
+    if constexpr(std::is_same_v<Comp, duktape_runtime>) {
+        const auto type = duk_require_uint(ctx, 1);
 
-    auto &components = registry.get<DuktapeRuntime>(entity).components;
-    assert(components.find(type) != components.cend());
-    components.erase(type);
+        auto &components = registry.get<duktape_runtime>(entity).components;
+        assert(components.find(type) != components.cend());
+        components.erase(type);
 
-    if(components.empty()) {
-        registry.remove<DuktapeRuntime>(entity);
+        if(components.empty()) {
+            registry.remove<duktape_runtime>(entity);
+        }
+    } else {
+        registry.remove<Comp>(entity);
     }
 
     return 0;
 }
 
 template<typename Comp>
-duk_ret_t has(duk_context *ctx, entt::DefaultRegistry &registry) {
+duk_ret_t has(duk_context *ctx, entt::registry<> &registry) {
     const auto entity = duk_require_uint(ctx, 0);
-    duk_push_boolean(ctx, registry.has<Comp>(entity));
-    return 1;
-}
 
-template<>
-duk_ret_t has<DuktapeRuntime>(duk_context *ctx, entt::DefaultRegistry &registry) {
-    const auto entity = duk_require_uint(ctx, 0);
-    duk_push_boolean(ctx, registry.has<DuktapeRuntime>(entity));
+    if constexpr(std::is_same_v<Comp, duktape_runtime>) {
+        duk_push_boolean(ctx, registry.has<duktape_runtime>(entity));
 
-    if(registry.has<DuktapeRuntime>(entity)) {
-        const auto type = duk_require_uint(ctx, 1);
-        const auto &components = registry.get<DuktapeRuntime>(entity).components;
-        duk_push_boolean(ctx, components.find(type) != components.cend());
+        if(registry.has<duktape_runtime>(entity)) {
+            const auto type = duk_require_uint(ctx, 1);
+            const auto &components = registry.get<duktape_runtime>(entity).components;
+            duk_push_boolean(ctx, components.find(type) != components.cend());
+        } else {
+            duk_push_false(ctx);
+        }
     } else {
-        duk_push_false(ctx);
+        duk_push_boolean(ctx, registry.has<Comp>(entity));
     }
 
     return 1;
 }
 
 template<typename Comp>
-duk_ret_t get(duk_context *ctx, entt::DefaultRegistry &registry) {
-    assert(registry.has<Comp>(duk_require_uint(ctx, 0)));
-    duk_push_object(ctx);
-    return 1;
-}
-
-template<>
-duk_ret_t get<Position>(duk_context *ctx, entt::DefaultRegistry &registry) {
-    const auto entity = duk_require_uint(ctx, 0);
-    const auto &position = registry.get<Position>(entity);
-
-    const auto idx = duk_push_object(ctx);
+duk_ret_t get(duk_context *ctx, entt::registry<> &registry) {
+    [[maybe_unused]] const auto entity = duk_require_uint(ctx, 0);
 
-    duk_push_string(ctx, "x");
-    duk_push_number(ctx, position.x);
-    duk_def_prop(ctx, idx, DUK_DEFPROP_HAVE_VALUE);
+    if constexpr(std::is_same_v<Comp, position>) {
+        const auto &pos = registry.get<position>(entity);
 
-    duk_push_string(ctx, "y");
-    duk_push_number(ctx, position.y);
-    duk_def_prop(ctx, idx, DUK_DEFPROP_HAVE_VALUE);
+        const auto idx = duk_push_object(ctx);
 
-    return 1;
-}
+        duk_push_string(ctx, "x");
+        duk_push_number(ctx, pos.x);
+        duk_def_prop(ctx, idx, DUK_DEFPROP_HAVE_VALUE);
 
-template<>
-duk_ret_t get<DuktapeRuntime>(duk_context *ctx, entt::DefaultRegistry &registry) {
-    const auto entity = duk_require_uint(ctx, 0);
-    const auto type = duk_require_uint(ctx, 1);
+        duk_push_string(ctx, "y");
+        duk_push_number(ctx, pos.y);
+        duk_def_prop(ctx, idx, DUK_DEFPROP_HAVE_VALUE);
+    } if constexpr(std::is_same_v<Comp, duktape_runtime>) {
+        const auto type = duk_require_uint(ctx, 1);
 
-    auto &runtime = registry.get<DuktapeRuntime>(entity);
-    assert(runtime.components.find(type) != runtime.components.cend());
+        auto &runtime = registry.get<duktape_runtime>(entity);
+        assert(runtime.components.find(type) != runtime.components.cend());
 
-    duk_push_string(ctx, runtime.components[type].c_str());
-    duk_json_decode(ctx, -1);
+        duk_push_string(ctx, runtime.components[type].c_str());
+        duk_json_decode(ctx, -1);
+    } else {
+        assert(registry.has<Comp>(entity));
+        duk_push_object(ctx);
+    }
 
     return 1;
 }
 
-class DuktapeRegistry {
+class duktape_registry {
     // I'm pretty sure I won't have more than 99 components in the example
-    static constexpr entt::DefaultRegistry::component_type udef = 100;
+    static constexpr entt::registry<>::component_type udef = 100;
 
-    struct Func {
-        using func_type = duk_ret_t(*)(duk_context *, entt::DefaultRegistry &);
-        using test_type = bool(entt::DefaultRegistry:: *)(entt::DefaultRegistry::entity_type) const;
+    struct func_map {
+        using func_type = duk_ret_t(*)(duk_context *, entt::registry<> &);
+        using test_type = bool(entt::registry<>:: *)(entt::registry<>::entity_type) const;
 
         func_type set;
         func_type unset;
@@ -155,29 +138,27 @@ class DuktapeRegistry {
 
     template<typename... Comp>
     void reg() {
-        using accumulator_type = int[];
-        accumulator_type acc = { (func[registry.type<Comp>()] = {
-                                     &::set<Comp>,
-                                     &::unset<Comp>,
-                                     &::has<Comp>,
-                                     &::get<Comp>,
-                                     &entt::DefaultRegistry::has<Comp>
-                                 }, 0)... };
-        (void)acc;
+        ((func[registry.type<Comp>()] = {
+                &::set<Comp>,
+                &::unset<Comp>,
+                &::has<Comp>,
+                &::get<Comp>,
+                &entt::registry<>::has<Comp>
+        }), ...);
     }
 
-    static DuktapeRegistry & instance(duk_context *ctx) {
+    static duktape_registry & instance(duk_context *ctx) {
         duk_push_this(ctx);
 
         duk_push_string(ctx, DUK_HIDDEN_SYMBOL("dreg"));
         duk_get_prop(ctx, -2);
-        auto &dreg = *static_cast<DuktapeRegistry *>(duk_require_pointer(ctx, -1));
+        auto &dreg = *static_cast<duktape_registry *>(duk_require_pointer(ctx, -1));
         duk_pop_2(ctx);
 
         return dreg;
     }
 
-    template<Func::func_type Func::*Op>
+    template<func_map::func_type func_map::*Op>
     static duk_ret_t invoke(duk_context *ctx) {
         auto &dreg = instance(ctx);
         auto &func = dreg.func;
@@ -185,7 +166,7 @@ class DuktapeRegistry {
         auto type = duk_require_uint(ctx, 1);
 
         if(type >= udef) {
-            type = registry.type<DuktapeRuntime>();
+            type = registry.type<duktape_runtime>();
         }
 
         assert(func.find(type) != func.cend());
@@ -194,10 +175,10 @@ class DuktapeRegistry {
     }
 
 public:
-    DuktapeRegistry(entt::DefaultRegistry &registry)
+    duktape_registry(entt::registry<> &registry)
         : registry{registry}
     {
-        reg<Position, Renderable, DuktapeRuntime>();
+        reg<position, renderable, duktape_runtime>();
     }
 
     static duk_ret_t identifier(duk_context *ctx) {
@@ -213,19 +194,19 @@ public:
     }
 
     static duk_ret_t set(duk_context *ctx) {
-        return invoke<&Func::set>(ctx);
+        return invoke<&func_map::set>(ctx);
     }
 
     static duk_ret_t unset(duk_context *ctx) {
-        return invoke<&Func::unset>(ctx);
+        return invoke<&func_map::unset>(ctx);
     }
 
     static duk_ret_t has(duk_context *ctx) {
-        return invoke<&Func::has>(ctx);
+        return invoke<&func_map::has>(ctx);
     }
 
     static duk_ret_t get(duk_context *ctx) {
-        return invoke<&Func::get>(ctx);
+        return invoke<&func_map::get>(ctx);
     }
 
     static duk_ret_t entities(duk_context *ctx) {
@@ -235,8 +216,8 @@ public:
 
         duk_push_array(ctx);
 
-        std::vector<typename entt::DefaultRegistry::component_type> components;
-        std::vector<typename entt::DefaultRegistry::component_type> runtime;
+        std::vector<typename entt::registry<>::component_type> components;
+        std::vector<typename entt::registry<>::component_type> runtime;
 
         for(duk_idx_t arg = 0; arg < nargs; arg++) {
             auto type = duk_require_uint(ctx, arg);
@@ -245,21 +226,21 @@ public:
                 components.push_back(type);
             } else {
                 if(runtime.empty()) {
-                    components.push_back(dreg.registry.type<DuktapeRuntime>());
+                    components.push_back(dreg.registry.type<duktape_runtime>());
                 }
 
                 runtime.push_back(type);
             }
         }
 
-        auto view = dreg.registry.view(components.cbegin(), components.cend());
+        auto view = dreg.registry.runtime_view(components.cbegin(), components.cend());
 
         for(const auto entity: view) {
             if(runtime.empty()) {
                 duk_push_uint(ctx, entity);
                 duk_put_prop_index(ctx, -2, pos++);
             } else {
-                const auto &components = dreg.registry.get<DuktapeRuntime>(entity).components;
+                const auto &components = dreg.registry.get<duktape_runtime>(entity).components;
                 const auto match = std::all_of(runtime.cbegin(), runtime.cend(), [&components](const auto type) {
                     return components.find(type) != components.cend();
                 });
@@ -275,23 +256,23 @@ public:
     }
 
 private:
-    std::map<duk_uint_t, Func> func;
-    entt::DefaultRegistry &registry;
+    std::map<duk_uint_t, func_map> func;
+    entt::registry<> &registry;
 };
 
-const duk_function_list_entry js_DuktapeRegistry_methods[] = {
-    { "identifier", &DuktapeRegistry::identifier, 0 },
-    { "create", &DuktapeRegistry::create, 0 },
-    { "set", &DuktapeRegistry::set, DUK_VARARGS },
-    { "unset", &DuktapeRegistry::unset, 2 },
-    { "has", &DuktapeRegistry::has, 2 },
-    { "get", &DuktapeRegistry::get, 2 },
-    { "entities", &DuktapeRegistry::entities, DUK_VARARGS },
+const duk_function_list_entry js_duktape_registry_methods[] = {
+    { "identifier", &duktape_registry::identifier, 0 },
+    { "create", &duktape_registry::create, 0 },
+    { "set", &duktape_registry::set, DUK_VARARGS },
+    { "unset", &duktape_registry::unset, 2 },
+    { "has", &duktape_registry::has, 2 },
+    { "get", &duktape_registry::get, 2 },
+    { "entities", &duktape_registry::entities, DUK_VARARGS },
     { nullptr, nullptr, 0 }
 };
 
-void exportTypes(duk_context *ctx, entt::DefaultRegistry &registry) {
-    auto exportType = [](auto *ctx, auto &registry, auto idx, auto type, const auto *name) {
+void export_types(duk_context *ctx, entt::registry<> &registry) {
+    auto export_type = [](auto *ctx, auto &registry, auto idx, auto type, const auto *name) {
         duk_push_string(ctx, name);
         duk_push_uint(ctx, registry.template type<typename decltype(type)::type>());
         duk_def_prop(ctx, idx, DUK_DEFPROP_HAVE_VALUE | DUK_DEFPROP_CLEAR_WRITABLE);
@@ -299,34 +280,34 @@ void exportTypes(duk_context *ctx, entt::DefaultRegistry &registry) {
 
     auto idx = duk_push_object(ctx);
 
-    exportType(ctx, registry, idx, tag<Position>{}, "POSITION");
-    exportType(ctx, registry, idx, tag<Renderable>{}, "RENDERABLE");
+    export_type(ctx, registry, idx, tag<position>{}, "position");
+    export_type(ctx, registry, idx, tag<renderable>{}, "renderable");
 
     duk_put_global_string(ctx, "Types");
 }
 
-void exportDuktapeRegistry(duk_context *ctx, DuktapeRegistry &dreg) {
+void export_duktape_registry(duk_context *ctx, duktape_registry &dreg) {
     auto idx = duk_push_object(ctx);
 
     duk_push_string(ctx, DUK_HIDDEN_SYMBOL("dreg"));
     duk_push_pointer(ctx, &dreg);
     duk_put_prop(ctx, idx);
 
-    duk_put_function_list(ctx, idx, js_DuktapeRegistry_methods);
+    duk_put_function_list(ctx, idx, js_duktape_registry_methods);
     duk_put_global_string(ctx, "Registry");
 }
 
 TEST(Mod, Duktape) {
-    entt::DefaultRegistry registry;
-    DuktapeRegistry dreg{registry};
+    entt::registry<> registry;
+    duktape_registry dreg{registry};
     duk_context *ctx = duk_create_heap_default();
 
     if(!ctx) {
         FAIL();
     }
 
-    exportTypes(ctx, registry);
-    exportDuktapeRegistry(ctx, dreg);
+    export_types(ctx, registry);
+    export_duktape_registry(ctx, dreg);
 
     const char *s0 = ""
             "Types[\"PLAYING_CHARACTER\"] = Registry.identifier();"
@@ -338,33 +319,33 @@ TEST(Mod, Duktape) {
     }
 
     const auto e0 = registry.create();
-    registry.assign<Position>(e0, 0., 0.);
-    registry.assign<Renderable>(e0);
+    registry.assign<position>(e0, 0., 0.);
+    registry.assign<renderable>(e0);
 
     const auto e1 = registry.create();
-    registry.assign<Position>(e1, 0., 0.);
+    registry.assign<position>(e1, 0., 0.);
 
     const char *s1 = ""
-            "Registry.entities(Types.POSITION, Types.RENDERABLE).forEach(function(entity) {"
-                "Registry.set(entity, Types.POSITION, 100., 100.);"
+            "Registry.entities(Types.position, Types.renderable).forEach(function(entity) {"
+                "Registry.set(entity, Types.position, 100., 100.);"
             "});"
             "var entity = Registry.create();"
-            "Registry.set(entity, Types.POSITION, 100., 100.);"
-            "Registry.set(entity, Types.RENDERABLE);"
+            "Registry.set(entity, Types.position, 100., 100.);"
+            "Registry.set(entity, Types.renderable);"
             "";
 
     if(duk_peval_string(ctx, s1)) {
         FAIL();
     }
 
-    ASSERT_EQ(registry.view<DuktapeRuntime>().size(), 0u);
-    ASSERT_EQ(registry.view<Position>().size(), 3u);
-    ASSERT_EQ(registry.view<Renderable>().size(), 2u);
+    ASSERT_EQ(registry.view<duktape_runtime>().size(), 0u);
+    ASSERT_EQ(registry.view<position>().size(), 3u);
+    ASSERT_EQ(registry.view<renderable>().size(), 2u);
 
-    registry.view<Position>().each([&registry](auto entity, const auto &position) {
-        ASSERT_FALSE(registry.has<DuktapeRuntime>(entity));
+    registry.view<position>().each([&registry](auto entity, const auto &position) {
+        ASSERT_FALSE(registry.has<duktape_runtime>(entity));
 
-        if(registry.has<Renderable>(entity)) {
+        if(registry.has<renderable>(entity)) {
             ASSERT_EQ(position.x, 100.);
             ASSERT_EQ(position.y, 100.);
         } else {
@@ -374,8 +355,8 @@ TEST(Mod, Duktape) {
     });
 
     const char *s2 = ""
-            "Registry.entities(Types.POSITION).forEach(function(entity) {"
-                "if(!Registry.has(entity, Types.RENDERABLE)) {"
+            "Registry.entities(Types.position).forEach(function(entity) {"
+                "if(!Registry.has(entity, Types.renderable)) {"
                     "Registry.set(entity, Types.VELOCITY, { \"dx\": -100., \"dy\": -100. });"
                     "Registry.set(entity, Types.PLAYING_CHARACTER, {});"
                 "}"
@@ -386,18 +367,18 @@ TEST(Mod, Duktape) {
         FAIL();
     }
 
-    ASSERT_EQ(registry.view<DuktapeRuntime>().size(), 1u);
-    ASSERT_EQ(registry.view<Position>().size(), 3u);
-    ASSERT_EQ(registry.view<Renderable>().size(), 2u);
+    ASSERT_EQ(registry.view<duktape_runtime>().size(), 1u);
+    ASSERT_EQ(registry.view<position>().size(), 3u);
+    ASSERT_EQ(registry.view<renderable>().size(), 2u);
 
-    registry.view<DuktapeRuntime>().each([](auto, const DuktapeRuntime &runtime) {
+    registry.view<duktape_runtime>().each([](auto, const duktape_runtime &runtime) {
         ASSERT_EQ(runtime.components.size(), 2u);
     });
 
     const char *s3 = ""
-            "Registry.entities(Types.POSITION, Types.RENDERABLE, Types.VELOCITY, Types.PLAYING_CHARACTER).forEach(function(entity) {"
+            "Registry.entities(Types.position, Types.renderable, Types.VELOCITY, Types.PLAYING_CHARACTER).forEach(function(entity) {"
                 "var velocity = Registry.get(entity, Types.VELOCITY);"
-                "Registry.set(entity, Types.POSITION, velocity.dx, velocity.dy)"
+                "Registry.set(entity, Types.position, velocity.dx, velocity.dy)"
             "});"
             "";
 
@@ -405,11 +386,11 @@ TEST(Mod, Duktape) {
         FAIL();
     }
 
-    ASSERT_EQ(registry.view<DuktapeRuntime>().size(), 1u);
-    ASSERT_EQ(registry.view<Position>().size(), 3u);
-    ASSERT_EQ(registry.view<Renderable>().size(), 2u);
+    ASSERT_EQ(registry.view<duktape_runtime>().size(), 1u);
+    ASSERT_EQ(registry.view<position>().size(), 3u);
+    ASSERT_EQ(registry.view<renderable>().size(), 2u);
 
-    registry.view<Position, Renderable, DuktapeRuntime>().each([](auto, const Position &position, const auto &...) {
+    registry.view<position, renderable, duktape_runtime>().each([](auto, const position &position, const auto &...) {
         ASSERT_EQ(position.x, -100.);
         ASSERT_EQ(position.y, -100.);
     });
@@ -419,8 +400,8 @@ TEST(Mod, Duktape) {
                 "Registry.unset(entity, Types.VELOCITY);"
                 "Registry.unset(entity, Types.PLAYING_CHARACTER);"
             "});"
-            "Registry.entities(Types.POSITION).forEach(function(entity) {"
-                "Registry.unset(entity, Types.POSITION);"
+            "Registry.entities(Types.position).forEach(function(entity) {"
+                "Registry.unset(entity, Types.position);"
             "});"
             "";
 
@@ -428,9 +409,9 @@ TEST(Mod, Duktape) {
         FAIL();
     }
 
-    ASSERT_EQ(registry.view<DuktapeRuntime>().size(), 0u);
-    ASSERT_EQ(registry.view<Position>().size(), 0u);
-    ASSERT_EQ(registry.view<Renderable>().size(), 2u);
+    ASSERT_EQ(registry.view<duktape_runtime>().size(), 0u);
+    ASSERT_EQ(registry.view<position>().size(), 0u);
+    ASSERT_EQ(registry.view<renderable>().size(), 2u);
 
     duk_destroy_heap(ctx);
 }

+ 62 - 62
test/snapshot/snapshot.cpp

@@ -4,54 +4,54 @@
 #include <cereal/archives/json.hpp>
 #include <entt/entity/registry.hpp>
 
-struct Position {
+struct position {
     float x;
     float y;
 };
 
-struct Timer {
+struct timer {
     int duration;
     int elapsed{0};
 };
 
-struct Relationship {
-    entt::DefaultRegistry::entity_type parent;
+struct relationship {
+    entt::registry<>::entity_type parent;
 };
 
 template<typename Archive>
-void serialize(Archive &archive, Position &position) {
+void serialize(Archive &archive, position &position) {
   archive(position.x, position.y);
 }
 
 template<typename Archive>
-void serialize(Archive &archive, Timer &timer) {
+void serialize(Archive &archive, timer &timer) {
   archive(timer.duration);
 }
 
 template<typename Archive>
-void serialize(Archive &archive, Relationship &relationship) {
+void serialize(Archive &archive, relationship &relationship) {
   archive(relationship.parent);
 }
 
 TEST(Snapshot, Full) {
     std::stringstream storage;
 
-    entt::DefaultRegistry source;
-    entt::DefaultRegistry destination;
+    entt::registry<> source;
+    entt::registry<> destination;
 
     auto e0 = source.create();
-    source.assign<Position>(e0, 16.f, 16.f);
+    source.assign<position>(e0, 16.f, 16.f);
 
     source.destroy(source.create());
 
     auto e1 = source.create();
-    source.assign<Position>(e1, .8f, .0f);
-    source.assign<Relationship>(e1, e0);
+    source.assign<position>(e1, .8f, .0f);
+    source.assign<relationship>(e1, e0);
 
     auto e2 = source.create();
 
     auto e3 = source.create();
-    source.assign<Timer>(e3, 1000, 100);
+    source.assign<timer>(e3, 1000, 100);
 
     source.destroy(e2);
     auto v2 = source.current(e2);
@@ -60,41 +60,41 @@ TEST(Snapshot, Full) {
         // output finishes flushing its contents when it goes out of scope
         cereal::JSONOutputArchive output{storage};
         source.snapshot().entities(output).destroyed(output)
-                .component<Position, Timer, Relationship>(output);
+                .component<position, timer, relationship>(output);
     }
 
     cereal::JSONInputArchive input{storage};
-    destination.restore().entities(input).destroyed(input)
-            .component<Position, Timer, Relationship>(input);
+    destination.loader().entities(input).destroyed(input)
+            .component<position, timer, relationship>(input);
 
     ASSERT_TRUE(destination.valid(e0));
-    ASSERT_TRUE(destination.has<Position>(e0));
-    ASSERT_EQ(destination.get<Position>(e0).x, 16.f);
-    ASSERT_EQ(destination.get<Position>(e0).y, 16.f);
+    ASSERT_TRUE(destination.has<position>(e0));
+    ASSERT_EQ(destination.get<position>(e0).x, 16.f);
+    ASSERT_EQ(destination.get<position>(e0).y, 16.f);
 
     ASSERT_TRUE(destination.valid(e1));
-    ASSERT_TRUE(destination.has<Position>(e1));
-    ASSERT_EQ(destination.get<Position>(e1).x, .8f);
-    ASSERT_EQ(destination.get<Position>(e1).y, .0f);
-    ASSERT_TRUE(destination.has<Relationship>(e1));
-    ASSERT_EQ(destination.get<Relationship>(e1).parent, e0);
+    ASSERT_TRUE(destination.has<position>(e1));
+    ASSERT_EQ(destination.get<position>(e1).x, .8f);
+    ASSERT_EQ(destination.get<position>(e1).y, .0f);
+    ASSERT_TRUE(destination.has<relationship>(e1));
+    ASSERT_EQ(destination.get<relationship>(e1).parent, e0);
 
     ASSERT_FALSE(destination.valid(e2));
     ASSERT_EQ(destination.current(e2), v2);
 
     ASSERT_TRUE(destination.valid(e3));
-    ASSERT_TRUE(destination.has<Timer>(e3));
-    ASSERT_EQ(destination.get<Timer>(e3).duration, 1000);
-    ASSERT_EQ(destination.get<Timer>(e3).elapsed, 0);
+    ASSERT_TRUE(destination.has<timer>(e3));
+    ASSERT_EQ(destination.get<timer>(e3).duration, 1000);
+    ASSERT_EQ(destination.get<timer>(e3).elapsed, 0);
 }
 
 TEST(Snapshot, Continuous) {
     std::stringstream storage;
 
-    entt::DefaultRegistry source;
-    entt::DefaultRegistry destination;
+    entt::registry<> source;
+    entt::registry<> destination;
 
-    std::vector<entt::DefaultRegistry::entity_type> entities;
+    std::vector<entt::registry<>::entity_type> entities;
     for(auto i = 0; i < 10; ++i) {
         entities.push_back(source.create());
     }
@@ -104,32 +104,32 @@ TEST(Snapshot, Continuous) {
     }
 
     auto e0 = source.create();
-    source.assign<Position>(e0, 0.f, 0.f);
-    source.assign<Relationship>(e0, e0);
+    source.assign<position>(e0, 0.f, 0.f);
+    source.assign<relationship>(e0, e0);
 
     auto e1 = source.create();
-    source.assign<Position>(e1, 1.f, 1.f);
-    source.assign<Relationship>(e1, e0);
+    source.assign<position>(e1, 1.f, 1.f);
+    source.assign<relationship>(e1, e0);
 
     auto e2 = source.create();
-    source.assign<Position>(e2, .2f, .2f);
-    source.assign<Relationship>(e2, e0);
+    source.assign<position>(e2, .2f, .2f);
+    source.assign<relationship>(e2, e0);
 
     auto e3 = source.create();
-    source.assign<Timer>(e3, 1000, 1000);
-    source.assign<Relationship>(e3, e2);
+    source.assign<timer>(e3, 1000, 1000);
+    source.assign<relationship>(e3, e2);
 
     {
         // output finishes flushing its contents when it goes out of scope
         cereal::JSONOutputArchive output{storage};
-        source.snapshot().entities(output).component<Position, Relationship, Timer>(output);
+        source.snapshot().entities(output).component<position, relationship, timer>(output);
     }
 
     cereal::JSONInputArchive input{storage};
-    entt::ContinuousLoader<entt::DefaultRegistry::entity_type> loader{destination};
+    entt::continuous_loader<entt::registry<>::entity_type> loader{destination};
     loader.entities(input)
-            .component<Position, Relationship>(input, &Relationship::parent)
-            .component<Timer>(input);
+            .component<position, relationship>(input, &relationship::parent)
+            .component<timer>(input);
 
     ASSERT_FALSE(destination.valid(e0));
     ASSERT_TRUE(loader.has(e0));
@@ -137,11 +137,11 @@ TEST(Snapshot, Continuous) {
     auto l0 = loader.map(e0);
 
     ASSERT_TRUE(destination.valid(l0));
-    ASSERT_TRUE(destination.has<Position>(l0));
-    ASSERT_EQ(destination.get<Position>(l0).x, 0.f);
-    ASSERT_EQ(destination.get<Position>(l0).y, 0.f);
-    ASSERT_TRUE(destination.has<Relationship>(l0));
-    ASSERT_EQ(destination.get<Relationship>(l0).parent, l0);
+    ASSERT_TRUE(destination.has<position>(l0));
+    ASSERT_EQ(destination.get<position>(l0).x, 0.f);
+    ASSERT_EQ(destination.get<position>(l0).y, 0.f);
+    ASSERT_TRUE(destination.has<relationship>(l0));
+    ASSERT_EQ(destination.get<relationship>(l0).parent, l0);
 
     ASSERT_FALSE(destination.valid(e1));
     ASSERT_TRUE(loader.has(e1));
@@ -149,11 +149,11 @@ TEST(Snapshot, Continuous) {
     auto l1 = loader.map(e1);
 
     ASSERT_TRUE(destination.valid(l1));
-    ASSERT_TRUE(destination.has<Position>(l1));
-    ASSERT_EQ(destination.get<Position>(l1).x, 1.f);
-    ASSERT_EQ(destination.get<Position>(l1).y, 1.f);
-    ASSERT_TRUE(destination.has<Relationship>(l1));
-    ASSERT_EQ(destination.get<Relationship>(l1).parent, l0);
+    ASSERT_TRUE(destination.has<position>(l1));
+    ASSERT_EQ(destination.get<position>(l1).x, 1.f);
+    ASSERT_EQ(destination.get<position>(l1).y, 1.f);
+    ASSERT_TRUE(destination.has<relationship>(l1));
+    ASSERT_EQ(destination.get<relationship>(l1).parent, l0);
 
     ASSERT_FALSE(destination.valid(e2));
     ASSERT_TRUE(loader.has(e2));
@@ -161,11 +161,11 @@ TEST(Snapshot, Continuous) {
     auto l2 = loader.map(e2);
 
     ASSERT_TRUE(destination.valid(l2));
-    ASSERT_TRUE(destination.has<Position>(l2));
-    ASSERT_EQ(destination.get<Position>(l2).x, .2f);
-    ASSERT_EQ(destination.get<Position>(l2).y, .2f);
-    ASSERT_TRUE(destination.has<Relationship>(l2));
-    ASSERT_EQ(destination.get<Relationship>(l2).parent, l0);
+    ASSERT_TRUE(destination.has<position>(l2));
+    ASSERT_EQ(destination.get<position>(l2).x, .2f);
+    ASSERT_EQ(destination.get<position>(l2).y, .2f);
+    ASSERT_TRUE(destination.has<relationship>(l2));
+    ASSERT_EQ(destination.get<relationship>(l2).parent, l0);
 
     ASSERT_FALSE(destination.valid(e3));
     ASSERT_TRUE(loader.has(e3));
@@ -173,9 +173,9 @@ TEST(Snapshot, Continuous) {
     auto l3 = loader.map(e3);
 
     ASSERT_TRUE(destination.valid(l3));
-    ASSERT_TRUE(destination.has<Timer>(l3));
-    ASSERT_EQ(destination.get<Timer>(l3).duration, 1000);
-    ASSERT_EQ(destination.get<Timer>(l3).elapsed, 0);
-    ASSERT_TRUE(destination.has<Relationship>(l3));
-    ASSERT_EQ(destination.get<Relationship>(l3).parent, l2);
+    ASSERT_TRUE(destination.has<timer>(l3));
+    ASSERT_EQ(destination.get<timer>(l3).duration, 1000);
+    ASSERT_EQ(destination.get<timer>(l3).elapsed, 0);
+    ASSERT_TRUE(destination.has<relationship>(l3));
+    ASSERT_EQ(destination.get<relationship>(l3).parent, l2);
 }

Some files were not shown because too many files changed in this diff