Browse Source

organizer: fixed an issue for free functions with payload (close #613)

Michele Caini 5 years ago
parent
commit
002f92fe1e
2 changed files with 80 additions and 7 deletions
  1. 10 7
      src/entt/entity/organizer.hpp
  2. 70 0
      test/entt/entity/organizer.cpp

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

@@ -86,13 +86,16 @@ struct resource<type_list<Args...>, type_list<Req...>> {
 
 
 template<typename... Req, typename Ret, typename... Args>
-resource<type_list<std::remove_reference_t<Args>...>, type_list<Req...>> to_resource(Ret(*)(Args...));
+resource<type_list<std::remove_reference_t<Args>...>, type_list<Req...>> free_function_to_resource(Ret(*)(Args...));
+
+template<typename... Req, typename Ret, typename Type, typename... Args>
+resource<type_list<std::remove_reference_t<Args>...>, type_list<Req...>> constrained_function_to_resource(Ret(*)(Type &, Args...));
 
 template<typename... Req, typename Ret, typename Class, typename... Args>
-resource<type_list<std::remove_reference_t<Args>...>, type_list<Req...>> to_resource(Ret(Class:: *)(Args...));
+resource<type_list<std::remove_reference_t<Args>...>, type_list<Req...>> constrained_function_to_resource(Ret(Class:: *)(Args...));
 
 template<typename... Req, typename Ret, typename Class, typename... Args>
-resource<type_list<std::remove_reference_t<Args>...>, type_list<Req...>> to_resource(Ret(Class:: *)(Args...) const);
+resource<type_list<std::remove_reference_t<Args>...>, type_list<Req...>> constrained_function_to_resource(Ret(Class:: *)(Args...) const);
 
 template<typename... Req>
 resource<type_list<>, type_list<Req...>> to_resource();
@@ -371,7 +374,7 @@ public:
      */
     template<auto Candidate, typename... Req>
     void emplace(const char *name = nullptr) {
-        using resource_type = decltype(internal::to_resource<Req...>(Candidate));
+        using resource_type = decltype(internal::free_function_to_resource<Req...>(Candidate));
         constexpr auto requires_registry = type_list_contains_v<typename resource_type::args, basic_registry<entity_type>>;
 
         callback_type *callback = +[](const void *, basic_registry<entity_type> &reg) {
@@ -403,11 +406,11 @@ public:
      */
     template<auto Candidate, typename... Req, typename Type>
     void emplace(Type &value_or_instance, const char *name = nullptr) {
-        using resource_type = decltype(internal::to_resource<Req...>(Candidate));
+        using resource_type = decltype(internal::constrained_function_to_resource<Req...>(Candidate));
         constexpr auto requires_registry = type_list_contains_v<typename resource_type::args, basic_registry<entity_type>>;
 
         callback_type *callback = +[](const void *payload, basic_registry<entity_type> &reg) {
-            Type *curr = static_cast<Type *>(const_cast<std::conditional_t<std::is_const_v<Type>, const void *, void *>>(payload));
+            Type *curr = static_cast<Type *>(const_cast<constness_as_t<void, Type> *>(payload));
             std::apply(Candidate, std::tuple_cat(std::forward_as_tuple(*curr), to_args(reg, typename resource_type::args{})));
         };
 
@@ -439,7 +442,7 @@ public:
      */
     template<typename... Req>
     void emplace(function_type *func, const void *payload = nullptr, const char *name = nullptr) {
-        using resource_type = decltype(internal::to_resource<Req...>());
+        using resource_type = internal::resource<type_list<>, type_list<Req...>>;
         track_dependencies(vertices.size(), true, typename resource_type::ro{}, typename resource_type::rw{});
 
         vertices.push_back({

+ 70 - 0
test/entt/entity/organizer.cpp

@@ -13,6 +13,10 @@ struct clazz {
     void rw_int(entt::view<entt::exclude_t<>, int>) {}
     void rw_int_char(entt::view<entt::exclude_t<>, int, char>) {}
     void rw_int_char_double(entt::view<entt::exclude_t<>, int, char>, double &) {}
+
+    static void ro_int_with_payload(const clazz &, entt::view<entt::exclude_t<>, const int>) {}
+    static void ro_char_with_payload(const clazz &, entt::view<entt::exclude_t<>, const char>) {}
+    static void ro_int_char_with_payload(clazz &, entt::view<entt::exclude_t<>, const int, const char>) {}
 };
 
 void to_args_integrity(entt::view<entt::exclude_t<>, int> view, std::size_t &value, entt::registry &registry) {
@@ -131,6 +135,72 @@ TEST(Organizer, EmplaceMemberFunction) {
     ASSERT_EQ(organizer.graph().size(), 0u);
 }
 
+TEST(Organizer, EmplaceFreeFunctionWithPayload) {
+    entt::organizer organizer;
+    entt::registry registry;
+    clazz instance;
+
+    // TODO
+
+    organizer.emplace<&clazz::ro_int_char_double>(instance, "t1");
+    organizer.emplace<&clazz::ro_int_with_payload>(instance, "t2");
+    organizer.emplace<&clazz::ro_char_with_payload, const clazz>(instance, "t3");
+    organizer.emplace<&clazz::ro_int_char_with_payload, clazz>(instance, "t4");
+    organizer.emplace<&clazz::rw_int_char>(instance, "t5");
+
+    const auto graph = organizer.graph();
+
+    ASSERT_EQ(graph.size(), 5u);
+
+    ASSERT_STREQ(graph[0u].name(), "t1");
+    ASSERT_STREQ(graph[1u].name(), "t2");
+    ASSERT_STREQ(graph[2u].name(), "t3");
+    ASSERT_STREQ(graph[3u].name(), "t4");
+    ASSERT_STREQ(graph[4u].name(), "t5");
+
+    ASSERT_EQ(graph[0u].ro_count(), 3u);
+    ASSERT_EQ(graph[1u].ro_count(), 1u);
+    ASSERT_EQ(graph[2u].ro_count(), 2u);
+    ASSERT_EQ(graph[3u].ro_count(), 2u);
+    ASSERT_EQ(graph[4u].ro_count(), 0u);
+
+    ASSERT_EQ(graph[0u].rw_count(), 0u);
+    ASSERT_EQ(graph[1u].rw_count(), 0u);
+    ASSERT_EQ(graph[2u].rw_count(), 0u);
+    ASSERT_EQ(graph[3u].rw_count(), 1u);
+    ASSERT_EQ(graph[4u].rw_count(), 2u);
+
+    ASSERT_NE(graph[0u].info(), graph[1u].info());
+    ASSERT_NE(graph[1u].info(), graph[2u].info());
+    ASSERT_NE(graph[2u].info(), graph[3u].info());
+    ASSERT_NE(graph[3u].info(), graph[4u].info());
+
+    ASSERT_TRUE(graph[0u].top_level());
+    ASSERT_TRUE(graph[1u].top_level());
+    ASSERT_TRUE(graph[2u].top_level());
+    ASSERT_FALSE(graph[3u].top_level());
+    ASSERT_FALSE(graph[4u].top_level());
+
+    ASSERT_EQ(graph[0u].children().size(), 1u);
+    ASSERT_EQ(graph[1u].children().size(), 1u);
+    ASSERT_EQ(graph[2u].children().size(), 1u);
+    ASSERT_EQ(graph[3u].children().size(), 1u);
+    ASSERT_EQ(graph[4u].children().size(), 0u);
+
+    ASSERT_EQ(graph[0u].children()[0u], 4u);
+    ASSERT_EQ(graph[1u].children()[0u], 4u);
+    ASSERT_EQ(graph[2u].children()[0u], 3u);
+    ASSERT_EQ(graph[3u].children()[0u], 4u);
+
+    for(auto &&vertex: graph) {
+        ASSERT_NO_THROW(vertex.callback()(vertex.data(), registry));
+    }
+
+    organizer.clear();
+
+    ASSERT_EQ(organizer.graph().size(), 0u);
+}
+
 TEST(Organizer, EmplaceDirectFunction) {
     entt::organizer organizer;
     entt::registry registry;