diff --git a/libs/ecs/include/psemek/ecs/container.hpp b/libs/ecs/include/psemek/ecs/container.hpp index c9e31370..1a8b24fa 100644 --- a/libs/ecs/include/psemek/ecs/container.hpp +++ b/libs/ecs/include/psemek/ecs/container.hpp @@ -364,6 +364,9 @@ namespace psemek::ecs template Index & index(Args && ... args); + template + Index & index_factory(Factory && factory); + template std::size_t memory_usage(); @@ -767,6 +770,12 @@ namespace psemek::ecs return index_container_.get(*this, std::forward(args)...); } + template + Index & container::index_factory(Factory && factory) + { + return index_container_.set(std::move(factory)); + } + template std::size_t container::memory_usage() { diff --git a/libs/ecs/include/psemek/ecs/detail/index_container.hpp b/libs/ecs/include/psemek/ecs/detail/index_container.hpp index a13bdbe5..d0e71160 100644 --- a/libs/ecs/include/psemek/ecs/detail/index_container.hpp +++ b/libs/ecs/include/psemek/ecs/detail/index_container.hpp @@ -4,6 +4,7 @@ #include #include #include +#include #include @@ -24,19 +25,21 @@ namespace psemek::ecs::detail { auto uuid = Index::uuid(); if (auto it = storage_.find(uuid); it != storage_.end()) - return *reinterpret_cast(it->second.get()); + return *reinterpret_cast(it->second()); if constexpr (std::is_constructible_v) { - auto ptr = std::make_shared(container, std::forward(args)...); - storage_.insert({uuid, ptr}); - return *ptr; + auto ptr = std::make_unique(container, std::forward(args)...); + auto result = ptr.get(); + storage_.insert({uuid, [ptr = std::move(ptr)]{ return ptr.get(); }}); + return *result; } else if constexpr (std::is_constructible_v) { - auto ptr = std::make_shared(std::forward(args)...); - storage_.insert({uuid, ptr}); - return *ptr; + auto ptr = std::make_unique(std::forward(args)...); + auto result = ptr.get(); + storage_.insert({uuid, [ptr = std::move(ptr)]{ return ptr.get(); }}); + return *result; } else { @@ -44,8 +47,20 @@ namespace psemek::ecs::detail } } + template + Index & set(Factory && factory) + { + auto uuid = Index::uuid(); + if (storage_.contains(uuid)) + throw util::exception("Index " + util::type_name() + " is already set"); + + auto result = factory(); + storage_[Index::uuid()] = std::move(factory); + return *result; + } + private: - util::hash_map> storage_; + util::hash_map> storage_; }; }