#include #include #include #include #include #include class AbstractTest { public: virtual void yeah() { std::cout << "I'm AbstractTest! " << typeid(AbstractTest).name() << std::endl; } }; class Test : public AbstractTest { public: void yeah() override { log(); } void log() { std::cout << "I'm Test! " << typeid(Test).name() << std::endl; } }; class Test2 : public AbstractTest { public: void log() { std::cout << "I'm Test2! " << typeid(Test).name() << std::endl; } }; namespace ioc { class Container { public: class AbstractInstance { public: virtual ~AbstractInstance() {} }; template class Instance : public AbstractInstance { public: Instance(T *ptr) : ptr(ptr) {} std::shared_ptr ptr; }; template void registerType(std::function callback) { m_callbacks[std::type_index(typeid(T))] = callback; } template std::shared_ptr make() { auto type = std::type_index(typeid(T)); auto search = m_instances.find(type); if (search != m_instances.end()) { auto instance = std::static_pointer_cast>(search->second); return instance->ptr; } void *ptr = m_callbacks[type](); auto instance = std::make_shared>(static_cast(ptr)); m_instances[type] = instance; return instance->ptr; } protected: std::unordered_map> m_callbacks; std::unordered_map> m_instances; }; } int main() { ioc::Container container; container.registerType([]() { return new Test(); }); // container.registerType([]() { // return new Test2(); // }); auto test = container.make(); // test->log(); test->yeah(); // auto test2 = container.make(); // std::cout << (test == test2) << std::endl; return 0; }