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