moved tags from entity/helper to core/type_traits (see #419)

This commit is contained in:
Michele Caini
2020-02-18 09:58:28 +01:00
parent 652e569afc
commit d9f93ccc11
6 changed files with 53 additions and 63 deletions

View File

@@ -14,6 +14,9 @@
* [Monostate](#monostate)
* [Type info](#type-info)
* [Almost unique identifiers](#almost-unique-identifiers)
* [Traits](#traits)
* [Member class type](#member-class-type)
* [Tags](#tags)
<!--
@endcond TURN_OFF_DOXYGEN
-->
@@ -256,3 +259,38 @@ many others. As already mentioned above, since users have full control over
their types, this problem is in any case easy to solve and should not worry too
much.<br/>
In all likelihood, it will never happen to run into a conflict anyway.
# Traits
This section contains a handful of utilities and traits not present in the
standard template library but which can be useful in everyday life.
## Member class type
The `auto` template parameter introduced with C++17 made it possible to simplify
many class templates and template functions but also made the class type opaque
when members are passed as template arguments.<br/>
The purpose of this utility is to extract the class type in a few lines of code:
```cpp
template<typename Member>
using clazz = entt::member_class_t<Member>;
```
## Tags
Since in `EnTT` the type identified by `ENTT_ID_TYPE` is very important and
widely used, there is a more user-friendly shortcut for the creation of integral
constants based on it.<br/>
This shortcut is the alias template `entt::tag`.
If used in combination with hashed strings, it helps to use human-readable names
where types would be required otherwise. As an example:
```cpp
registry.assign<entt::tag<"enemy"_hs>>(entity);
```
However, this isn't the only permitted use. Literally any value convertible to
`ENTT_ID_TYPE` is a good candidate, such as the named constants of an unscoped
enum.

View File

@@ -20,7 +20,6 @@
* [Null entity](#null-entity)
* [Stamp](#stamp)
* [Dependencies](#dependencies)
* [Tags](#tags)
* [Actor](#actor)
* [Context variables](#context-variables)
* [Meet the runtime](#meet-the-runtime)
@@ -626,20 +625,6 @@ There are many other types of dependencies. In general, most of the functions
that accept an entity as the first argument are good candidates for this
purpose.
### Tags
There's nothing magical about the way tags can be assigned to entities while
avoiding a performance hit at runtime. Nonetheless, the syntax can be annoying
and that's why a more user-friendly shortcut is provided to do it.<br/>
This shortcut is the alias template `entt::tag`.
If used in combination with hashed strings, it helps to use tags where types
would be required otherwise. As an example:
```cpp
registry.assign<entt::tag<"enemy"_hs>>(entity);
```
### Actor
The `actor` class is designed for those who don't feel immediately comfortable

View File

@@ -201,6 +201,14 @@ template<typename Member>
using member_class_t = typename member_class<Member>::type;
/**
* @brief Alias template to ease the creation of named values.
* @tparam Value A constant value at least convertible to `ENTT_ID_TYPE`.
*/
template<ENTT_ID_TYPE Value>
using tag = std::integral_constant<ENTT_ID_TYPE, Value>;
}

View File

@@ -142,29 +142,6 @@ template<typename Entity>
as_group(const basic_registry<Entity> &) ENTT_NOEXCEPT -> as_group<true, Entity>;
/**
* @brief Alias template to ease the assignment of tags to entities.
*
* If used in combination with hashed strings, it simplifies the assignment of
* tags to entities and the use of tags in general where a type would be
* required otherwise.<br/>
* As an example and where the user defined literal for hashed strings hasn't
* been changed:
* @code{.cpp}
* entt::registry registry;
* registry.assign<entt::tag<"enemy"_hs>>(entity);
* @endcode
*
* @note
* Tags are empty components and therefore candidates for the empty component
* optimization.
*
* @tparam Value The numeric representation of an instance of hashed string.
*/
template<ENTT_ID_TYPE Value>
using tag = std::integral_constant<ENTT_ID_TYPE, Value>;
}

View File

@@ -1,4 +1,6 @@
#include <gtest/gtest.h>
#include <entt/config/config.h>
#include <entt/core/hashed_string.hpp>
#include <entt/core/type_traits.hpp>
TEST(Choice, Functionalities) {
@@ -34,3 +36,8 @@ TEST(MemberClass, Functionalities) {
ASSERT_TRUE((std::is_same_v<clazz, entt::member_class_t<decltype(&clazz::bar)>>));
ASSERT_TRUE((std::is_same_v<clazz, entt::member_class_t<decltype(&clazz::quux)>>));
}
TEST(Tag, Functionalities) {
ASSERT_EQ(entt::tag<"foobar"_hs>::value, entt::hashed_string::value("foobar"));
ASSERT_TRUE((std::is_same_v<typename entt::tag<"foobar"_hs>::value_type, ENTT_ID_TYPE>));
}

View File

@@ -22,28 +22,3 @@ TEST(Helper, AsGroup) {
([](entt::group<entt::exclude_t<int>, entt::get_t<const char>, double>) {})(entt::as_group{registry});
([](entt::group<entt::exclude_t<int>, entt::get_t<const char>, const double>) {})(entt::as_group{registry});
}
TEST(Helper, Tag) {
entt::registry registry;
const auto entity = registry.create();
registry.assign<entt::tag<"foobar"_hs>>(entity);
registry.assign<int>(entity, 42);
int counter{};
ASSERT_FALSE(registry.has<entt::tag<"barfoo"_hs>>(entity));
ASSERT_TRUE(registry.has<entt::tag<"foobar"_hs>>(entity));
for(auto entt: registry.view<int, entt::tag<"foobar"_hs>>()) {
(void)entt;
++counter;
}
ASSERT_NE(counter, 0);
for(auto entt: registry.view<entt::tag<"foobar"_hs>>()) {
(void)entt;
--counter;
}
ASSERT_EQ(counter, 0);
}