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