diff --git a/src/babylon/application_context.cpp b/src/babylon/application_context.cpp index b97ad82..5e7aa8b 100644 --- a/src/babylon/application_context.cpp +++ b/src/babylon/application_context.cpp @@ -115,7 +115,6 @@ Any ApplicationContext::ComponentHolder::create(ApplicationContext& context, void ApplicationContext::ComponentHolder::for_each_type( const ::std::function& callback) const noexcept { - callback(&_type_id->type_id); for (auto& pair : _convert_offset) { callback(pair.first); } @@ -191,7 +190,7 @@ ApplicationContext::EmptyComponentHolder //////////////////////////////////////////////////////////////////////////////// // ApplicationContext::EmptyComponentHolder begin ApplicationContext::EmptyComponentHolder::EmptyComponentHolder() noexcept - : ComponentHolder {static_cast(nullptr)} {} + : ComponentHolder {static_cast(nullptr)} {} Any ApplicationContext::EmptyComponentHolder::create_instance() noexcept { return {}; diff --git a/src/babylon/application_context.h b/src/babylon/application_context.h index c203cb1..a74c763 100644 --- a/src/babylon/application_context.h +++ b/src/babylon/application_context.h @@ -200,6 +200,16 @@ class ApplicationContext::ComponentHolder { int initialize(Any& instance, ApplicationContext& context, const Any& option) noexcept; + // 设置实例类型信息,用于支持构造函数的实现 + template + void set_type() noexcept; + template + void add_convertible_type() noexcept; + template + void add_convertible_type() noexcept; + template + void remove_convertible_type() noexcept; + // 使用空参create_instance构造实例,之后探测协议函数并调用 // 一般情况下实现空参版本即可,特殊情况下例如想要更换或禁用探测协议函数,可以重写此入口 virtual Any create_instance(ApplicationContext& context, @@ -225,14 +235,6 @@ class ApplicationContext::ComponentHolder { // 查询转换到指定类型所需的偏移量,无法转换时返回最大值PTRDIFF_MAX ptrdiff_t convert_offset(const Id* type) const noexcept; - // 设置实例类型信息,用于支持构造函数的实现 - template - void set_type() noexcept; - template - void add_convertible_type() noexcept; - template - void add_convertible_type() noexcept; - void create_singleton(ApplicationContext& context) noexcept; inline ::std::atomic& atomic_singleton_state() noexcept; @@ -546,13 +548,6 @@ ApplicationContext::get_or_create(StringView name) noexcept { //////////////////////////////////////////////////////////////////////////////// // ApplicationContext::ComponentHolder begin -template -ABSL_ATTRIBUTE_NOINLINE ApplicationContext::ComponentHolder::ComponentHolder( - T*, BS*...) noexcept { - set_type(); - add_convertible_type(); -} - template ABSL_ATTRIBUTE_NOINLINE void ApplicationContext::ComponentHolder::set_option( T&& option) noexcept { @@ -561,9 +556,6 @@ ABSL_ATTRIBUTE_NOINLINE void ApplicationContext::ComponentHolder::set_option( template inline ptrdiff_t ApplicationContext::ComponentHolder::offset() const noexcept { - if (Any::descriptor() == _type_id) { - return 0; - } return convert_offset(&Any::descriptor()->type_id); } @@ -603,6 +595,13 @@ ApplicationContext::ComponentHolder::type_id() const noexcept { return &(_type_id->type_id); } +template +ABSL_ATTRIBUTE_NOINLINE ApplicationContext::ComponentHolder::ComponentHolder( + T*, BS*...) noexcept { + set_type(); + add_convertible_type(); +} + template ABSL_ATTRIBUTE_NOINLINE void ApplicationContext::ComponentHolder::set_type() noexcept { @@ -618,15 +617,19 @@ ApplicationContext::ComponentHolder::add_convertible_type() noexcept {} template ABSL_ATTRIBUTE_NOINLINE void ApplicationContext::ComponentHolder::add_convertible_type() noexcept { - if (TypeId::ID != TypeId::ID) { - _convert_offset[&TypeId::ID] = - reinterpret_cast( - static_cast(reinterpret_cast(alignof(T)))) - - alignof(T); - } + _convert_offset[&TypeId::ID] = + reinterpret_cast( + static_cast(reinterpret_cast(alignof(T)))) - + alignof(T); add_convertible_type(); } +template +ABSL_ATTRIBUTE_NOINLINE void +ApplicationContext::ComponentHolder::remove_convertible_type() noexcept { + _convert_offset.erase(&TypeId::ID); +} + inline ABSL_ATTRIBUTE_ALWAYS_INLINE ::std::atomic< ApplicationContext::ComponentHolder::SingletonState>& ApplicationContext::ComponentHolder::atomic_singleton_state() noexcept { diff --git a/test/test_application_context.cpp b/test/test_application_context.cpp index 0c5efc2..31aceed 100644 --- a/test/test_application_context.cpp +++ b/test/test_application_context.cpp @@ -118,6 +118,55 @@ TEST_F(ApplicationContextTest, create_convertible_to_parent_registered) { ASSERT_FALSE(context.component_accessor()); } +TEST_F(ApplicationContextTest, fix_conflict_by_remove_some_convertible_type) { + struct P { + int vp = 1; + }; + struct C : public P { + int vc = 1; + }; + struct CAsPHolder : public DefaultComponentHolder { + CAsPHolder() : DefaultComponentHolder {} { + remove_convertible_type(); + } + static ::std::unique_ptr create() { + return {new CAsPHolder, {}}; + } + }; + { + context.register_component(DefaultComponentHolder::create()); + context.register_component(DefaultComponentHolder::create()); + ASSERT_FALSE(context.component_accessor()); + ASSERT_TRUE(context.component_accessor

()); + context.clear(); + } + { + context.register_component(DefaultComponentHolder::create()); + context.register_component(CAsPHolder::create()); + ASSERT_TRUE(context.component_accessor()); + ASSERT_TRUE(context.component_accessor

()); + context.clear(); + } + { + context.register_component(DefaultComponentHolder::create()); + context.register_component(DefaultComponentHolder::create(), "P"); + ASSERT_FALSE(context.component_accessor()); + ASSERT_TRUE(context.component_accessor

()); + ASSERT_TRUE(context.component_accessor("P")); + ASSERT_TRUE(context.component_accessor

("P")); + context.clear(); + } + { + context.register_component(DefaultComponentHolder::create()); + context.register_component(CAsPHolder::create(), "P"); + ASSERT_TRUE(context.component_accessor()); + ASSERT_TRUE(context.component_accessor

()); + ASSERT_FALSE(context.component_accessor("P")); + ASSERT_TRUE(context.component_accessor

("P")); + context.clear(); + } +} + TEST_F(ApplicationContextTest, create_with_auto_initialize_if_exist) { { struct Initializable {