#include #include #include #include #include // 自动注册实现 template constexpr auto type_name() noexcept { std::string_view name, prefix, suffix; #ifdef __clang__ name = __PRETTY_FUNCTION__; prefix = "auto type_name() [T = "; suffix = "]"; #elif defined(__GNUC__) name = __PRETTY_FUNCTION__; prefix = "constexpr auto type_name() [with T = "; suffix = "]"; #elif defined(_MSC_VER) name = __FUNCSIG__; prefix = "auto __cdecl type_name<"; suffix = ">(void) noexcept"; #endif name.remove_prefix(prefix.size()); name.remove_suffix(suffix.size()); return name; } // 基类 class Base { public: virtual const std::string_view className() const { return "base"; }; virtual ~Base() { } }; using BFun = std::function; using BMap = std::unordered_map; class Dic { public: static void reg(std::string_view className, const BFun &fun) { getMap().insert(std::make_pair(className, fun)); } static BMap &getMap() { static BMap bMap; return bMap; } }; template class BaseObj : public virtual Base { public: const std::string_view className() const override { return allocator.className(); } static const std::string_view getClassName() { return allocator.className(); } protected: BaseObj() {}; ~BaseObj() override = default; private: class Allocator { public: Allocator() { registerClass(); } const std::string_view &className() const { static std::string_view class_name = type_name(); return class_name; } template typename std::enable_if::value, void>::type registerClass() { Dic::reg(className(), []() -> Base * { return new T(); }); } template typename std::enable_if::value, void>::type registerClass() { } }; static Allocator allocator; }; template typename BaseObj::Allocator BaseObj::allocator; // class A : public BaseObj { public: }; class B : public BaseObj { public: }; // 工厂类 class Factory { public: static Base *create(const std::string & className) { BMap map = Dic::getMap(); auto iter = map.find(className); if (iter != map.end()) { return iter->second(); } return nullptr; } }; int main() { auto aa = Factory::create("A"); auto bb = Factory::create("B"); if (aa != nullptr) { std::cout << aa->className() << std::endl; } if (bb != nullptr) { std::cout << bb->className() << std::endl; } std::cout << "hello world!" << std::endl; return 0; }