commit
						2a17ecac50
					
				@ -0,0 +1,6 @@
 | 
				
			||||
cmake_minimum_required(VERSION 3.25)
 | 
				
			||||
project(c_base)
 | 
				
			||||
 | 
				
			||||
set(CMAKE_CXX_STANDARD 17)
 | 
				
			||||
 | 
				
			||||
add_executable(c_base main.cpp)
 | 
				
			||||
@ -0,0 +1,151 @@
 | 
				
			||||
#include <iostream>
 | 
				
			||||
#include <string>
 | 
				
			||||
#include <functional>
 | 
				
			||||
#include <unordered_map>
 | 
				
			||||
#include <string_view>
 | 
				
			||||
// 自动注册实现
 | 
				
			||||
 | 
				
			||||
template<typename T>
 | 
				
			||||
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<Base *()>;
 | 
				
			||||
using BMap = std::unordered_map<std::string_view, BFun>;
 | 
				
			||||
 | 
				
			||||
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<typename T>
 | 
				
			||||
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<T>();
 | 
				
			||||
        }
 | 
				
			||||
 | 
				
			||||
        const std::string_view &className() const {
 | 
				
			||||
            static std::string_view class_name = type_name<T>();
 | 
				
			||||
            return class_name;
 | 
				
			||||
        }
 | 
				
			||||
 | 
				
			||||
        template<typename D>
 | 
				
			||||
        typename std::enable_if<std::is_default_constructible<D>::value,
 | 
				
			||||
                void>::type
 | 
				
			||||
        registerClass() {
 | 
				
			||||
            Dic::reg(className(), []() -> Base * { return new T(); });
 | 
				
			||||
        }
 | 
				
			||||
 | 
				
			||||
        template<typename D>
 | 
				
			||||
        typename std::enable_if<!std::is_default_constructible<D>::value,
 | 
				
			||||
                void>::type
 | 
				
			||||
        registerClass() {
 | 
				
			||||
 | 
				
			||||
        }
 | 
				
			||||
    };
 | 
				
			||||
 | 
				
			||||
    static Allocator allocator;
 | 
				
			||||
};
 | 
				
			||||
 | 
				
			||||
template<typename T>
 | 
				
			||||
typename BaseObj<T>::Allocator BaseObj<T>::allocator;
 | 
				
			||||
 | 
				
			||||
 | 
				
			||||
//
 | 
				
			||||
class A : public BaseObj<A> {
 | 
				
			||||
public:
 | 
				
			||||
};
 | 
				
			||||
 | 
				
			||||
 | 
				
			||||
class B : public BaseObj<B> {
 | 
				
			||||
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;
 | 
				
			||||
}
 | 
				
			||||
					Loading…
					
					
				
		Reference in new issue