Browse Source

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

Michele Caini 6 years ago
parent
commit
d9f93ccc11

+ 38 - 0
docs/md/core.md

@@ -14,6 +14,9 @@
 * [Monostate](#monostate)
 * [Monostate](#monostate)
 * [Type info](#type-info)
 * [Type info](#type-info)
   * [Almost unique identifiers](#almost-unique-identifiers)
   * [Almost unique identifiers](#almost-unique-identifiers)
+* [Traits](#traits)
+  * [Member class type](#member-class-type)
+  * [Tags](#tags)
 <!--
 <!--
 @endcond TURN_OFF_DOXYGEN
 @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
 their types, this problem is in any case easy to solve and should not worry too
 much.<br/>
 much.<br/>
 In all likelihood, it will never happen to run into a conflict anyway.
 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.

+ 0 - 15
docs/md/entity.md

@@ -20,7 +20,6 @@
     * [Null entity](#null-entity)
     * [Null entity](#null-entity)
     * [Stamp](#stamp)
     * [Stamp](#stamp)
     * [Dependencies](#dependencies)
     * [Dependencies](#dependencies)
-    * [Tags](#tags)
     * [Actor](#actor)
     * [Actor](#actor)
     * [Context variables](#context-variables)
     * [Context variables](#context-variables)
   * [Meet the runtime](#meet-the-runtime)
   * [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
 that accept an entity as the first argument are good candidates for this
 purpose.
 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
 ### Actor
 
 
 The `actor` class is designed for those who don't feel immediately comfortable
 The `actor` class is designed for those who don't feel immediately comfortable

+ 8 - 0
src/entt/core/type_traits.hpp

@@ -201,6 +201,14 @@ template<typename Member>
 using member_class_t = typename member_class<Member>::type;
 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>;
+
+
 }
 }
 
 
 
 

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

@@ -142,29 +142,6 @@ template<typename Entity>
 as_group(const basic_registry<Entity> &) ENTT_NOEXCEPT -> as_group<true, 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>;
-
-
 }
 }
 
 
 
 

+ 7 - 0
test/entt/core/type_traits.cpp

@@ -1,4 +1,6 @@
 #include <gtest/gtest.h>
 #include <gtest/gtest.h>
+#include <entt/config/config.h>
+#include <entt/core/hashed_string.hpp>
 #include <entt/core/type_traits.hpp>
 #include <entt/core/type_traits.hpp>
 
 
 TEST(Choice, Functionalities) {
 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::bar)>>));
     ASSERT_TRUE((std::is_same_v<clazz, entt::member_class_t<decltype(&clazz::quux)>>));
     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>));
+}

+ 0 - 25
test/entt/entity/helper.cpp

@@ -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>, double>) {})(entt::as_group{registry});
     ([](entt::group<entt::exclude_t<int>, entt::get_t<const char>, const 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);
-}