#include #include #include #include #include #include #include #include #include struct base_t { base_t() : value{'c'} {} char value; }; struct derived_t: base_t { derived_t() : base_t{} {} }; struct clazz_t { clazz_t(const base_t &other, int &iv) : clazz_t{iv, other.value} {} clazz_t(const int &iv, char cv) : i{iv}, c{cv} {} operator int() const { return i; } static clazz_t factory(int value) { return {value, 'c'}; } static clazz_t factory(base_t other, int value, int mul) { return {value * mul, other.value}; } int i{}; char c{}; }; double double_factory() { return 42.; } struct MetaCtor: ::testing::Test { void SetUp() override { using namespace entt::literals; entt::meta() .type("double"_hs) .ctor(); entt::meta() .type("derived"_hs) .base(); entt::meta() .type("clazz"_hs) .ctor<&entt::registry::emplace_or_replace, entt::as_ref_t>() .ctor() .ctor() .ctor(clazz_t::factory)>() .ctor(clazz_t::factory)>() .conv(); } void TearDown() override { entt::meta_reset(); } }; TEST_F(MetaCtor, Functionalities) { auto any = entt::resolve().construct(42, 'c'); ASSERT_TRUE(any); ASSERT_EQ(any.cast().i, 42); ASSERT_EQ(any.cast().c, 'c'); } TEST_F(MetaCtor, Func) { auto any = entt::resolve().construct(42); ASSERT_TRUE(any); ASSERT_EQ(any.cast().i, 42); ASSERT_EQ(any.cast().c, 'c'); } TEST_F(MetaCtor, MetaAnyArgs) { auto any = entt::resolve().construct(entt::meta_any{42}, entt::meta_any{'c'}); ASSERT_TRUE(any); ASSERT_EQ(any.cast().i, 42); ASSERT_EQ(any.cast().c, 'c'); } TEST_F(MetaCtor, InvalidArgs) { ASSERT_FALSE(entt::resolve().construct(entt::meta_any{}, derived_t{})); } TEST_F(MetaCtor, CastAndConvert) { auto any = entt::resolve().construct(derived_t{}, clazz_t{42, 'd'}); ASSERT_TRUE(any); ASSERT_EQ(any.cast().i, 42); ASSERT_EQ(any.cast().c, 'c'); } TEST_F(MetaCtor, ArithmeticConversion) { auto any = entt::resolve().construct(true, 4.2); ASSERT_TRUE(any); ASSERT_EQ(any.cast().i, 1); ASSERT_EQ(any.cast().c, char{4}); } TEST_F(MetaCtor, ConstNonConstRefArgs) { int ivalue = 42; const char cvalue = 'c'; auto any = entt::resolve().construct(entt::forward_as_meta(ivalue), entt::forward_as_meta(cvalue)); ASSERT_TRUE(any); ASSERT_EQ(any.cast().i, 42); ASSERT_EQ(any.cast().c, 'c'); } TEST_F(MetaCtor, WrongConstness) { int value = 42; auto any = entt::resolve().construct(derived_t{}, entt::forward_as_meta(value)); auto other = entt::resolve().construct(derived_t{}, entt::forward_as_meta(std::as_const(value))); ASSERT_TRUE(any); ASSERT_FALSE(other); ASSERT_EQ(any.cast().i, 42); ASSERT_EQ(any.cast().c, 'c'); } TEST_F(MetaCtor, FuncMetaAnyArgs) { auto any = entt::resolve().construct(entt::meta_any{42}); ASSERT_TRUE(any); ASSERT_EQ(any.cast().i, 42); ASSERT_EQ(any.cast().c, 'c'); } TEST_F(MetaCtor, FuncCastAndConvert) { auto any = entt::resolve().construct(derived_t{}, 3., clazz_t{3, 'd'}); ASSERT_TRUE(any); ASSERT_EQ(any.cast().i, 9); ASSERT_EQ(any.cast().c, 'c'); } TEST_F(MetaCtor, FuncArithmeticConversion) { auto any = entt::resolve().construct(4.2); ASSERT_TRUE(any); ASSERT_EQ(any.cast().i, 4); ASSERT_EQ(any.cast().c, 'c'); } TEST_F(MetaCtor, FuncConstNonConstRefArgs) { int ivalue = 42; auto any = entt::resolve().construct(entt::forward_as_meta(ivalue)); auto other = entt::resolve().construct(entt::forward_as_meta(std::as_const(ivalue))); ASSERT_TRUE(any); ASSERT_TRUE(other); ASSERT_EQ(any.cast().i, 42); ASSERT_EQ(other.cast().i, 42); } TEST_F(MetaCtor, ExternalMemberFunction) { entt::registry registry; const auto entity = registry.create(); ASSERT_FALSE(registry.all_of(entity)); const auto any = entt::resolve().construct(entt::forward_as_meta(registry), entity, 3, 'c'); ASSERT_TRUE(any); ASSERT_TRUE(registry.all_of(entity)); ASSERT_EQ(registry.get(entity).i, 3); ASSERT_EQ(registry.get(entity).c, 'c'); } TEST_F(MetaCtor, OverrideImplicitlyGeneratedDefaultConstructor) { auto type = entt::resolve(); auto any = type.construct(); ASSERT_TRUE(any); ASSERT_EQ(any.type(), entt::resolve()); ASSERT_EQ(any.cast(), 42.); } TEST_F(MetaCtor, NonDefaultConstructibleType) { auto type = entt::resolve(); // no implicitly generated default constructor ASSERT_FALSE(type.construct()); } TEST_F(MetaCtor, ReRegistration) { SetUp(); auto &&node = entt::internal::resolve(entt::internal::meta_context::from(entt::locator::value_or())); ASSERT_TRUE(node.details); ASSERT_FALSE(node.details->ctor.empty()); // implicitly generated default constructor is not cleared ASSERT_NE(node.default_constructor, nullptr); }