zengine/engine/modules/engine/zlib/include/refl/detail/uclass.inl
2024-10-22 21:52:43 +08:00

73 lines
2.0 KiB
C++

#include "uclass.h"
#include "name.h"
#include "type.h"
namespace refl {
template <class T>
concept is_metas_v = requires(const Name & name) { Meta<T>::GetMeta(name); };
template<typename T>
class UClass_Auto : public UClass {
public:
UClass_Auto() : UClass(type_name<T>().View(), sizeof(T)) {
if constexpr (std::is_pointer_v<T>) {
using RT = std::remove_pointer_t<T>;
flag |= CLASS_POINTER_FLAG;
if constexpr (!std::is_same_v<RT, void>) {
parent = type_info<RT>();
}
}
else if constexpr (is_array_v<T>) {
using RT = is_array_t<T>;
flag = CLASS_ARRAY_FLAG;
if constexpr (std::is_pointer_v<RT>) {
flag |= CLASS_POINTER_FLAG;
}
parent = type_info<RT>();
}
else {
vtable.Add(string_hash("Construct"), (void*)&UClass::Construct<T>);
vtable.Add(string_hash("Destruct"), (void*)&UClass::Destruct<T>);
}
}
};
template<typename T, typename MetaImpl>
class UClass_Meta : public UClass {
using FieldsType = decltype(MetaImpl::MakeFields());
FieldsType Fields{ MetaImpl::MakeFields() };
UClass_Meta() : UClass(type_name<T>().View(), sizeof(T)) {
if constexpr (has_parent_v<T>) {
parent = type_info<parent_t<T>>();
}
}
};
inline UniquePtr<table<Name, const UClass*>, string_hash("refl::ClassTable")> ClassTablePtr;
inline const UClass* find_info(Name name) {
auto& ClassTable = *ClassTablePtr.Ptr();
if (auto it = ClassTable.find(name); it != ClassTable.end()) {
return it->second;
}
return nullptr;
}
template<typename Type>
inline const UClass* type_info()
{
using T = real_type_t<Type>;
constexpr auto name = type_name<T>();
if (auto cls = find_info(name.View())) {
return cls;
}
UClass* cls;
if constexpr (is_meta_v<T>){
cls = new(GlobalPool()) UClass_Meta<T, meta_t<T>>{};
}
else if constexpr (std::is_same_v<T, void>) {
cls = new(GlobalPool()) UClass{ name.View(), 0 };
}
else {
cls = new(GlobalPool()) UClass_Auto<T>{};
}
auto& ClassTable = *ClassTablePtr.Ptr();
ClassTable[name.View()] = cls;
return cls;
}
}