diff --git a/core/env_test.hh b/core/env_test.hh index a687458..b493d32 100644 --- a/core/env_test.hh +++ b/core/env_test.hh @@ -29,22 +29,17 @@ class EnvFixture : public ::testing::Test { protected: template - void Install(const std::shared_ptr& o) { - fmap_.emplace(typeid(I), [o](auto&) { return o; }); - } - template - void Install(std::function(Env&)>&& factory) { - fmap_.emplace(typeid(I), std::move(factory)); + void Install(SimpleEnv::ObjectOrFactory&& v) { + map_.emplace(typeid(I), std::move(v)); } template void Install() { - fmap_.emplace( - typeid(I), [](auto& env) { return std::make_shared(env); }); + map_.insert(SimpleEnv::MakeItem()); } protected: void SetUp() override { - env_.emplace(std::move(fmap_)); + env_.emplace(std::move(map_)); } void TearDown() override { env_ = std::nullopt; @@ -54,7 +49,7 @@ class EnvFixture : public ::testing::Test { Env& env() noexcept { return *env_; } private: - SimpleEnv::FactoryMap fmap_; + SimpleEnv::Map map_; std::optional env_; }; diff --git a/core/meta_env_test.cc b/core/meta_env_test.cc index ba2254d..5e49429 100644 --- a/core/meta_env_test.cc +++ b/core/meta_env_test.cc @@ -6,18 +6,16 @@ #include "iface/env.hh" -static inline std::shared_ptr MakeEmptyEnv() { - return std::make_shared(nf7::SimpleEnv::FactoryMap {}); -} -static inline bool MatchPair(const std::optional& a, - const nf7::subsys::MetaEnv::Pair& b) { +static inline bool MatchPair( + const std::optional& a, + const nf7::subsys::MetaEnv::Pair& b) { return a && a->first == b.first && &a->second == &b.second; } TEST(MetaEnv, FindOrByName) { - const auto a = MakeEmptyEnv(); - const auto b = MakeEmptyEnv(); - const auto c = MakeEmptyEnv(); + const auto a = std::make_shared(); + const auto b = std::make_shared(); + const auto c = std::make_shared(); nf7::core::MetaEnv sut { { @@ -35,9 +33,9 @@ TEST(MetaEnv, FindOrByName) { } TEST(MetaEnv, FindOrByIndex) { - const auto a = MakeEmptyEnv(); - const auto b = MakeEmptyEnv(); - const auto c = MakeEmptyEnv(); + const auto a = std::make_shared(); + const auto b = std::make_shared(); + const auto c = std::make_shared(); nf7::core::MetaEnv sut { { @@ -54,9 +52,9 @@ TEST(MetaEnv, FindOrByIndex) { } TEST(MetaEnv, FetchAll) { - const auto a = MakeEmptyEnv(); - const auto b = MakeEmptyEnv(); - const auto c = MakeEmptyEnv(); + const auto a = std::make_shared(); + const auto b = std::make_shared(); + const auto c = std::make_shared(); nf7::core::MetaEnv sut { { diff --git a/iface/common/container.hh b/iface/common/container.hh index e147a49..23e397f 100644 --- a/iface/common/container.hh +++ b/iface/common/container.hh @@ -8,6 +8,7 @@ #include #include #include +#include #include #include "iface/common/exception.hh" @@ -27,7 +28,6 @@ class Container { Container& operator=(Container&&) = delete; virtual std::shared_ptr Get(std::type_index) = 0; - virtual bool installed(std::type_index) const noexcept = 0; template void Get(std::shared_ptr& out) { @@ -57,42 +57,34 @@ class Container { const auto& ret = Get(idx); return nullptr != ret? ret: def; } - - template - bool installed() const noexcept { - return installed(typeid(T)); - } }; template class NullContainer : public Container { public: - static std::shared_ptr instance() - try { - static const auto kInstance = std::make_shared(); - return kInstance; - } catch (const std::bad_alloc&) { - throw MemoryException {}; - } + static inline const auto kInstance = std::make_shared(); public: NullContainer() = default; public: std::shared_ptr Get(std::type_index) override { return nullptr; } - bool installed(std::type_index) const noexcept override { return false; } }; template class SimpleContainer : public Container { public: - using Factory = std::function(Container&)>; - using FactoryPair = std::pair; - using FactoryMap = std::unordered_map; - using ObjectMap = std::unordered_map>; + using Object = std::shared_ptr; + using Factory = std::function&)>; + using ObjectOrFactory = std::variant; + + using MapItem = std::pair; + using Map = std::unordered_map; + + public: template - static FactoryPair MakePair() noexcept { + static MapItem MakeItem() noexcept { static_assert(std::is_base_of_v, "registerable interface must be based on " "container common interface"); @@ -102,62 +94,47 @@ class SimpleContainer : public Container { static_assert(std::is_constructible_v&>, "registerable concrete type must be " "constructible with container"); - return FactoryPair { - typeid(I2), [](auto& x) { return std::make_shared(x); }}; - } - static std::shared_ptr> Make(FactoryMap&& factories) { - try { - return std::make_shared>(std::move(factories)); - } catch (const std::bad_alloc&) { - throw MemoryException {}; - } + return MapItem { + typeid(I2), + [](auto& x) { return std::make_shared(x); }, + }; } - SimpleContainer() = delete; - SimpleContainer(FactoryMap&& factories, - Container& fb = *NullContainer::instance()) noexcept - : fallback_(fb), factories_(std::move(factories)) { } + public: + SimpleContainer(Map&& m = {}, + Container& fb = *NullContainer::kInstance) noexcept + : fallback_(fb), map_(std::move(m)) { } - std::shared_ptr Get(std::type_index idx) override { - const auto obj_itr = objs_.find(idx); - if (objs_.end() != obj_itr) { - return obj_itr->second; + public: + Object Get(std::type_index idx) override { + assert(nest_ < 1000 && "circular dependency detected"); + + auto itr = map_.find(idx); + if (map_.end() == itr) { + return fallback_.Get(idx); } - const auto factory_itr = factories_.find(idx); - if (factories_.end() != factory_itr) { - assert(nest_ < 1000 && - "circular dependency detected in container factory"); + auto& v = itr->second; + auto ret = Object {nullptr}; + if (std::holds_alternative(v)) { + ret = std::get(v); + } else { ++nest_; - auto obj = factory_itr->second(*this); + ret = std::get(v)(*this); --nest_; - - try { - const auto [itr, added] = objs_.insert({idx, std::move(obj)}); - (void) itr; - (void) added; - assert(added); - return itr->second; - } catch (...) { - throw MemoryException {}; - } + v = ret; } - return fallback_.Get(idx); - } - - bool installed(std::type_index idx) const noexcept override { - return factories_.contains(idx) || fallback_.installed(idx); + return nullptr != ret? ret: + throw Exception {"the specified interface is hidden"}; } using Container::Get; using Container::GetOr; - using Container::installed; private: Container& fallback_; - FactoryMap factories_; - ObjectMap objs_; + Map map_; uint32_t nest_ = 0; }; diff --git a/iface/common/container_test.cc b/iface/common/container_test.cc index 24325c2..bea800d 100644 --- a/iface/common/container_test.cc +++ b/iface/common/container_test.cc @@ -35,15 +35,15 @@ class BRecursive : public IB { TEST(SimpleContainer, FetchIsolated) { SUT sut {{ - SUT::MakePair(), + SUT::MakeItem(), }}; auto ptr = sut.Get(); EXPECT_TRUE(std::dynamic_pointer_cast(ptr)); } TEST(SimpleContainer, FetchDepending) { SUT sut {{ - SUT::MakePair(), - SUT::MakePair(), + SUT::MakeItem(), + SUT::MakeItem(), }}; auto ptr = sut.Get(); EXPECT_TRUE(std::dynamic_pointer_cast(ptr)); @@ -54,21 +54,14 @@ TEST(SimpleContainer, FetchUnknown) { } TEST(SimpleContainer, FetchUnknownDepending) { SUT sut {{ - SUT::MakePair(), + SUT::MakeItem(), }}; EXPECT_THROW(sut.Get(), nf7::Exception); } -TEST(SimpleContainer, CheckInstalled) { - SUT sut {{ - SUT::MakePair(), - }}; - EXPECT_TRUE(sut.installed()); - EXPECT_FALSE(sut.installed()); -} TEST(SimpleContainer, FetchWithFallback) { SUT fb {{ - SUT::MakePair(), + SUT::MakeItem(), }}; SUT sut {{}, fb}; auto ptr = sut.Get(); @@ -79,19 +72,11 @@ TEST(SimpleContainer, FetchUnknownWithFallback) { SUT sut {{}, fb}; EXPECT_THROW(sut.Get(), nf7::Exception); } -TEST(SimpleContainer, CheckInstalledWithFallback) { - SUT fb {{ - SUT::MakePair(), - }}; - SUT sut {{}, fb}; - EXPECT_TRUE(sut.installed()); - EXPECT_FALSE(sut.installed()); -} #if !defined(NDEBUG) TEST(SimpleContainer, DeathByFetchRecursive) { SUT sut {{ - SUT::MakePair(), + SUT::MakeItem(), }}; ASSERT_DEATH_IF_SUPPORTED(sut.Get(), ""); }