diff --git a/TODO b/TODO index f877eea49..542cef15f 100644 --- a/TODO +++ b/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 - 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" +* 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 diff --git a/src/entt/meta/factory.hpp b/src/entt/meta/factory.hpp index 873c53bd9..78300bd8d 100644 --- a/src/entt/meta/factory.hpp +++ b/src/entt/meta/factory.hpp @@ -24,19 +24,17 @@ namespace entt { namespace internal { -template +template struct meta_function_helper; template struct meta_function_helper { - using return_type = Ret; - using args_type = std::tuple; - - template - using arg_type = std::decay_t>; + using return_type = std::remove_cv_t>; + using args_type = std::tuple>...>; 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 { return std::array{{meta_info::resolve()...}}[index]; @@ -44,40 +42,38 @@ struct meta_function_helper { }; -template -struct meta_function_helper, std::bool_constant>: meta_function_helper { - using class_type = Class; - static constexpr auto is_const = Const; - static constexpr auto is_static = Static; +template +struct meta_function_helper: meta_function_helper { + static constexpr auto is_const = true; }; template -constexpr meta_function_helper, std::bool_constant> +constexpr meta_function_helper to_meta_function_helper(Ret(Class:: *)(Args...)); template -constexpr meta_function_helper, std::bool_constant> +constexpr meta_function_helper to_meta_function_helper(Ret(Class:: *)(Args...) const); template -constexpr meta_function_helper, std::bool_constant> +constexpr meta_function_helper to_meta_function_helper(Ret(*)(Args...)); -template -struct meta_function_helper>: decltype(to_meta_function_helper(Func)) {}; +template +using meta_function_helper_t = decltype(to_meta_function_helper(std::declval())); template meta_any construct(meta_any * const args, std::index_sequence) { - [[maybe_unused]] auto direct = std::make_tuple((args+Indexes)->try_cast>>()...); + [[maybe_unused]] auto direct = std::make_tuple((args+Indexes)->try_cast()...); meta_any any{}; - if(((std::get(direct) || (args+Indexes)->convert>>()) && ...)) { - any = Type{(std::get(direct) ? *std::get(direct) : (args+Indexes)->cast>>())...}; + if(((std::get(direct) || (args+Indexes)->convert()) && ...)) { + any = Type{(std::get(direct) ? *std::get(direct) : (args+Indexes)->cast())...}; } return any; @@ -90,8 +86,8 @@ bool setter([[maybe_unused]] meta_handle handle, [[maybe_unused]] meta_any index if constexpr(!Const) { if constexpr(std::is_function_v> || std::is_member_function_pointer_v) { - using helper_type = meta_function_helper>; - using data_type = std::decay_t, typename helper_type::args_type>>; + using helper_type = meta_function_helper_t; + using data_type = std::tuple_element_t, typename helper_type::args_type>; static_assert(std::is_invocable_v); auto *direct = value.try_cast(); auto *clazz = handle.data(); @@ -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) { using data_type = std::remove_cv_t().*Data)>>; - static_assert(std::is_invocable_v); + static_assert(std::is_invocable_v); auto *clazz = handle.data(); if constexpr(std::is_array_v) { @@ -180,41 +176,41 @@ meta_any getter([[maybe_unused]] meta_handle handle, [[maybe_unused]] meta_any i } -template -std::enable_if_t>, meta_any> -invoke(meta_handle, meta_any *args, std::index_sequence) { - using helper_type = meta_function_helper>; - [[maybe_unused]] auto direct = std::make_tuple((args+Indexes)->try_cast>()...); +template +meta_any invoke([[maybe_unused]] meta_handle handle, meta_any *args, std::index_sequence) { + using helper_type = meta_function_helper_t; meta_any any{}; - if(((std::get(direct) || (args+Indexes)->convert>()) && ...)) { - if constexpr(std::is_void_v) { - std::invoke(Func, (std::get(direct) ? *std::get(direct) : (args+Indexes)->cast>())...); - any.emplace(); - } else { - any = std::invoke(Func, (std::get(direct) ? *std::get(direct) : (args+Indexes)->cast>())...); + [[maybe_unused]] const auto direct = std::make_tuple([args](meta_any *curr) { + using arg_type = std::tuple_element_t; + auto *instance = curr->try_cast(); + + if(!instance && (args+Indexes)->convert()) { + instance = (args+Indexes)->try_cast(); } - } - return any; -} + return instance; + }(args+Indexes)...); + if constexpr(std::is_function_v>) { + if((std::get(direct) && ...)) { + if constexpr(std::is_void_v) { + std::invoke(Candidate, *std::get(direct)...); + any.emplace(); + } else { + any = std::invoke(Candidate, *std::get(direct)...); + } + } + } else { + auto *clazz = handle.data(); -template -std::enable_if_t, meta_any> -invoke(meta_handle handle, meta_any *args, std::index_sequence) { - using helper_type = meta_function_helper>; - static_assert(std::is_base_of_v); - [[maybe_unused]] auto direct = std::make_tuple((args+Indexes)->try_cast>()...); - auto *clazz = handle.data(); - meta_any any{}; - - if(clazz && ((std::get(direct) || (args+Indexes)->convert>()) && ...)) { - if constexpr(std::is_void_v) { - std::invoke(Member, clazz, (std::get(direct) ? *std::get(direct) : (args+Indexes)->cast>())...); - any.emplace(); - } else { - any = std::invoke(Member, clazz, (std::get(direct) ? *std::get(direct) : (args+Indexes)->cast>())...); + if(clazz && (std::get(direct) && ...)) { + if constexpr(std::is_void_v) { + std::invoke(Candidate, clazz, *std::get(direct)...); + any.emplace(); + } else { + any = std::invoke(Candidate, clazz, *std::get(direct)...); + } } } @@ -466,7 +462,7 @@ public: */ template meta_factory ctor(Property &&... property) ENTT_NOEXCEPT { - using helper_type = internal::meta_function_helper>; + using helper_type = internal::meta_function_helper_t; static_assert(std::is_same_v); auto * const type = internal::meta_info::resolve(); @@ -508,7 +504,7 @@ public: */ template meta_factory ctor(Property &&... property) ENTT_NOEXCEPT { - using helper_type = internal::meta_function_helper; + using helper_type = internal::meta_function_helper_t; auto * const type = internal::meta_info::resolve(); static internal::meta_ctor_node node{ @@ -519,7 +515,7 @@ public: helper_type::size, &helper_type::arg, [](meta_any * const any) { - return internal::construct(any, std::make_index_sequence{}); + return internal::construct>...>(any, std::make_index_sequence{}); }, []() ENTT_NOEXCEPT -> meta_ctor { return &node; @@ -733,31 +729,31 @@ public: * 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. * - * @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. * @param identifier Unique identifier. * @param property Properties to assign to the meta function. * @return A meta factory for the parent type. */ - template + template meta_factory func(const ENTT_ID_TYPE identifier, Property &&... property) ENTT_NOEXCEPT { - using owner_type = std::integral_constant; - using helper_type = internal::meta_function_helper>; + using owner_type = std::integral_constant; + using helper_type = internal::meta_function_helper_t; auto * const type = internal::meta_info::resolve(); static internal::meta_func_node node{ - &internal::meta_info::template func, + &internal::meta_info::template func, {}, type, nullptr, nullptr, helper_type::size, helper_type::is_const, - helper_type::is_static, + !std::is_member_function_pointer_v, &internal::meta_info::resolve, &helper_type::arg, [](meta_handle handle, meta_any *any) { - return internal::invoke(handle, any, std::make_index_sequence{}); + return internal::invoke(handle, any, std::make_index_sequence{}); }, []() ENTT_NOEXCEPT -> meta_func { return &node; @@ -768,8 +764,8 @@ public: node.next = type->func; node.prop = properties(std::forward(property)...); ENTT_ASSERT(!duplicate(identifier, node.next)); - ENTT_ASSERT((!internal::meta_info::template func)); - internal::meta_info::template func = &node; + ENTT_ASSERT((!internal::meta_info::template func)); + internal::meta_info::template func = &node; type->func = &node; return *this;