Pārlūkot izejas kodu

meta: typeless -> overloaded types

skypjack 4 dienas atpakaļ
vecāks
revīzija
9702af32f1

+ 3 - 2
TODO

@@ -33,12 +33,13 @@ TODO:
 * make meta_any buffer size configurable (propagate to any)
 * test trivially_destructible optimization
 * document stl and injections support
-* add instance-type to meta data and func (useful for typeless types)
 * use a dense_set for the meta context bucket to speed up lookups
 * new meta multi support: md and natvis
 * improve meta_reset and similar on multi contexts
-* review/refine/improve meta factory base for typed vs typeless types (ctor and type)
+* review/refine/improve meta factory base for typed vs overloaded types (ctor and type)
 * check coverage on new meta context features
 * fast lookup on meta reset
 * check for duplicates in basic_meta_factory constructor (with tests)
 * test (and fix) resolve where the type id conflicts with the type hash
+* rename meta-type::id -> ::alias
+* assert and test type mismatch on meta factory construction and type(...) - ie id vs alias on overloaded and standard

+ 21 - 269
src/entt/meta/factory.hpp

@@ -52,11 +52,11 @@ class basic_meta_factory {
     }
 
 protected:
-    void type(const id_type id, const char *name) noexcept {
+    void type(const id_type alias, const char *name) noexcept {
         state = mode::type;
-        ENTT_ASSERT((parent->id == id) || stl::find_if(ctx->bucket.cbegin(), ctx->bucket.cend(), [id](const auto &value) { return value.second->id == id; }) == ctx->bucket.cend(), "Duplicate identifier");
+        ENTT_ASSERT((parent->id == alias) || stl::find_if(ctx->bucket.cbegin(), ctx->bucket.cend(), [alias](const auto &value) { return value.second->id == alias; }) == ctx->bucket.cend(), "Duplicate identifier");
         parent->name = name;
-        parent->id = id;
+        parent->id = alias;
     }
 
     template<typename Type>
@@ -172,6 +172,13 @@ public:
     meta_factory() noexcept
         : meta_factory{locator<meta_ctx>::value_or()} {}
 
+    /**
+     * @brief Constructs an unconstrained type assigned to a given identifier.
+     * @param id A custom unique identifier.
+     */
+    meta_factory(const id_type id) noexcept
+        : meta_factory{locator<meta_ctx>::value_or(), id} {}
+
     /**
      * @brief Context aware constructor.
      * @param area The context into which to construct meta types.
@@ -179,6 +186,14 @@ public:
     meta_factory(meta_ctx &area) noexcept
         : internal::basic_meta_factory{area, internal::setup_node_for<element_type>(), type_hash<Type>::value()} {}
 
+    /**
+     * @brief Context aware constructor.
+     * @param id A custom unique identifier.
+     * @param area The context into which to construct meta types.
+     */
+    meta_factory(meta_ctx &area, const id_type id) noexcept
+        : internal::basic_meta_factory{area, internal::setup_node_for<element_type>(), id} {}
+
     /**
      * @brief Assigns a custom unique identifier to a meta type.
      * @param name A custom unique identifier as a **string literal**.
@@ -190,12 +205,12 @@ public:
 
     /**
      * @brief Assigns a custom unique identifier to a meta type.
-     * @param id A custom unique identifier.
+     * @param alias A custom unique identifier.
      * @param name An optional name for the type as a **string literal**.
      * @return A meta factory for the given type.
      */
-    meta_factory type(const id_type id, const char *name = nullptr) noexcept {
-        base_type::type(id, name);
+    meta_factory type(const id_type alias, const char *name = nullptr) noexcept {
+        base_type::type(alias, name);
         return *this;
     }
 
@@ -210,8 +225,6 @@ public:
     template<typename Base>
     requires stl::derived_from<element_type, Base>
     meta_factory base() noexcept {
-        static_assert(!stl::is_void_v<element_type>, "Feature not supported by void type");
-
         if constexpr(!stl::same_as<element_type, Base>) {
             auto *const op = +[](const void *instance) noexcept { return static_cast<const void *>(static_cast<const Base *>(static_cast<const element_type *>(instance))); };
 
@@ -239,8 +252,6 @@ public:
      */
     template<auto Candidate>
     auto conv() noexcept {
-        static_assert(!stl::is_void_v<element_type>, "Feature not supported by void type");
-
         using conv_type = stl::remove_cvref_t<stl::invoke_result_t<decltype(Candidate), element_type &>>;
         auto *const op = +[](const meta_ctx &area, const void *instance) { return forward_as_meta(area, stl::invoke(Candidate, *static_cast<const element_type *>(instance))); };
 
@@ -263,8 +274,6 @@ public:
      */
     template<typename To>
     meta_factory conv() noexcept {
-        static_assert(!stl::is_void_v<element_type>, "Feature not supported by void type");
-
         using conv_type = stl::remove_cvref_t<To>;
         auto *const op = +[](const meta_ctx &area, const void *instance) { return forward_as_meta(area, static_cast<To>(*static_cast<const element_type *>(instance))); };
 
@@ -291,8 +300,6 @@ public:
      */
     template<auto Candidate, typename Policy = as_value_t>
     meta_factory ctor() noexcept {
-        static_assert(!stl::is_void_v<element_type>, "Feature not supported by void type");
-
         using descriptor = meta_function_helper_t<element_type, decltype(Candidate)>;
         static_assert(Policy::template value<typename descriptor::return_type>, "Invalid return type for the given policy");
         static_assert(stl::is_same_v<stl::remove_cvref_t<typename descriptor::return_type>, element_type>, "The function doesn't return an object of the required type");
@@ -319,8 +326,6 @@ public:
      */
     template<typename... Args>
     meta_factory ctor() noexcept {
-        static_assert(!stl::is_void_v<element_type>, "Feature not supported by void type");
-
         // default constructor is already implicitly generated, no need for redundancy
         if constexpr(sizeof...(Args) != 0u) {
             using descriptor = meta_function_helper_t<element_type, element_type (*)(Args...)>;
@@ -545,259 +550,6 @@ public:
     }
 };
 
-/*! @brief Meta factory specialization for typeless meta types. */
-template<>
-class meta_factory<void>: private internal::basic_meta_factory {
-    using base_type = internal::basic_meta_factory;
-
-public:
-    /*! @brief Type of object for which this factory builds a meta type. */
-    using element_type = void;
-
-    /**
-     * @brief Constructs a factory for a uniquely identified typeless type.
-     * @param name A custom unique identifier as a **string literal**.
-     */
-    meta_factory(const char *name) noexcept
-        : meta_factory{locator<meta_ctx>::value_or(), name} {}
-
-    /**
-     * @brief Constructs a factory for a uniquely identified typeless type.
-     * @param id A custom unique identifier.
-     * @param name An optional name for the type as a **string literal**.
-     */
-    meta_factory(const id_type id, const char *name = nullptr) noexcept
-        : meta_factory{locator<meta_ctx>::value_or(), id, name} {}
-
-    /**
-     * @brief Context aware constructor for uniquely identified typeless types.
-     * @param name A custom unique identifier as a **string literal**.
-     */
-    meta_factory(meta_ctx &area, const char *name) noexcept
-        : meta_factory{area, hashed_string::value(name), name} {}
-
-    /**
-     * @brief Context aware constructor for uniquely identified typeless types.
-     * @param id A custom unique identifier.
-     * @param name An optional name for the type as a **string literal**.
-     */
-    meta_factory(meta_ctx &area, const id_type id, const char *name = nullptr) noexcept
-        : internal::basic_meta_factory{area, internal::setup_node_for<element_type>(), id} {
-        type(id, name);
-    }
-
-    /**
-     * @brief Assigns a meta data to a meta type.
-     * @tparam Data The actual variable to attach to the meta type.
-     * @tparam Policy Optional policy (no policy set by default).
-     * @param name A custom unique identifier as a **string literal**.
-     * @return A meta factory for the given type.
-     */
-    template<auto Data, typename Policy = as_value_t>
-    meta_factory data(const char *name) noexcept {
-        return data<Data, Policy>(hashed_string::value(name), name);
-    }
-
-    /**
-     * @brief Assigns a meta data to a meta type.
-     *
-     * Both data members and static and global variables, as well as constants
-     * of any kind, can be assigned to a meta type.<br/>
-     * From a client's point of view, all the variables associated with the
-     * reflected object will appear as if they were part of the type itself.
-     *
-     * @tparam Data The actual variable to attach to the meta type.
-     * @tparam Policy Optional policy (no policy set by default).
-     * @param id Unique identifier.
-     * @param name An optional name for the meta data as a **string literal**.
-     * @return A meta factory for the parent type.
-     */
-    template<auto Data, typename Policy = as_value_t>
-    meta_factory data(const id_type id, const char *name = nullptr) noexcept {
-        if constexpr(stl::is_member_object_pointer_v<decltype(Data)>) {
-            using class_type = member_class_t<decltype(Data)>;
-            using data_type = stl::invoke_result_t<decltype(Data), class_type &>;
-            static_assert(Policy::template value<data_type>, "Invalid return type for the given policy");
-
-            base_type::data(
-                internal::meta_data_node{
-                    id,
-                    name,
-                    /* this is never static */
-                    stl::is_const_v<stl::remove_reference_t<data_type>> ? internal::meta_traits::is_const : internal::meta_traits::is_none,
-                    &internal::resolve<stl::remove_cvref_t<data_type>>,
-                    &internal::resolve<stl::remove_cvref_t<data_type>>,
-                    &meta_setter<class_type, Data>,
-                    &meta_getter<class_type, Data, Policy>});
-        } else {
-            using data_type = stl::remove_pointer_t<decltype(Data)>;
-
-            if constexpr(stl::is_pointer_v<decltype(Data)>) {
-                static_assert(Policy::template value<decltype(*Data)>, "Invalid return type for the given policy");
-            } else {
-                static_assert(Policy::template value<data_type>, "Invalid return type for the given policy");
-            }
-
-            base_type::data(
-                internal::meta_data_node{
-                    id,
-                    name,
-                    ((!stl::is_pointer_v<decltype(Data)> || stl::is_const_v<data_type>) ? internal::meta_traits::is_const : internal::meta_traits::is_none) | internal::meta_traits::is_static,
-                    &internal::resolve<stl::remove_cvref_t<data_type>>,
-                    &internal::resolve<stl::remove_cvref_t<data_type>>,
-                    &meta_setter<void, Data>,
-                    &meta_getter<void, Data, Policy>});
-        }
-
-        return *this;
-    }
-
-    /**
-     * @brief Assigns a meta data to a meta type by means of its setter and
-     * getter.
-     * @tparam Setter The actual function to use as a setter.
-     * @tparam Getter The actual function to use as a getter.
-     * @tparam Policy Optional policy (no policy set by default).
-     * @param name A custom unique identifier as a **string literal**.
-     * @return A meta factory for the given type.
-     */
-    template<auto Setter, auto Getter, typename Policy = as_value_t>
-    meta_factory data(const char *name) noexcept {
-        return data<Setter, Getter, Policy>(hashed_string::value(name), name);
-    }
-
-    /**
-     * @brief Assigns a meta data to a meta type by means of its setter and
-     * getter.
-     *
-     * Setters and getters can be either free functions, member functions or a
-     * mix of them.<br/>
-     * In case of free functions, setters and getters must accept a reference to
-     * an instance of the parent type as their first argument. A setter has then
-     * an extra argument of a type convertible to that of the parameter to
-     * set.<br/>
-     * In case of member functions, getters have no arguments at all, while
-     * setters has an argument of a type convertible to that of the parameter to
-     * set.
-     *
-     * @tparam Setter The actual function to use as a setter.
-     * @tparam Getter The actual function to use as a getter.
-     * @tparam Policy Optional policy (no policy set by default).
-     * @param id Unique identifier.
-     * @param name An optional name for the meta data as a **string literal**.
-     * @return A meta factory for the parent type.
-     */
-    template<auto Setter, auto Getter, typename Policy = as_value_t>
-    meta_factory data(const id_type id, const char *name = nullptr) noexcept {
-        using class_type = stl::remove_cvref_t<typename stl::conditional_t<stl::is_member_pointer_v<decltype(Getter)>, member_class<decltype(Getter)>, nth_argument<0u, decltype(Getter)>>::type>;
-        using descriptor = meta_function_helper_t<class_type, decltype(Getter)>;
-        static_assert(Policy::template value<typename descriptor::return_type>, "Invalid return type for the given policy");
-
-        if constexpr(stl::is_same_v<decltype(Setter), stl::nullptr_t>) {
-            base_type::data(
-                internal::meta_data_node{
-                    id,
-                    name,
-                    /* this is never static */
-                    internal::meta_traits::is_const,
-                    &internal::resolve<stl::remove_cvref_t<typename descriptor::return_type>>,
-                    nullptr,
-                    &meta_setter<class_type, Setter>,
-                    &meta_getter<class_type, Getter, Policy>});
-        } else {
-            using args_type = meta_function_helper_t<class_type, decltype(Setter)>::args_type;
-
-            base_type::data(
-                internal::meta_data_node{
-                    id,
-                    name,
-                    /* this is never static nor const */
-                    internal::meta_traits::is_none,
-                    &internal::resolve<stl::remove_cvref_t<typename descriptor::return_type>>,
-                    &internal::resolve<stl::remove_cvref_t<type_list_element_t<static_cast<stl::size_t>(args_type::size != 1u), args_type>>>,
-                    &meta_setter<class_type, Setter>,
-                    &meta_getter<class_type, Getter, Policy>});
-        }
-
-        return *this;
-    }
-
-    /**
-     * @brief Assigns a meta function to a meta type.
-     * @tparam Candidate The actual function to attach to the meta function.
-     * @tparam Policy Optional policy (no policy set by default).
-     * @param name A custom unique identifier as a **string literal**.
-     * @return A meta factory for the given type.
-     */
-    template<auto Candidate, typename Policy = as_value_t>
-    meta_factory func(const char *name) noexcept {
-        return func<Candidate, Policy>(hashed_string::value(name), name);
-    }
-
-    /**
-     * @brief Assigns a meta function to a meta type.
-     *
-     * Both member functions and free functions can be assigned to a meta
-     * type.<br/>
-     * 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 Candidate The actual function to attach to the meta type.
-     * @tparam Policy Optional policy (no policy set by default).
-     * @param id Unique identifier.
-     * @param name An optional name for the function as a **string literal**.
-     * @return A meta factory for the parent type.
-     */
-    template<auto Candidate, typename Policy = as_value_t>
-    meta_factory func(const id_type id, const char *name = nullptr) noexcept {
-        using class_type = stl::remove_cvref_t<typename stl::conditional_t<stl::is_member_pointer_v<decltype(Candidate)>, member_class<decltype(Candidate)>, nth_argument<0u, decltype(Candidate)>>::type>;
-        using descriptor = meta_function_helper_t<class_type, decltype(Candidate)>;
-        static_assert(Policy::template value<typename descriptor::return_type>, "Invalid return type for the given policy");
-
-        base_type::func(
-            internal::meta_func_node{
-                id,
-                name,
-                (descriptor::is_const ? internal::meta_traits::is_const : internal::meta_traits::is_none) | (descriptor::is_static ? internal::meta_traits::is_static : internal::meta_traits::is_none),
-                descriptor::args_type::size,
-                &internal::resolve<stl::conditional_t<stl::is_same_v<Policy, as_void_t>, void, stl::remove_cvref_t<typename descriptor::return_type>>>,
-                &meta_arg<typename descriptor::args_type>,
-                &meta_invoke<class_type, Candidate, Policy>});
-
-        return *this;
-    }
-
-    /**
-     * @brief Sets traits on the last created meta object.
-     *
-     * The assigned value must be an enum and intended as a bitmask.
-     *
-     * @tparam Value Type of the traits value.
-     * @param value Traits value.
-     * @param unset True to unset the given traits, false otherwise.
-     * @return A meta factory for the parent type.
-     */
-    template<typename Value>
-    meta_factory traits(const Value value, const bool unset = false) {
-        static_assert(stl::is_enum_v<Value>, "Invalid enum type");
-        base_type::traits(internal::user_to_meta_traits(value), unset);
-        return *this;
-    }
-
-    /**
-     * @brief Sets user defined data that will never be used by the library.
-     * @tparam Value Type of user defined data to store.
-     * @tparam Args Types of arguments to use to construct the user data.
-     * @param args Parameters to use to initialize the user data.
-     * @return A meta factory for the parent type.
-     */
-    template<typename Value, typename... Args>
-    meta_factory custom(Args &&...args) {
-        base_type::custom(internal::meta_custom_node{type_id<Value>().hash(), stl::make_shared<Value>(stl::forward<Args>(args)...)});
-        return *this;
-    }
-};
-
 /**
  * @brief Resets a type and all its parts.
  *

+ 2 - 2
src/entt/meta/resolve.hpp

@@ -60,8 +60,8 @@ template<typename Type>
 [[nodiscard]] inline meta_type resolve(const meta_ctx &ctx, const id_type id) noexcept {
     const auto &context = internal::meta_context::from(ctx);
 
-    // fast lookup for unsearchable and typeless types
-    if(const auto it = context.bucket.find(id); (it != context.bucket.end()) && (it->second->id == id)) {
+    // fast lookup for unsearchable and overloaded types
+    if(const auto it = context.bucket.find(id); it != context.bucket.end()) {
         return meta_type{ctx, *it->second};
     }
 

+ 5 - 5
test/entt/meta/meta_context.cpp

@@ -35,7 +35,7 @@ class MetaContext: public ::testing::Test {
         entt::meta_factory<template_clazz<int>>{}
             .type("template"_hs);
 
-        entt::meta_factory<void>("global")
+        entt::meta_factory<void>("global"_hs)
             .data<1>("value"_hs);
     }
 
@@ -67,7 +67,7 @@ class MetaContext: public ::testing::Test {
         entt::meta_factory<template_clazz<int, char>>{context}
             .type("template"_hs);
 
-        entt::meta_factory<void>(context, "local")
+        entt::meta_factory<void>(context, "local"_hs)
             .data<2>("value"_hs);
     }
 
@@ -223,7 +223,7 @@ TEST_F(MetaContext, MetaType) {
     ASSERT_EQ(local.invoke("get"_hs, instance).cast<char>(), 'c');
 }
 
-TEST_F(MetaContext, MetaTypelessType) {
+TEST_F(MetaContext, MetaOverloadedType) {
     using namespace entt::literals;
 
     const auto global = entt::resolve("global"_hs);
@@ -234,8 +234,8 @@ TEST_F(MetaContext, MetaTypelessType) {
 
     ASSERT_NE(global, local);
 
-    ASSERT_EQ(global.id(), "global"_hs);
-    ASSERT_EQ(local.id(), "local"_hs);
+    ASSERT_EQ(global.id(), entt::type_hash<void>::value());
+    ASSERT_EQ(local.id(), entt::type_hash<void>::value());
 
     clazz instance{'c', 8};
     const argument value{2};

+ 43 - 372
test/entt/meta/meta_factory.cpp

@@ -68,6 +68,8 @@ using MetaVoidFactory = MetaFactory;
 using MetaFactoryDeathTest = MetaFactory;
 
 TEST_F(MetaFactory, Constructors) {
+    using namespace entt::literals;
+
     entt::meta_ctx ctx{};
 
     ASSERT_EQ(entt::resolve(entt::type_id<int>()), entt::meta_type{});
@@ -84,6 +86,22 @@ TEST_F(MetaFactory, Constructors) {
     ASSERT_NE(entt::resolve(entt::type_id<int>()), entt::meta_type{});
     ASSERT_NE(entt::resolve(ctx, entt::type_id<int>()), entt::meta_type{});
     ASSERT_TRUE(entt::resolve(ctx, entt::type_id<int>()).is_integral());
+
+    entt::meta_factory<double> other{"custom"_hs};
+
+    ASSERT_EQ(entt::resolve(entt::type_id<double>()), entt::meta_type{});
+    ASSERT_NE(entt::resolve("custom"_hs), entt::meta_type{});
+    ASSERT_EQ(entt::resolve(ctx, entt::type_id<double>()), entt::meta_type{});
+    ASSERT_EQ(entt::resolve(ctx, "custom"_hs), entt::meta_type{});
+    ASSERT_TRUE(entt::resolve("custom"_hs).is_arithmetic());
+
+    other = entt::meta_factory<double>{ctx, "custom"_hs};
+
+    ASSERT_EQ(entt::resolve(entt::type_id<double>()), entt::meta_type{});
+    ASSERT_NE(entt::resolve("custom"_hs), entt::meta_type{});
+    ASSERT_EQ(entt::resolve(ctx, entt::type_id<double>()), entt::meta_type{});
+    ASSERT_NE(entt::resolve(ctx, "custom"_hs), entt::meta_type{});
+    ASSERT_TRUE(entt::resolve("custom"_hs).is_arithmetic());
 }
 
 TEST_F(MetaFactory, Type) {
@@ -105,6 +123,31 @@ TEST_F(MetaFactory, Type) {
     ASSERT_EQ(entt::resolve<int>().id(), "bar"_hs);
 }
 
+TEST_F(MetaFactory, OverloadedType) {
+    using namespace entt::literals;
+
+    entt::meta_factory<int>{}
+        .type("foo"_hs)
+        .data<1>("value"_hs);
+
+    entt::meta_factory<int>{"integral"_hs}
+        .type("bar"_hs)
+        .data<2>("value"_hs);
+
+    ASSERT_NE(entt::resolve<int>(), entt::meta_type{});
+    ASSERT_NE(entt::resolve("integral"_hs), entt::meta_type{});
+    ASSERT_NE(entt::resolve<int>(), entt::resolve("integral"_hs));
+
+    ASSERT_NE(entt::resolve("foo"_hs), entt::meta_type{});
+    ASSERT_NE(entt::resolve("bar"_hs), entt::meta_type{});
+
+    ASSERT_EQ(entt::resolve("foo"_hs), entt::resolve<int>());
+    ASSERT_EQ(entt::resolve("bar"_hs), entt::resolve("integral"_hs));
+
+    ASSERT_EQ(entt::resolve<int>().data("value"_hs).get({}).cast<int>(), 1);
+    ASSERT_EQ(entt::resolve("integral"_hs).data("value"_hs).get({}).cast<int>(), 2);
+}
+
 ENTT_DEBUG_TEST_F(MetaFactoryDeathTest, Type) {
     using namespace entt::literals;
 
@@ -539,375 +582,3 @@ TEST_F(MetaFactory, MetaReset) {
     ASSERT_FALSE(entt::resolve(entt::type_id<int>()));
     ASSERT_FALSE(entt::resolve(ctx, entt::type_id<int>()));
 }
-
-TEST_F(MetaVoidFactory, Constructors) {
-    using namespace entt::literals;
-
-    entt::meta_ctx ctx{};
-
-    ASSERT_FALSE(entt::resolve("type"_hs));
-    ASSERT_FALSE(entt::resolve(ctx, "type"_hs));
-
-    entt::meta_factory<void> factory{"type"};
-
-    ASSERT_TRUE(entt::resolve("type"_hs));
-    ASSERT_FALSE(entt::resolve(ctx, "type"_hs));
-    ASSERT_EQ(entt::resolve("type"_hs).info(), entt::type_id<void>());
-
-    factory = entt::meta_factory<void>{ctx, "type"};
-
-    ASSERT_TRUE(entt::resolve("type"_hs));
-    ASSERT_TRUE(entt::resolve(ctx, "type"_hs));
-    ASSERT_EQ(entt::resolve(ctx, "type"_hs).info(), entt::type_id<void>());
-}
-
-TEST_F(MetaVoidFactory, DataMemberObject) {
-    using namespace entt::literals;
-
-    base instance{'c'};
-    entt::meta_factory<void> factory{"type"};
-    entt::meta_type type = entt::resolve("type"_hs);
-
-    ASSERT_FALSE(type.data("member"_hs));
-
-    factory.data<&base::member>("member"_hs);
-    type = entt::resolve("type"_hs);
-
-    ASSERT_TRUE(type.data("member"_hs));
-    ASSERT_EQ(type.get("member"_hs, std::as_const(instance)), instance.member);
-    ASSERT_EQ(type.get("member"_hs, instance), instance.member);
-    ASSERT_FALSE(type.set("member"_hs, std::as_const(instance), instance.member));
-    ASSERT_TRUE(type.set("member"_hs, instance, instance.member));
-}
-
-TEST_F(MetaVoidFactory, DataFreeFunction) {
-    using namespace entt::literals;
-
-    clazz instance{1};
-    entt::meta_factory<void> factory{"type"};
-    entt::meta_type type = entt::resolve("type"_hs);
-
-    ASSERT_FALSE(type.data("member"_hs));
-
-    factory.data<&clazz::set_double, &clazz::get_double>("member"_hs);
-    type = entt::resolve("type"_hs);
-
-    ASSERT_TRUE(type.data("member"_hs));
-    ASSERT_EQ(type.get("member"_hs, std::as_const(instance)).cast<double>(), instance.get_int());
-    ASSERT_EQ(type.get("member"_hs, instance).cast<double>(), instance.get_int());
-    ASSERT_FALSE(type.set("member"_hs, std::as_const(instance), instance.member));
-    ASSERT_TRUE(type.set("member"_hs, instance, instance.member));
-}
-
-TEST_F(MetaVoidFactory, DataPointer) {
-    using namespace entt::literals;
-
-    entt::meta_factory<void> factory{"type"};
-    entt::meta_type type = entt::resolve("type"_hs);
-
-    ASSERT_FALSE(type.data("value"_hs));
-
-    static int value = 1;
-    factory.data<&value>("value"_hs);
-    type = entt::resolve("type"_hs);
-
-    ASSERT_TRUE(type.data("value"_hs));
-    ASSERT_EQ(type.get("value"_hs, {}), value);
-    ASSERT_TRUE(type.set("value"_hs, {}, value));
-}
-
-TEST_F(MetaVoidFactory, DataValue) {
-    using namespace entt::literals;
-
-    constexpr int value = 1;
-    entt::meta_factory<void> factory{"type"};
-    entt::meta_type type = entt::resolve("type"_hs);
-
-    ASSERT_FALSE(type.data("value"_hs));
-
-    factory.data<value>("value"_hs);
-    type = entt::resolve("type"_hs);
-
-    ASSERT_TRUE(type.data("value"_hs));
-    ASSERT_EQ(type.get("value"_hs, {}), value);
-    ASSERT_FALSE(type.set("value"_hs, {}, value));
-}
-
-TEST_F(MetaVoidFactory, DataGetterOnly) {
-    using namespace entt::literals;
-
-    clazz instance{1};
-    entt::meta_factory<void> factory{"type"};
-    entt::meta_type type = entt::resolve("type"_hs);
-
-    ASSERT_FALSE(type.data("value"_hs));
-
-    factory.data<nullptr, &clazz::get_int>("value"_hs);
-    type = entt::resolve("type"_hs);
-
-    ASSERT_TRUE(type.data("value"_hs));
-    ASSERT_EQ(type.get("value"_hs, std::as_const(instance)), instance.get_int());
-    ASSERT_EQ(type.get("value"_hs, instance), instance.get_int());
-    ASSERT_FALSE(type.set("value"_hs, std::as_const(instance), instance.get_int()));
-    ASSERT_FALSE(type.set("value"_hs, instance, instance.get_int()));
-}
-
-TEST_F(MetaVoidFactory, DataSetterGetter) {
-    using namespace entt::literals;
-
-    clazz instance{1};
-    entt::meta_factory<void> factory{"type"};
-    entt::meta_type type = entt::resolve("type"_hs);
-
-    ASSERT_FALSE(type.data("value"_hs));
-
-    factory.data<&clazz::set_int, &clazz::get_int>("value"_hs);
-    type = entt::resolve("type"_hs);
-
-    ASSERT_TRUE(type.data("value"_hs));
-    ASSERT_EQ(type.get("value"_hs, std::as_const(instance)), instance.get_int());
-    ASSERT_EQ(type.get("value"_hs, instance), instance.get_int());
-    ASSERT_FALSE(type.set("value"_hs, std::as_const(instance), instance.get_int()));
-    ASSERT_TRUE(type.set("value"_hs, instance, instance.get_int()));
-}
-
-TEST_F(MetaVoidFactory, DataOverwrite) {
-    using namespace entt::literals;
-
-    entt::meta_factory<void> factory{"type"};
-    entt::meta_type type = entt::resolve("type"_hs);
-
-    ASSERT_FALSE(type.data("value"_hs));
-
-    factory.data<nullptr, &clazz::get_int>("value"_hs);
-    type = entt::resolve("type"_hs);
-
-    ASSERT_TRUE(type.data("value"_hs));
-    ASSERT_TRUE(type.data("value"_hs).is_const());
-
-    factory.data<&clazz::set_int, &clazz::get_int>("value"_hs);
-    type = entt::resolve("type"_hs);
-
-    ASSERT_TRUE(type.data("value"_hs));
-    ASSERT_FALSE(type.data("value"_hs).is_const());
-}
-
-TEST_F(MetaVoidFactory, DataTypeNameClash) {
-    using namespace entt::literals;
-
-    const auto value = 2;
-    entt::meta_factory<void> factory{"type"};
-    const auto member = entt::type_id<base>().hash();
-    entt::meta_data data = entt::resolve("type"_hs).data(member);
-
-    ASSERT_FALSE(data);
-
-    factory.data<&base::member>(member).custom<int>(value);
-    data = entt::resolve("type"_hs).data(member);
-
-    ASSERT_TRUE(data);
-    ASSERT_NE(static_cast<const int *>(data.custom()), nullptr);
-    ASSERT_EQ(static_cast<int>(data.custom()), value);
-}
-
-TEST_F(MetaVoidFactory, Func) {
-    using namespace entt::literals;
-
-    const clazz instance{1};
-    entt::meta_factory<void> factory{"type"};
-    entt::meta_type type = entt::resolve("type"_hs);
-
-    ASSERT_FALSE(type.func("func"_hs));
-
-    factory.func<&clazz::get_int>("func"_hs);
-    type = entt::resolve("type"_hs);
-
-    ASSERT_TRUE(type.func("func"_hs));
-    ASSERT_TRUE(type.invoke("func"_hs, instance));
-    ASSERT_EQ(type.invoke("func"_hs, instance).cast<int>(), instance.get_int());
-    ASSERT_FALSE(type.invoke("func"_hs, {}));
-}
-
-TEST_F(MetaVoidFactory, FuncFreeFunction) {
-    using namespace entt::literals;
-
-    const clazz instance{1};
-    entt::meta_factory<void> factory{"type"};
-    entt::meta_type type = entt::resolve("type"_hs);
-
-    ASSERT_FALSE(type.func("func"_hs));
-
-    factory.func<&clazz::get_double>("func"_hs);
-    type = entt::resolve("type"_hs);
-
-    ASSERT_TRUE(type.func("func"_hs));
-    ASSERT_TRUE(type.invoke("func"_hs, instance));
-    ASSERT_EQ(type.invoke("func"_hs, instance).cast<double>(), clazz::get_double(instance));
-    ASSERT_FALSE(type.invoke("func"_hs, {}));
-}
-
-TEST_F(MetaVoidFactory, FuncOverload) {
-    using namespace entt::literals;
-
-    clazz instance{1};
-    entt::meta_factory<void> factory{"type"};
-    entt::meta_type type = entt::resolve("type"_hs);
-
-    ASSERT_FALSE(type.func("func"_hs));
-
-    factory.func<&clazz::set_int>("func"_hs);
-
-    ASSERT_TRUE(type.func("func"_hs));
-    ASSERT_FALSE(type.func("func"_hs).next());
-
-    factory.func<&clazz::set_boxed_int>("func"_hs);
-
-    ASSERT_TRUE(type.func("func"_hs));
-    ASSERT_TRUE(type.func("func"_hs).next());
-    ASSERT_FALSE(type.func("func"_hs).next().next());
-
-    ASSERT_TRUE(type.invoke("func"_hs, instance, 2));
-    ASSERT_EQ(instance.get_int(), 2);
-
-    ASSERT_TRUE(type.invoke("func"_hs, instance, test::boxed_int{3}));
-    ASSERT_EQ(instance.get_int(), 3);
-}
-
-TEST_F(MetaVoidFactory, FuncTypeNameClash) {
-    using namespace entt::literals;
-
-    const auto value = 2;
-    const auto name = "type"_hs;
-    entt::meta_factory<void> factory{name};
-    entt::meta_func func = entt::resolve(name).func(name);
-
-    ASSERT_FALSE(func);
-
-    factory.func<&clazz::get_int>(name).custom<int>(value);
-    func = entt::resolve(name).func(name);
-
-    ASSERT_TRUE(func);
-    ASSERT_NE(static_cast<const int *>(func.custom()), nullptr);
-    ASSERT_EQ(static_cast<int>(func.custom()), value);
-}
-
-TEST_F(MetaVoidFactory, Traits) {
-    using namespace entt::literals;
-
-    entt::meta_factory<void>{"type"}
-        .data<&base::member>("member"_hs)
-        .func<&clazz::set_int>("func"_hs)
-        .func<&clazz::set_boxed_int>("func"_hs);
-
-    entt::meta_type type = entt::resolve("type"_hs);
-
-    ASSERT_EQ(type.traits<test::meta_traits>(), test::meta_traits::none);
-    ASSERT_EQ(type.data("member"_hs).traits<test::meta_traits>(), test::meta_traits::none);
-    ASSERT_EQ(type.func("func"_hs).traits<test::meta_traits>(), test::meta_traits::none);
-    ASSERT_EQ(type.func("func"_hs).next().traits<test::meta_traits>(), test::meta_traits::none);
-
-    entt::meta_factory<void>{"type"}
-        .traits(test::meta_traits::one | test::meta_traits::three)
-        .data<&base::member>("member"_hs)
-        .traits(test::meta_traits::one)
-        .func<&clazz::set_int>("func"_hs)
-        .traits(test::meta_traits::two)
-        .func<&clazz::set_boxed_int>("func"_hs)
-        .traits(test::meta_traits::three);
-
-    // traits are copied and never refreshed
-    type = entt::resolve("type"_hs);
-
-    ASSERT_EQ(type.traits<test::meta_traits>(), test::meta_traits::one | test::meta_traits::three);
-    ASSERT_EQ(type.data("member"_hs).traits<test::meta_traits>(), test::meta_traits::one);
-    ASSERT_EQ(type.func("func"_hs).traits<test::meta_traits>(), test::meta_traits::two);
-    ASSERT_EQ(type.func("func"_hs).next().traits<test::meta_traits>(), test::meta_traits::three);
-
-    entt::meta_factory<void>{"type"}
-        .traits(test::meta_traits::one, true)
-        .data<&base::member>("member"_hs)
-        .traits(test::meta_traits::one | test::meta_traits::three, true)
-        .func<&clazz::set_int>("func"_hs)
-        .traits(test::meta_traits::one | test::meta_traits::three, true)
-        .func<&clazz::set_boxed_int>("func"_hs)
-        .traits(test::meta_traits::all, true);
-
-    // traits are copied and never refreshed
-    type = entt::resolve("type"_hs);
-
-    ASSERT_EQ(type.traits<test::meta_traits>(), test::meta_traits::three);
-    ASSERT_EQ(type.data("member"_hs).traits<test::meta_traits>(), test::meta_traits::none);
-    ASSERT_EQ(type.func("func"_hs).traits<test::meta_traits>(), test::meta_traits::two);
-    ASSERT_EQ(type.func("func"_hs).next().traits<test::meta_traits>(), test::meta_traits::none);
-}
-
-TEST_F(MetaVoidFactory, Custom) {
-    using namespace entt::literals;
-
-    entt::meta_factory<void>{"type"}
-        .data<&base::member>("member"_hs)
-        .func<&clazz::set_int>("func"_hs)
-        .func<&clazz::set_boxed_int>("func"_hs);
-
-    entt::meta_type type = entt::resolve("type"_hs);
-
-    ASSERT_EQ(static_cast<const int *>(type.custom()), nullptr);
-    ASSERT_EQ(static_cast<const int *>(type.data("member"_hs).custom()), nullptr);
-    ASSERT_EQ(static_cast<const int *>(type.func("func"_hs).custom()), nullptr);
-    ASSERT_EQ(static_cast<const int *>(type.func("func"_hs).next().custom()), nullptr);
-
-    entt::meta_factory<void>{"type"}
-        .custom<int>(0)
-        .data<&base::member>("member"_hs)
-        .custom<int>(1)
-        .func<&clazz::set_int>("func"_hs)
-        .custom<int>(2)
-        .func<&clazz::set_boxed_int>("func"_hs)
-        .custom<int>(3);
-
-    // custom data pointers are copied and never refreshed
-    type = entt::resolve("type"_hs);
-
-    ASSERT_EQ(static_cast<int>(type.custom()), 0);
-    ASSERT_EQ(static_cast<int>(type.data("member"_hs).custom()), 1);
-    ASSERT_EQ(static_cast<int>(type.func("func"_hs).custom()), 2);
-    ASSERT_EQ(static_cast<int>(type.func("func"_hs).next().custom()), 3);
-}
-
-TEST_F(MetaVoidFactory, MetaReset) {
-    using namespace entt::literals;
-
-    entt::meta_ctx ctx{};
-
-    entt::meta_factory<void>{"type"};
-    entt::meta_factory<void>{ctx, "type"};
-
-    ASSERT_TRUE(entt::resolve("type"_hs));
-    ASSERT_TRUE(entt::resolve(ctx, "type"_hs));
-
-    entt::meta_reset();
-
-    ASSERT_FALSE(entt::resolve("type"_hs));
-    ASSERT_TRUE(entt::resolve(ctx, "type"_hs));
-
-    entt::meta_reset(ctx);
-
-    ASSERT_FALSE(entt::resolve("type"_hs));
-    ASSERT_FALSE(entt::resolve(ctx, "type"_hs));
-
-    entt::meta_factory<void>{"type"};
-    entt::meta_factory<void>{ctx, "type"};
-
-    ASSERT_TRUE(entt::resolve("type"_hs));
-    ASSERT_TRUE(entt::resolve(ctx, "type"_hs));
-
-    entt::meta_reset("type"_hs);
-
-    ASSERT_FALSE(entt::resolve("type"_hs));
-    ASSERT_TRUE(entt::resolve(ctx, "type"_hs));
-
-    entt::meta_reset(ctx, "type"_hs);
-
-    ASSERT_FALSE(entt::resolve("type"_hs));
-    ASSERT_FALSE(entt::resolve(ctx, "type"_hs));
-}

+ 1 - 1
test/entt/meta/meta_type.cpp

@@ -980,7 +980,7 @@ TEST_F(MetaType, ReRegistration) {
     // this should not overwrite traits and custom data
     entt::meta_factory<double>{}.type("real"_hs);
 
-    ASSERT_FALSE(entt::resolve("double"_hs));
+    ASSERT_TRUE(entt::resolve("double"_hs));
     ASSERT_TRUE(entt::resolve("real"_hs));
     ASSERT_TRUE(entt::resolve("real"_hs).data("var"_hs));