Browse Source

meta: review

Michele Caini 6 years ago
parent
commit
f220a577e0
2 changed files with 61 additions and 63 deletions
  1. 2 0
      TODO
  2. 59 63
      src/entt/meta/factory.hpp

+ 2 - 0
TODO

@@ -29,3 +29,5 @@ TODO
   - cloning all/part of the components are both required and a target entity on which to stomp your stuff could help
   - cloning all/part of the components are both required and a target entity on which to stomp your stuff could help
   - clone is just clone, creating new entity. But yeah, both "clone-all", and "clone-components"
   - clone is just clone, creating new entity. But yeah, both "clone-all", and "clone-components"
   - for "apply", again both All and Components, and maybe an enum of what kind of apply "dont overwrite, overwrite, add-only"
   - for "apply", again both All and Components, and maybe an enum of what kind of apply "dont overwrite, overwrite, add-only"
+* meta: copy on aliasing should make an actual copy of the value, not of the pointer (steal has a similar problem)
+* meta: almost always aliasing method

+ 59 - 63
src/entt/meta/factory.hpp

@@ -24,19 +24,17 @@ namespace entt {
 namespace internal {
 namespace internal {
 
 
 
 
-template<typename...>
+template<typename>
 struct meta_function_helper;
 struct meta_function_helper;
 
 
 
 
 template<typename Ret, typename... Args>
 template<typename Ret, typename... Args>
 struct meta_function_helper<Ret(Args...)> {
 struct meta_function_helper<Ret(Args...)> {
-    using return_type = Ret;
-    using args_type = std::tuple<Args...>;
-
-    template<std::size_t Index>
-    using arg_type = std::decay_t<std::tuple_element_t<Index, args_type>>;
+    using return_type = std::remove_cv_t<std::remove_reference_t<Ret>>;
+    using args_type = std::tuple<std::remove_cv_t<std::remove_reference_t<Args>>...>;
 
 
     static constexpr auto size = sizeof...(Args);
     static constexpr auto size = sizeof...(Args);
+    static constexpr auto is_const = false;
 
 
     static auto arg(typename internal::meta_func_node::size_type index) ENTT_NOEXCEPT {
     static auto arg(typename internal::meta_func_node::size_type index) ENTT_NOEXCEPT {
         return std::array<meta_type_node *, sizeof...(Args)>{{meta_info<Args>::resolve()...}}[index];
         return std::array<meta_type_node *, sizeof...(Args)>{{meta_info<Args>::resolve()...}}[index];
@@ -44,40 +42,38 @@ struct meta_function_helper<Ret(Args...)> {
 };
 };
 
 
 
 
-template<typename Class, typename Ret, typename... Args, bool Const, bool Static>
-struct meta_function_helper<Class, Ret(Args...), std::bool_constant<Const>, std::bool_constant<Static>>: meta_function_helper<Ret(Args...)> {
-    using class_type = Class;
-    static constexpr auto is_const = Const;
-    static constexpr auto is_static = Static;
+template<typename Ret, typename... Args>
+struct meta_function_helper<Ret(Args...) const>: meta_function_helper<Ret(Args...)> {
+    static constexpr auto is_const = true;
 };
 };
 
 
 
 
 template<typename Ret, typename... Args, typename Class>
 template<typename Ret, typename... Args, typename Class>
-constexpr meta_function_helper<Class, Ret(Args...), std::bool_constant<false>, std::bool_constant<false>>
+constexpr meta_function_helper<Ret(Args...)>
 to_meta_function_helper(Ret(Class:: *)(Args...));
 to_meta_function_helper(Ret(Class:: *)(Args...));
 
 
 
 
 template<typename Ret, typename... Args, typename Class>
 template<typename Ret, typename... Args, typename Class>
-constexpr meta_function_helper<Class, Ret(Args...), std::bool_constant<true>, std::bool_constant<false>>
+constexpr meta_function_helper<Ret(Args...) const>
 to_meta_function_helper(Ret(Class:: *)(Args...) const);
 to_meta_function_helper(Ret(Class:: *)(Args...) const);
 
 
 
 
 template<typename Ret, typename... Args>
 template<typename Ret, typename... Args>
-constexpr meta_function_helper<void, Ret(Args...), std::bool_constant<false>, std::bool_constant<true>>
+constexpr meta_function_helper<Ret(Args...)>
 to_meta_function_helper(Ret(*)(Args...));
 to_meta_function_helper(Ret(*)(Args...));
 
 
 
 
-template<auto Func>
-struct meta_function_helper<std::integral_constant<decltype(Func), Func>>: decltype(to_meta_function_helper(Func)) {};
+template<typename Candidate>
+using meta_function_helper_t = decltype(to_meta_function_helper(std::declval<Candidate>()));
 
 
 
 
 template<typename Type, typename... Args, std::size_t... Indexes>
 template<typename Type, typename... Args, std::size_t... Indexes>
 meta_any construct(meta_any * const args, std::index_sequence<Indexes...>) {
 meta_any construct(meta_any * const args, std::index_sequence<Indexes...>) {
-    [[maybe_unused]] auto direct = std::make_tuple((args+Indexes)->try_cast<std::remove_cv_t<std::remove_reference_t<Args>>>()...);
+    [[maybe_unused]] auto direct = std::make_tuple((args+Indexes)->try_cast<Args>()...);
     meta_any any{};
     meta_any any{};
 
 
-    if(((std::get<Indexes>(direct) || (args+Indexes)->convert<std::remove_cv_t<std::remove_reference_t<Args>>>()) && ...)) {
-        any = Type{(std::get<Indexes>(direct) ? *std::get<Indexes>(direct) : (args+Indexes)->cast<std::remove_cv_t<std::remove_reference_t<Args>>>())...};
+    if(((std::get<Indexes>(direct) || (args+Indexes)->convert<Args>()) && ...)) {
+        any = Type{(std::get<Indexes>(direct) ? *std::get<Indexes>(direct) : (args+Indexes)->cast<Args>())...};
     }
     }
 
 
     return any;
     return any;
@@ -90,8 +86,8 @@ bool setter([[maybe_unused]] meta_handle handle, [[maybe_unused]] meta_any index
 
 
     if constexpr(!Const) {
     if constexpr(!Const) {
         if constexpr(std::is_function_v<std::remove_pointer_t<decltype(Data)>> || std::is_member_function_pointer_v<decltype(Data)>) {
         if constexpr(std::is_function_v<std::remove_pointer_t<decltype(Data)>> || std::is_member_function_pointer_v<decltype(Data)>) {
-            using helper_type = meta_function_helper<std::integral_constant<decltype(Data), Data>>;
-            using data_type = std::decay_t<std::tuple_element_t<!std::is_member_function_pointer_v<decltype(Data)>, typename helper_type::args_type>>;
+            using helper_type = meta_function_helper_t<decltype(Data)>;
+            using data_type = std::tuple_element_t<!std::is_member_function_pointer_v<decltype(Data)>, typename helper_type::args_type>;
             static_assert(std::is_invocable_v<decltype(Data), Type &, data_type>);
             static_assert(std::is_invocable_v<decltype(Data), Type &, data_type>);
             auto *direct = value.try_cast<data_type>();
             auto *direct = value.try_cast<data_type>();
             auto *clazz = handle.data<Type>();
             auto *clazz = handle.data<Type>();
@@ -102,7 +98,7 @@ bool setter([[maybe_unused]] meta_handle handle, [[maybe_unused]] meta_any index
             }
             }
         } else if constexpr(std::is_member_object_pointer_v<decltype(Data)>) {
         } else if constexpr(std::is_member_object_pointer_v<decltype(Data)>) {
             using data_type = std::remove_cv_t<std::remove_reference_t<decltype(std::declval<Type>().*Data)>>;
             using data_type = std::remove_cv_t<std::remove_reference_t<decltype(std::declval<Type>().*Data)>>;
-            static_assert(std::is_invocable_v<decltype(Data), Type>);
+            static_assert(std::is_invocable_v<decltype(Data), Type *>);
             auto *clazz = handle.data<Type>();
             auto *clazz = handle.data<Type>();
 
 
             if constexpr(std::is_array_v<data_type>) {
             if constexpr(std::is_array_v<data_type>) {
@@ -180,41 +176,41 @@ meta_any getter([[maybe_unused]] meta_handle handle, [[maybe_unused]] meta_any i
 }
 }
 
 
 
 
-template<typename Type, auto Func, std::size_t... Indexes>
-std::enable_if_t<std::is_function_v<std::remove_pointer_t<decltype(Func)>>, meta_any>
-invoke(meta_handle, meta_any *args, std::index_sequence<Indexes...>) {
-    using helper_type = meta_function_helper<std::integral_constant<decltype(Func), Func>>;
-    [[maybe_unused]] auto direct = std::make_tuple((args+Indexes)->try_cast<typename helper_type::template arg_type<Indexes>>()...);
+template<typename Type, auto Candidate, std::size_t... Indexes>
+meta_any invoke([[maybe_unused]] meta_handle handle, meta_any *args, std::index_sequence<Indexes...>) {
+    using helper_type = meta_function_helper_t<decltype(Candidate)>;
     meta_any any{};
     meta_any any{};
 
 
-    if(((std::get<Indexes>(direct) || (args+Indexes)->convert<typename helper_type::template arg_type<Indexes>>()) && ...)) {
-        if constexpr(std::is_void_v<typename helper_type::return_type>) {
-            std::invoke(Func, (std::get<Indexes>(direct) ? *std::get<Indexes>(direct) : (args+Indexes)->cast<typename helper_type::template arg_type<Indexes>>())...);
-            any.emplace<void>();
-        } else {
-            any = std::invoke(Func, (std::get<Indexes>(direct) ? *std::get<Indexes>(direct) : (args+Indexes)->cast<typename helper_type::template arg_type<Indexes>>())...);
-        }
-    }
+    [[maybe_unused]] const auto direct = std::make_tuple([args](meta_any *curr) {
+        using arg_type = std::tuple_element_t<Indexes, typename helper_type::args_type>;
+        auto *instance = curr->try_cast<arg_type>();
 
 
-    return any;
-}
+        if(!instance && (args+Indexes)->convert<arg_type>()) {
+            instance = (args+Indexes)->try_cast<arg_type>();
+        }
 
 
+        return instance;
+    }(args+Indexes)...);
 
 
-template<typename Type, auto Member, std::size_t... Indexes>
-std::enable_if_t<std::is_member_function_pointer_v<decltype(Member)>, meta_any>
-invoke(meta_handle handle, meta_any *args, std::index_sequence<Indexes...>) {
-    using helper_type = meta_function_helper<std::integral_constant<decltype(Member), Member>>;
-    static_assert(std::is_base_of_v<typename helper_type::class_type, Type>);
-    [[maybe_unused]] auto direct = std::make_tuple((args+Indexes)->try_cast<typename helper_type::template arg_type<Indexes>>()...);
-    auto *clazz = handle.data<Type>();
-    meta_any any{};
+    if constexpr(std::is_function_v<std::remove_pointer_t<decltype(Candidate)>>) {
+        if((std::get<Indexes>(direct) && ...)) {
+            if constexpr(std::is_void_v<typename helper_type::return_type>) {
+                std::invoke(Candidate, *std::get<Indexes>(direct)...);
+                any.emplace<void>();
+            } else {
+                any = std::invoke(Candidate, *std::get<Indexes>(direct)...);
+            }
+        }
+    } else {
+        auto *clazz = handle.data<Type>();
 
 
-    if(clazz && ((std::get<Indexes>(direct) || (args+Indexes)->convert<typename helper_type::template arg_type<Indexes>>()) && ...)) {
-        if constexpr(std::is_void_v<typename helper_type::return_type>) {
-            std::invoke(Member, clazz, (std::get<Indexes>(direct) ? *std::get<Indexes>(direct) : (args+Indexes)->cast<typename helper_type::template arg_type<Indexes>>())...);
-            any.emplace<void>();
-        } else {
-            any = std::invoke(Member, clazz, (std::get<Indexes>(direct) ? *std::get<Indexes>(direct) : (args+Indexes)->cast<typename helper_type::template arg_type<Indexes>>())...);
+        if(clazz && (std::get<Indexes>(direct) && ...)) {
+            if constexpr(std::is_void_v<typename helper_type::return_type>) {
+                std::invoke(Candidate, clazz, *std::get<Indexes>(direct)...);
+                any.emplace<void>();
+            } else {
+                any = std::invoke(Candidate, clazz, *std::get<Indexes>(direct)...);
+            }
         }
         }
     }
     }
 
 
@@ -466,7 +462,7 @@ public:
      */
      */
     template<auto Func, typename... Property>
     template<auto Func, typename... Property>
     meta_factory ctor(Property &&... property) ENTT_NOEXCEPT {
     meta_factory ctor(Property &&... property) ENTT_NOEXCEPT {
-        using helper_type = internal::meta_function_helper<std::integral_constant<decltype(Func), Func>>;
+        using helper_type = internal::meta_function_helper_t<decltype(Func)>;
         static_assert(std::is_same_v<typename helper_type::return_type, Type>);
         static_assert(std::is_same_v<typename helper_type::return_type, Type>);
         auto * const type = internal::meta_info<Type>::resolve();
         auto * const type = internal::meta_info<Type>::resolve();
 
 
@@ -508,7 +504,7 @@ public:
      */
      */
     template<typename... Args, typename... Property>
     template<typename... Args, typename... Property>
     meta_factory ctor(Property &&... property) ENTT_NOEXCEPT {
     meta_factory ctor(Property &&... property) ENTT_NOEXCEPT {
-        using helper_type = internal::meta_function_helper<Type(Args...)>;
+        using helper_type = internal::meta_function_helper_t<Type(*)(Args...)>;
         auto * const type = internal::meta_info<Type>::resolve();
         auto * const type = internal::meta_info<Type>::resolve();
 
 
         static internal::meta_ctor_node node{
         static internal::meta_ctor_node node{
@@ -519,7 +515,7 @@ public:
             helper_type::size,
             helper_type::size,
             &helper_type::arg,
             &helper_type::arg,
             [](meta_any * const any) {
             [](meta_any * const any) {
-                return internal::construct<Type, Args...>(any, std::make_index_sequence<helper_type::size>{});
+                return internal::construct<Type, std::remove_cv_t<std::remove_reference_t<Args>>...>(any, std::make_index_sequence<helper_type::size>{});
             },
             },
             []() ENTT_NOEXCEPT -> meta_ctor {
             []() ENTT_NOEXCEPT -> meta_ctor {
                 return &node;
                 return &node;
@@ -733,31 +729,31 @@ public:
      * From a client's point of view, all the functions associated with the
      * From a client's point of view, all the functions associated with the
      * reflected object will appear as if they were part of the type itself.
      * reflected object will appear as if they were part of the type itself.
      *
      *
-     * @tparam Func The actual function to attach to the meta type.
+     * @tparam Candidate The actual function to attach to the meta type.
      * @tparam Property Types of properties to assign to the meta function.
      * @tparam Property Types of properties to assign to the meta function.
      * @param identifier Unique identifier.
      * @param identifier Unique identifier.
      * @param property Properties to assign to the meta function.
      * @param property Properties to assign to the meta function.
      * @return A meta factory for the parent type.
      * @return A meta factory for the parent type.
      */
      */
-    template<auto Func, typename... Property>
+    template<auto Candidate, typename... Property>
     meta_factory func(const ENTT_ID_TYPE identifier, Property &&... property) ENTT_NOEXCEPT {
     meta_factory func(const ENTT_ID_TYPE identifier, Property &&... property) ENTT_NOEXCEPT {
-        using owner_type = std::integral_constant<decltype(Func), Func>;
-        using helper_type = internal::meta_function_helper<std::integral_constant<decltype(Func), Func>>;
+        using owner_type = std::integral_constant<decltype(Candidate), Candidate>;
+        using helper_type = internal::meta_function_helper_t<decltype(Candidate)>;
         auto * const type = internal::meta_info<Type>::resolve();
         auto * const type = internal::meta_info<Type>::resolve();
 
 
         static internal::meta_func_node node{
         static internal::meta_func_node node{
-            &internal::meta_info<Type>::template func<Func>,
+            &internal::meta_info<Type>::template func<Candidate>,
             {},
             {},
             type,
             type,
             nullptr,
             nullptr,
             nullptr,
             nullptr,
             helper_type::size,
             helper_type::size,
             helper_type::is_const,
             helper_type::is_const,
-            helper_type::is_static,
+            !std::is_member_function_pointer_v<decltype(Candidate)>,
             &internal::meta_info<typename helper_type::return_type>::resolve,
             &internal::meta_info<typename helper_type::return_type>::resolve,
             &helper_type::arg,
             &helper_type::arg,
             [](meta_handle handle, meta_any *any) {
             [](meta_handle handle, meta_any *any) {
-                return internal::invoke<Type, Func>(handle, any, std::make_index_sequence<helper_type::size>{});
+                return internal::invoke<Type, Candidate>(handle, any, std::make_index_sequence<helper_type::size>{});
             },
             },
             []() ENTT_NOEXCEPT -> meta_func {
             []() ENTT_NOEXCEPT -> meta_func {
                 return &node;
                 return &node;
@@ -768,8 +764,8 @@ public:
         node.next = type->func;
         node.next = type->func;
         node.prop = properties<owner_type>(std::forward<Property>(property)...);
         node.prop = properties<owner_type>(std::forward<Property>(property)...);
         ENTT_ASSERT(!duplicate(identifier, node.next));
         ENTT_ASSERT(!duplicate(identifier, node.next));
-        ENTT_ASSERT((!internal::meta_info<Type>::template func<Func>));
-        internal::meta_info<Type>::template func<Func> = &node;
+        ENTT_ASSERT((!internal::meta_info<Type>::template func<Candidate>));
+        internal::meta_info<Type>::template func<Candidate> = &node;
         type->func = &node;
         type->func = &node;
 
 
         return *this;
         return *this;