Browse Source

group: index based get

Michele Caini 3 years ago
parent
commit
def82b534b
2 changed files with 87 additions and 31 deletions
  1. 46 12
      src/entt/entity/group.hpp
  2. 41 19
      test/entt/entity/group.cpp

+ 46 - 12
src/entt/entity/group.hpp

@@ -494,18 +494,35 @@ public:
      * Attempting to use an entity that doesn't belong to the group results in
      * Attempting to use an entity that doesn't belong to the group results in
      * undefined behavior.
      * undefined behavior.
      *
      *
-     * @tparam Type Types of components to get.
+     * @tparam Type Type of the component to get.
+     * @tparam Other Other types of components to get.
      * @param entt A valid identifier.
      * @param entt A valid identifier.
      * @return The components assigned to the entity.
      * @return The components assigned to the entity.
      */
      */
-    template<typename... Type>
+    template<typename Type, typename... Other>
     [[nodiscard]] decltype(auto) get(const entity_type entt) const {
     [[nodiscard]] decltype(auto) get(const entity_type entt) const {
-        if constexpr(sizeof...(Type) == 0) {
+        return get<index_of<Type>, index_of<Other>...>(entt);
+    }
+
+    /**
+     * @brief Returns the components assigned to the given entity.
+     *
+     * @warning
+     * Attempting to use an entity that doesn't belong to the groups results in
+     * undefined behavior.
+     *
+     * @tparam Index Indexes of the components to get.
+     * @param entt A valid identifier.
+     * @return The components assigned to the entity.
+     */
+    template<std::size_t... Index>
+    [[nodiscard]] decltype(auto) get(const entity_type entt) const {
+        if constexpr(sizeof...(Index) == 0) {
             return std::apply([entt](auto *...curr) { return std::tuple_cat(curr->get_as_tuple(entt)...); }, pools());
             return std::apply([entt](auto *...curr) { return std::tuple_cat(curr->get_as_tuple(entt)...); }, pools());
-        } else if constexpr(sizeof...(Type) == 1) {
-            return (storage<index_of<Type>>().get(entt), ...);
+        } else if constexpr(sizeof...(Index) == 1) {
+            return (storage<Index>().get(entt), ...);
         } else {
         } else {
-            return std::tuple_cat(storage<index_of<Type>>().get_as_tuple(entt)...);
+            return std::tuple_cat(storage<Index>().get_as_tuple(entt)...);
         }
         }
     }
     }
 
 
@@ -883,18 +900,35 @@ public:
      * Attempting to use an entity that doesn't belong to the group results in
      * Attempting to use an entity that doesn't belong to the group results in
      * undefined behavior.
      * undefined behavior.
      *
      *
-     * @tparam Type Types of components to get.
+     * @tparam Type Type of the component to get.
+     * @tparam Other Other types of components to get.
      * @param entt A valid identifier.
      * @param entt A valid identifier.
      * @return The components assigned to the entity.
      * @return The components assigned to the entity.
      */
      */
-    template<typename... Type>
+    template<typename Type, typename... Other>
     [[nodiscard]] decltype(auto) get(const entity_type entt) const {
     [[nodiscard]] decltype(auto) get(const entity_type entt) const {
-        if constexpr(sizeof...(Type) == 0) {
+        return get<index_of<Type>, index_of<Other>...>(entt);
+    }
+
+    /**
+     * @brief Returns the components assigned to the given entity.
+     *
+     * @warning
+     * Attempting to use an entity that doesn't belong to the groups results in
+     * undefined behavior.
+     *
+     * @tparam Index Indexes of the components to get.
+     * @param entt A valid identifier.
+     * @return The components assigned to the entity.
+     */
+    template<std::size_t... Index>
+    [[nodiscard]] decltype(auto) get(const entity_type entt) const {
+        if constexpr(sizeof...(Index) == 0) {
             return std::apply([entt](auto *...curr) { return std::tuple_cat(curr->get_as_tuple(entt)...); }, pools());
             return std::apply([entt](auto *...curr) { return std::tuple_cat(curr->get_as_tuple(entt)...); }, pools());
-        } else if constexpr(sizeof...(Type) == 1) {
-            return (storage<index_of<Type>>().get(entt), ...);
+        } else if constexpr(sizeof...(Index) == 1) {
+            return (storage<Index>().get(entt), ...);
         } else {
         } else {
-            return std::tuple_cat(storage<index_of<Type>>().get_as_tuple(entt)...);
+            return std::tuple_cat(storage<Index>().get_as_tuple(entt)...);
         }
         }
     }
     }
 
 

+ 41 - 19
test/entt/entity/group.cpp

@@ -56,7 +56,7 @@ TEST(NonOwningGroup, Functionalities) {
     for(auto entity: group) {
     for(auto entity: group) {
         ASSERT_EQ(std::get<0>(cgroup.get<const int, const char>(entity)), 42);
         ASSERT_EQ(std::get<0>(cgroup.get<const int, const char>(entity)), 42);
         ASSERT_EQ(std::get<1>(group.get<int, char>(entity)), '2');
         ASSERT_EQ(std::get<1>(group.get<int, char>(entity)), '2');
-        ASSERT_EQ(cgroup.get<const char>(entity), '2');
+        ASSERT_EQ(cgroup.get<1>(entity), '2');
     }
     }
 
 
     ASSERT_EQ(group.handle().data()[0u], e1);
     ASSERT_EQ(group.handle().data()[0u], e1);
@@ -276,9 +276,9 @@ TEST(NonOwningGroup, Sort) {
     ASSERT_EQ(group.handle().data()[1u], e1);
     ASSERT_EQ(group.handle().data()[1u], e1);
     ASSERT_EQ(group.handle().data()[2u], e2);
     ASSERT_EQ(group.handle().data()[2u], e2);
 
 
-    ASSERT_EQ((group.get<const int, unsigned int>(e0)), (std::make_tuple(0, 0u)));
-    ASSERT_EQ((group.get<const int, unsigned int>(e1)), (std::make_tuple(1, 1u)));
-    ASSERT_EQ((group.get<const int, unsigned int>(e2)), (std::make_tuple(2, 2u)));
+    ASSERT_EQ((group.get<0, 1>(e0)), (std::make_tuple(0, 0u)));
+    ASSERT_EQ((group.get<0, 1>(e1)), (std::make_tuple(1, 1u)));
+    ASSERT_EQ((group.get<0, 1>(e2)), (std::make_tuple(2, 2u)));
 
 
     ASSERT_FALSE(group.contains(e3));
     ASSERT_FALSE(group.contains(e3));
 
 
@@ -329,7 +329,7 @@ TEST(NonOwningGroup, SortAsAPool) {
     group.sort<unsigned int>();
     group.sort<unsigned int>();
 
 
     ASSERT_EQ((group.get<const int, unsigned int>(e0)), (std::make_tuple(0, 0u)));
     ASSERT_EQ((group.get<const int, unsigned int>(e0)), (std::make_tuple(0, 0u)));
-    ASSERT_EQ((group.get<const int, unsigned int>(e1)), (std::make_tuple(1, 1u)));
+    ASSERT_EQ((group.get<0, 1>(e1)), (std::make_tuple(1, 1u)));
     ASSERT_EQ((group.get<const int, unsigned int>(e2)), (std::make_tuple(2, 2u)));
     ASSERT_EQ((group.get<const int, unsigned int>(e2)), (std::make_tuple(2, 2u)));
 
 
     ASSERT_FALSE(group.contains(e3));
     ASSERT_FALSE(group.contains(e3));
@@ -387,9 +387,18 @@ TEST(NonOwningGroup, ConstNonConstAndAllInBetween) {
 
 
     ASSERT_EQ(group.size(), 1u);
     ASSERT_EQ(group.size(), 1u);
 
 
+    static_assert(std::is_same_v<decltype(group.get<0>({})), int &>);
     static_assert(std::is_same_v<decltype(group.get<int>({})), int &>);
     static_assert(std::is_same_v<decltype(group.get<int>({})), int &>);
+
+    static_assert(std::is_same_v<decltype(group.get<1>({})), void>);
+    static_assert(std::is_same_v<decltype(group.get<empty_type>({})), void>);
+
+    static_assert(std::is_same_v<decltype(group.get<2>({})), const char &>);
     static_assert(std::is_same_v<decltype(group.get<const char>({})), const char &>);
     static_assert(std::is_same_v<decltype(group.get<const char>({})), const char &>);
-    static_assert(std::is_same_v<decltype(group.get<int, const char>({})), std::tuple<int &, const char &>>);
+
+    static_assert(std::is_same_v<decltype(group.get<int, empty_type, const char>({})), std::tuple<int &, const char &>>);
+    static_assert(std::is_same_v<decltype(group.get<0, 1, 2>({})), std::tuple<int &, const char &>>);
+
     static_assert(std::is_same_v<decltype(group.get({})), std::tuple<int &, const char &>>);
     static_assert(std::is_same_v<decltype(group.get({})), std::tuple<int &, const char &>>);
 
 
     static_assert(std::is_same_v<decltype(std::as_const(registry).group_if_exists(entt::get<int, char>)), decltype(std::as_const(registry).group_if_exists(entt::get<const int, const char>))>);
     static_assert(std::is_same_v<decltype(std::as_const(registry).group_if_exists(entt::get<int, char>)), decltype(std::as_const(registry).group_if_exists(entt::get<const int, const char>))>);
@@ -478,7 +487,7 @@ TEST(NonOwningGroup, ExcludedComponents) {
         if(entity == e0) {
         if(entity == e0) {
             ASSERT_EQ(group.get<int>(e0), 0);
             ASSERT_EQ(group.get<int>(e0), 0);
         } else if(entity == e2) {
         } else if(entity == e2) {
-            ASSERT_EQ(group.get<int>(e2), 2);
+            ASSERT_EQ(group.get<0>(e2), 2);
         }
         }
     }
     }
 
 
@@ -496,7 +505,7 @@ TEST(NonOwningGroup, ExcludedComponents) {
         if(entity == e1) {
         if(entity == e1) {
             ASSERT_EQ(group.get<int>(e1), 1);
             ASSERT_EQ(group.get<int>(e1), 1);
         } else if(entity == e3) {
         } else if(entity == e3) {
-            ASSERT_EQ(group.get<int>(e3), 3);
+            ASSERT_EQ(group.get<0>(e3), 3);
         }
         }
     }
     }
 }
 }
@@ -786,7 +795,7 @@ TEST(OwningGroup, Functionalities) {
     for(auto entity: group) {
     for(auto entity: group) {
         ASSERT_EQ(std::get<0>(cgroup.get<const int, const char>(entity)), 42);
         ASSERT_EQ(std::get<0>(cgroup.get<const int, const char>(entity)), 42);
         ASSERT_EQ(std::get<1>(group.get<int, char>(entity)), '2');
         ASSERT_EQ(std::get<1>(group.get<int, char>(entity)), '2');
-        ASSERT_EQ(cgroup.get<const char>(entity), '2');
+        ASSERT_EQ(cgroup.get<1>(entity), '2');
     }
     }
 
 
     ASSERT_EQ(group.handle().data()[0u], e1);
     ASSERT_EQ(group.handle().data()[0u], e1);
@@ -975,7 +984,7 @@ TEST(OwningGroup, SortOrdered) {
     registry.emplace<boxed_int>(entities[4], 2);
     registry.emplace<boxed_int>(entities[4], 2);
 
 
     group.sort([&group](const entt::entity lhs, const entt::entity rhs) {
     group.sort([&group](const entt::entity lhs, const entt::entity rhs) {
-        return group.get<boxed_int>(lhs).value < group.get<boxed_int>(rhs).value;
+        return group.get<boxed_int>(lhs).value < group.get<0>(rhs).value;
     });
     });
 
 
     ASSERT_EQ(group.handle().data()[0u], entities[0]);
     ASSERT_EQ(group.handle().data()[0u], entities[0]);
@@ -995,7 +1004,7 @@ TEST(OwningGroup, SortOrdered) {
     ASSERT_EQ(group.storage<char>().raw()[0u][2u], 'c');
     ASSERT_EQ(group.storage<char>().raw()[0u][2u], 'c');
 
 
     ASSERT_EQ((group.get<boxed_int, char>(entities[0])), (std::make_tuple(boxed_int{12}, 'a')));
     ASSERT_EQ((group.get<boxed_int, char>(entities[0])), (std::make_tuple(boxed_int{12}, 'a')));
-    ASSERT_EQ((group.get<boxed_int, char>(entities[1])), (std::make_tuple(boxed_int{9}, 'b')));
+    ASSERT_EQ((group.get<0, 1>(entities[1])), (std::make_tuple(boxed_int{9}, 'b')));
     ASSERT_EQ((group.get<boxed_int, char>(entities[2])), (std::make_tuple(boxed_int{6}, 'c')));
     ASSERT_EQ((group.get<boxed_int, char>(entities[2])), (std::make_tuple(boxed_int{6}, 'c')));
 
 
     ASSERT_FALSE(group.contains(entities[3]));
     ASSERT_FALSE(group.contains(entities[3]));
@@ -1042,7 +1051,7 @@ TEST(OwningGroup, SortReverse) {
     ASSERT_EQ(group.storage<char>().raw()[0u][2u], 'a');
     ASSERT_EQ(group.storage<char>().raw()[0u][2u], 'a');
 
 
     ASSERT_EQ((group.get<boxed_int, char>(entities[0])), (std::make_tuple(boxed_int{6}, 'a')));
     ASSERT_EQ((group.get<boxed_int, char>(entities[0])), (std::make_tuple(boxed_int{6}, 'a')));
-    ASSERT_EQ((group.get<boxed_int, char>(entities[1])), (std::make_tuple(boxed_int{9}, 'b')));
+    ASSERT_EQ((group.get<0, 1>(entities[1])), (std::make_tuple(boxed_int{9}, 'b')));
     ASSERT_EQ((group.get<boxed_int, char>(entities[2])), (std::make_tuple(boxed_int{12}, 'c')));
     ASSERT_EQ((group.get<boxed_int, char>(entities[2])), (std::make_tuple(boxed_int{12}, 'c')));
 
 
     ASSERT_FALSE(group.contains(entities[3]));
     ASSERT_FALSE(group.contains(entities[3]));
@@ -1097,9 +1106,9 @@ TEST(OwningGroup, SortUnordered) {
     ASSERT_EQ(group.storage<boxed_int>().raw()[0u][6u].value, 5);
     ASSERT_EQ(group.storage<boxed_int>().raw()[0u][6u].value, 5);
 
 
     ASSERT_EQ(group.get<char>(group.handle().data()[0u]), 'e');
     ASSERT_EQ(group.get<char>(group.handle().data()[0u]), 'e');
-    ASSERT_EQ(group.get<char>(group.handle().data()[1u]), 'd');
+    ASSERT_EQ(group.get<1>(group.handle().data()[1u]), 'd');
     ASSERT_EQ(group.get<char>(group.handle().data()[2u]), 'c');
     ASSERT_EQ(group.get<char>(group.handle().data()[2u]), 'c');
-    ASSERT_EQ(group.get<char>(group.handle().data()[3u]), 'b');
+    ASSERT_EQ(group.get<1>(group.handle().data()[3u]), 'b');
     ASSERT_EQ(group.get<char>(group.handle().data()[4u]), 'a');
     ASSERT_EQ(group.get<char>(group.handle().data()[4u]), 'a');
 
 
     ASSERT_FALSE(group.contains(entities[5]));
     ASSERT_FALSE(group.contains(entities[5]));
@@ -1136,9 +1145,9 @@ TEST(OwningGroup, SortWithExclusionList) {
     ASSERT_EQ(group.storage<boxed_int>().raw()[0u][3u].value, 0);
     ASSERT_EQ(group.storage<boxed_int>().raw()[0u][3u].value, 0);
 
 
     ASSERT_EQ(group.get<boxed_int>(entities[0]).value, 0);
     ASSERT_EQ(group.get<boxed_int>(entities[0]).value, 0);
-    ASSERT_EQ(group.get<boxed_int>(entities[1]).value, 1);
+    ASSERT_EQ(group.get<0>(entities[1]).value, 1);
     ASSERT_EQ(group.get<boxed_int>(entities[3]).value, 3);
     ASSERT_EQ(group.get<boxed_int>(entities[3]).value, 3);
-    ASSERT_EQ(group.get<boxed_int>(entities[4]).value, 4);
+    ASSERT_EQ(group.get<0>(entities[4]).value, 4);
 
 
     ASSERT_FALSE(group.contains(entities[2]));
     ASSERT_FALSE(group.contains(entities[2]));
 }
 }
@@ -1192,11 +1201,24 @@ TEST(OwningGroup, ConstNonConstAndAllInBetween) {
 
 
     ASSERT_EQ(group.size(), 1u);
     ASSERT_EQ(group.size(), 1u);
 
 
+    static_assert(std::is_same_v<decltype(group.get<0>({})), int &>);
     static_assert(std::is_same_v<decltype(group.get<int>({})), int &>);
     static_assert(std::is_same_v<decltype(group.get<int>({})), int &>);
+
+    static_assert(std::is_same_v<decltype(group.get<1>({})), const char &>);
     static_assert(std::is_same_v<decltype(group.get<const char>({})), const char &>);
     static_assert(std::is_same_v<decltype(group.get<const char>({})), const char &>);
+
+    static_assert(std::is_same_v<decltype(group.get<2>({})), void>);
+    static_assert(std::is_same_v<decltype(group.get<empty_type>({})), void>);
+
+    static_assert(std::is_same_v<decltype(group.get<3>({})), double &>);
     static_assert(std::is_same_v<decltype(group.get<double>({})), double &>);
     static_assert(std::is_same_v<decltype(group.get<double>({})), double &>);
+
+    static_assert(std::is_same_v<decltype(group.get<4>({})), const float &>);
     static_assert(std::is_same_v<decltype(group.get<const float>({})), const float &>);
     static_assert(std::is_same_v<decltype(group.get<const float>({})), const float &>);
-    static_assert(std::is_same_v<decltype(group.get<int, const char, double, const float>({})), std::tuple<int &, const char &, double &, const float &>>);
+
+    static_assert(std::is_same_v<decltype(group.get<int, const char, empty_type, double, const float>({})), std::tuple<int &, const char &, double &, const float &>>);
+    static_assert(std::is_same_v<decltype(group.get<0, 1, 2, 3, 4>({})), std::tuple<int &, const char &, double &, const float &>>);
+
     static_assert(std::is_same_v<decltype(group.get({})), std::tuple<int &, const char &, double &, const float &>>);
     static_assert(std::is_same_v<decltype(group.get({})), std::tuple<int &, const char &, double &, const float &>>);
 
 
     static_assert(std::is_same_v<decltype(std::as_const(registry).group_if_exists<int>(entt::get<char>)), decltype(std::as_const(registry).group_if_exists<const int>(entt::get<const char>))>);
     static_assert(std::is_same_v<decltype(std::as_const(registry).group_if_exists<int>(entt::get<char>)), decltype(std::as_const(registry).group_if_exists<const int>(entt::get<const char>))>);
@@ -1289,7 +1311,7 @@ TEST(OwningGroup, ExcludedComponents) {
         if(entity == e0) {
         if(entity == e0) {
             ASSERT_EQ(group.get<int>(e0), 0);
             ASSERT_EQ(group.get<int>(e0), 0);
         } else if(entity == e2) {
         } else if(entity == e2) {
-            ASSERT_EQ(group.get<int>(e2), 2);
+            ASSERT_EQ(group.get<0>(e2), 2);
         }
         }
     }
     }
 
 
@@ -1307,7 +1329,7 @@ TEST(OwningGroup, ExcludedComponents) {
         if(entity == e1) {
         if(entity == e1) {
             ASSERT_EQ(group.get<int>(e1), 1);
             ASSERT_EQ(group.get<int>(e1), 1);
         } else if(entity == e3) {
         } else if(entity == e3) {
-            ASSERT_EQ(group.get<int>(e3), 3);
+            ASSERT_EQ(group.get<0>(e3), 3);
         }
         }
     }
     }
 }
 }