refl support ctor list

This commit is contained in:
ouczbs 2024-06-12 22:07:45 +08:00
parent 0cdc1d1948
commit a5bfccc1d8
11 changed files with 243 additions and 105 deletions

View File

@ -12,9 +12,7 @@ namespace refl {
}
inline bool Convert::Construct(Any& dst, const Any& src)
{
if (dst.Check(src.cls)) {
dst.cls->parent->InitObject((void*)dst.ptr);
dst.cls->parent->CopyObject((void*)dst.ptr, src.ptr);
if (dst.cls->CtorObject((void*)dst.ptr, src)) {
return true;
}
auto it = ClassMap.find(dst.cls);

View File

@ -36,7 +36,9 @@ namespace refl {
FIELD_MEMBER_FLAG = 1 << 0,
FIELD_ATTRIBUTE_FLAG = 1 << 1,
FIELD_METHOD_FLAG = 1 << 2,
FIELD_METHOD_VALUE_FLAG = 1 << 3
FIELD_METHOD_VALUE_FLAG = 1 << 3,
FIELD_CTOR_FLAG = 1 << 4,
FIELD_CTOR_VALUE_FLAG = 1 << 5,
};
using enum FieldFlag;
struct FieldPtr {
@ -61,6 +63,9 @@ namespace refl {
//safe
bool Invoke(svector<Any>& ArgsList)const;
template<typename TArgsList>
bool Invokes(TArgsList& ArgsList)const;
template<typename Func, typename... Args>
auto Call(Func func, Args&&... args)const;

View File

@ -34,7 +34,7 @@ namespace refl {
if (argsSize < paramsSize) {
return false;
}
Any* a = ArgsList.front();
auto a = ArgsList.front();
auto p = params.front();
for (auto e = params.back(); p < e; ++p, ++a) {
if (a->cls != *p && !a->Check(*p)) {
@ -45,6 +45,25 @@ namespace refl {
}
return Call;
}
template<typename TArgsList>
inline bool FieldPtr::Invokes(TArgsList& ArgsList)const {
auto Call = type->vtable.Call;
if (Call) {
sarray<const UClass*> params = GetParams();
if (params.size() != ArgsList.size()) {
return false;
}
auto a = ArgsList.front();
auto p = params.front();
for (auto e = params.back(); p < e; ++p, ++a) {
if (a->cls != *p && !a->Check(*p)) {
return false;
}
}
Call(this, ArgsList);
}
return false;
}
inline sarray<const UClass*> FieldPtr::GetParams() const {
auto GetParams = type->vtable.GetParams;
if (GetParams) {

View File

@ -31,6 +31,9 @@ namespace refl {
class UClass;
class Meta {
public:
template<typename T, typename... Args>
static FieldPtr CtorField(char*& memory, const MemberData& data = {});
template<typename T, typename Obj>
static FieldPtr MemberField(T Obj::* ptr, const Name& name, char*& memory, const MemberData& data = {});

View File

@ -3,7 +3,29 @@
#include "uclass.h"
#include "convert.h"
namespace refl {
template<typename T, typename ...Args>
inline FieldPtr Meta::CtorField(char*& memory, const MemberData& data)
{
MethodData method;
uint32_t flag = FIELD_MEMBER_FLAG | FIELD_CTOR_FLAG;
constexpr auto cls = &TypeInfo<void(*)(const void*, real_type_t<Args>...)>::StaticClass;
if (data.value.IsValid()) {
flag |= FIELD_CTOR_VALUE_FLAG;
AnyArgs args(data.value, cls->GetParams(), memory);
method.value = args.ToSArray();
memory += args.Size();
}
if (data.meta.IsValid()) {
method.meta = data.meta.Change(memory);
Convert::Construct(method.meta, data.meta);
memory += data.meta.Size();
}
static auto ptr = [](void* mem, Args... args) {
new (mem) T(std::forward<Args>(args)...);
};
method.fptr = { *(Method*)&ptr };
return { FName("Ctor"), cls, method,flag};
}
template<typename T, typename Obj>
inline FieldPtr Meta::MemberField(T Obj::* ptr, const Name& name, char*& memory, const MemberData& data)
{
@ -29,7 +51,7 @@ namespace refl {
MethodData method;
uint32_t flag = FIELD_METHOD_FLAG;
constexpr auto cls = &TypeInfo<real_type_t<R>(*)(real_type_t<Args>...)>::StaticClass;
if (data.value.IsValid()) {
if (data.value.valid()) {
flag |= FIELD_METHOD_VALUE_FLAG;
AnyArgs args(data.value, cls->GetParams(), memory);
method.value = args.ToSArray();
@ -49,7 +71,7 @@ namespace refl {
MethodData method;
uint32_t flag = FIELD_MEMBER_FLAG | FIELD_METHOD_FLAG;
constexpr auto cls = &TypeInfo<real_type_t<R>(*)(const void*, real_type_t<Args>...)>::StaticClass;
if (data.value.IsValid()) {
if (data.value.valid()) {
flag |= FIELD_METHOD_VALUE_FLAG;
AnyArgs args(data.value, cls->GetParams(), memory);
method.value = args.ToSArray();

View File

@ -2,6 +2,7 @@
#include "field.h"
#include "view.h"
#include "meta.h"
#include "convert.h"
namespace refl {
enum ClassFlag :uint32_t {
CLASS_NONE_FLAG = 0,
@ -10,10 +11,20 @@ namespace refl {
CLASS_ARRAY_FLAG = 1 << 2,
};
using enum ClassFlag;
enum EFieldFind :uint32_t {
FIND_ALL_FIELD = 0,
FIND_ALL_MEMBER,
FIND_ALL_METHOD,
FIND_FIELD,
FIND_CTOR,
FIND_MEMBER,
FIND_METHOD,
FIND_METHODS,//函数重载 特别是构造函数
};
struct vtable_uclass
{
//class
const FieldPtr* (*GetField)(const UClass*, const Name&, int);
const sarray<const FieldPtr> (*GetFields)(const UClass*, EFieldFind find, const Name& name);
//function
sarray<const UClass*>(*GetParams)(const UClass*);
//function
@ -21,9 +32,8 @@ namespace refl {
//meta
const UClass* (*GetMeta)(const Name&);
//object
void (*InitObject)(void*);
void (*CopyObject)(void*, const void*);
void (*DestObject)(void*);
bool (*CtorObject)(void* ptr,const UClass* cls, const sarray<Any>& ArgsList);
bool (*DestObject)(void*);
};
class UClass{
public:
@ -35,22 +45,22 @@ namespace refl {
public:
constexpr UClass(std::string_view name, uint32_t size, const UClass* parent = nullptr)
:name(name), size(size), parent(parent){}
AnyView New(void* ptr = nullptr) const{
AnyView New(void* ptr = nullptr, const sarray<Any>& ArgsList = {}) const {
if (ptr == nullptr) {
ptr = malloc(size);
InitObject(ptr);
CtorObject(ptr, ArgsList);
}
return { ptr , this };
}
template<typename T>
T* New(T* ptr = nullptr) const{
T* New(T* ptr = nullptr, const sarray<Any>& ArgsList = {}) const{
if (!IsChildOf<T>()) {
return nullptr;
}
if (ptr == nullptr) {
ptr = (T*)malloc(size);
}
InitObject(ptr);
CtorObject(ptr, ArgsList);
return ptr;
}
bool IsChildOf(const UClass* cls) const {
@ -68,27 +78,33 @@ namespace refl {
return IsChildOf(&TypeInfo<T>::StaticClass);
}
public:
const FieldPtr* GetField(const Name& name, int index)const {
if (vtable.GetField) {
return vtable.GetField(this, name, index);
const sarray<const FieldPtr> GetFields(EFieldFind find, const Name& name)const {
if (vtable.GetFields) {
return vtable.GetFields(this, find, name);
}
return nullptr;
return {};
}
void InitObject(void* ptr)const {
if (vtable.InitObject) {
vtable.InitObject(ptr);
}
else {
memset(ptr, 0, size);
}
}
void CopyObject(void* dst, const void* src)const {
if (vtable.CopyObject) {
vtable.CopyObject(dst, src);
}
else {
memcpy(dst, src, size);
bool CtorObject(void* ptr, const sarray<Any>& ArgsList = {})const {
if (vtable.CtorObject) {
if (vtable.CtorObject(ptr, this, ArgsList)) {
return true;
}
auto& fieldList = GetFields(EFieldFind::FIND_CTOR, FName("Ctor"));
if (fieldList.empty()) {
return false;
}
if (fieldList.size() == 1) {
return fieldList[0]->Invoke(ArgsList);
}
for (auto& field : fieldList) {
if (field.Invokes(ArgsList)) {
return true;
}
}
return false;
}
memset(ptr, 0, size);
return true;
}
void DestObject(void* ptr)const {
if (vtable.DestObject) {
@ -96,30 +112,23 @@ namespace refl {
}
}
public:
template<_ReflCheck_Ctor T>
static void InitObject(void* ptr) {
T obj{};
std::construct_at((T*)ptr, obj);
}
template<typename T>
static void CopyObject(void* dst, const void* src) {
*(T*)dst = *(T*)src;
}
template<_ReflCheck_Ctor T, int N>
static void InitObject(void* ptr) {
T* tptr = (T*)ptr;
T obj{};
for (int i = 0; i < N; i++) {
std::construct_at(tptr++, obj);
static bool CtorObject(void* ptr, const UClass* cls, const sarray<Any>& ArgsList = {}) {
int size = ArgsList.size();
if (size == 0) {
if constexpr (std::is_trivially_constructible_v<T>) {
std::construct_at((T*)ptr);
return true;
}
else {
throw "refl::error:: no default construct function!!!";
}
}
}
template<typename T, int N>
static void CopyObject(void* dst, const void* src) {
T* tdst = (T*)dst;
const T* tsrc = (const T*)src;
for (int i = 0; i < N; i++) {
*tdst++ = *tsrc++;
if (size == 1 && ArgsList[0]->Check(cls)) {
*(T*)ptr = *(const T*)ArgsList[0]->ptr;
return true;
}
return false;
}
};
}

View File

@ -10,20 +10,14 @@ namespace refl {
public:
consteval static MyUClass BuildClass() {
MyUClass cls(type_name<T>().View(), sizeof(T));
if constexpr (!std::is_trivially_copyable_v<T>) {
cls.vtable.InitObject = &MyUClass::InitObject<T>;
cls.vtable.CopyObject = &MyUClass::CopyObject<T>;
}
else if constexpr (std::is_pointer_v<T>){
cls.vtable.CtorObject = &MyUClass::CtorObject<T>;
if constexpr (std::is_pointer_v<T>){
using RawT = std::remove_pointer_t<T>;
cls.flag = CLASS_POINTER_FLAG;
if constexpr (!std::is_same_v<RawT, void>) {
cls.parent = &TypeInfo<RawT>::StaticClass;
}
}
else {
cls.flag = CLASS_TRIVIAL_FLAG;
}
if constexpr (requires {typename T::MyMetas; }) {
cls.vtable.GetMeta = &T::MyMetas::GetMeta;
}
@ -44,15 +38,11 @@ namespace refl {
public:
consteval static MyUClass BuildClass() {
MyUClass cls(type_name<T[N]>().View(), sizeof(T) * N, &TypeInfo<T>::StaticClass);
if constexpr (!std::is_trivially_copyable_v<T>) {
cls.vtable.InitObject = &MyUClass::InitObject<T, N>;
cls.vtable.CopyObject = &MyUClass::CopyObject<T, N>;
}
else if constexpr (std::is_pointer_v<T>) {
if constexpr (std::is_pointer_v<T>) {
cls.flag = CLASS_POINTER_FLAG | CLASS_ARRAY_FLAG;
}
else {
cls.flag = CLASS_TRIVIAL_FLAG | CLASS_ARRAY_FLAG;
cls.flag = CLASS_ARRAY_FLAG;
}
return cls;
}
@ -133,31 +123,71 @@ namespace refl {
if constexpr (!std::is_same_v<P, void>) {
parent = &TypeInfo<P>::StaticClass;
}
if constexpr (requires(void* ptr) {T::__InitObject(ptr);}) {
vtable.InitObject = &T::__InitObject;
}
else {
vtable.InitObject = &UClass::InitObject<T>;
}
if constexpr (requires(const Name & name) { T::MyMetas::GetMeta(name); }) {
vtable.GetMeta = &T::MyMetas::GetMeta;
}
vtable.GetField = &UClass_Meta::GetField;
vtable.GetFields = &UClass_Meta::GetFields;
}
const FieldPtr* GetField(int index) const {
return &Fields[index];
}
static const FieldPtr* GetField(const UClass* _cls,const Name& name, int index = 0){
auto cls = static_cast<const UClass_Meta*>(_cls);
auto& Fields = cls->Fields;
const sarray<const FieldPtr> GetFields(EFieldFind find, const Name& name) const {
constexpr int length = std::tuple_size<FieldsType>::value;
auto ptr = index < length ? &Fields[index] : nullptr;
for (int i = index; i < length; i++, ptr++) {
if (name == ptr->name) {
return ptr;
constexpr int MemberCount = MyMeta::MyStatic::MemberCount();
constexpr int CtorCount = MyMeta::MyStatic::CtorCount();
switch (find) {
case EFieldFind::FIND_ALL_FIELD:
return sarray<const FieldPtr>(&Fields[0], length);
case EFieldFind::FIND_ALL_MEMBER:
return sarray<const FieldPtr>(&Fields[0], MemberCount);
case EFieldFind::FIND_ALL_METHOD:
return sarray<const FieldPtr>(&Fields[MemberCount + CtorCount], length - MemberCount - CtorCount);
case EFieldFind::FIND_CTOR:
return sarray<const FieldPtr>(&Fields[MemberCount], CtorCount);
case EFieldFind::FIND_FIELD:
for (int i = 0; i < length; i++) {
if (name == Fields[i].name) {
return sarray<const FieldPtr>(&Fields[i], 1);
}
}
return {};
case EFieldFind::FIND_MEMBER:
for (int i = 0; i < MemberCount; i++) {
if (name == Fields[i].name) {
return sarray<const FieldPtr>(&Fields[i], 1);
}
}
return {};
case EFieldFind::FIND_METHOD:
for (int i = MemberCount + CtorCount; i < length; i++) {
if (name == Fields[i].name) {
return sarray<const FieldPtr>(&Fields[i], 1);
}
}
return {};
case EFieldFind::FIND_METHODS:
{
int first = 0,count = 0;
for (int i = MemberCount + CtorCount; i < length; i++) {
if (name == Fields[i].name) {
if (!count) {
first = i;
}
count++;
}
else if (count) {
return sarray<const FieldPtr>(&Fields[first], count);
}
}
return {};
}
return nullptr;
default:
return {};
}
}
static const sarray<const FieldPtr> GetFields(const UClass* _cls, EFieldFind find, const Name& name) {
auto cls = static_cast<const UClass_Meta*>(_cls);
return cls->GetFields(find, name);
}
};

View File

@ -29,6 +29,8 @@ namespace refl {
bool Invoke(const Name& name,svector<Any>& ArgsList);
bool Invokes(const Name& name, const sarray<Any>& ArgsList);
bool Invokes(const Name& name, svector<Any>& ArgsList);
AnyView Parent();
};
}

View File

@ -12,13 +12,7 @@ namespace refl {
auto p2 = toClass->parent;
assert(p1 && p2);
//子类转父类
if (p1->IsChildOf(p2)) {
return true;
}
if (p1->flag & CLASS_TRIVIAL_FLAG && p2->flag & CLASS_TRIVIAL_FLAG && p1->size >= p2->size) {
return true;
}
return false;
return p1->IsChildOf(p2);
}
inline constexpr int Any::Size()const
{
@ -94,9 +88,9 @@ namespace refl {
}
return isChild;
}
auto field = cls->GetField(name, 0);
if (field) {
cache = field;
auto& fieldList = cls->GetFields(EFieldFind::FIND_MEMBER, name);
if (fieldList.valid()) {
cache = fieldList.front();
goto _cache_get;
}
if (cls->parent) {
@ -114,9 +108,9 @@ namespace refl {
}
return isChild;
}
auto field = cls->GetField(name, 0);
if (field) {
cache = field;
auto& fieldList = cls->GetFields(EFieldFind::FIND_MEMBER, name);
if (fieldList.valid()) {
cache = fieldList.front();
goto _cache_set;
}
if (cls->parent) {
@ -126,25 +120,61 @@ namespace refl {
}
inline bool AnyView::Invoke(const Name& name,const sarray<Any>& ArgsList)
{
auto field = cls->GetField(name, 0);
if (!field) {
auto& fieldList = cls->GetFields(EFieldFind::FIND_METHOD, name);
if (fieldList.empty()) {
if (cls->parent) {
return Parent().Invoke(name, ArgsList);
}
return false;
}
return field->Invoke(ArgsList);
return fieldList[0]->Invoke(ArgsList);
}
inline bool AnyView::Invoke(const Name& name, svector<Any>& ArgsList)
{
auto field = cls->GetField(name, 0);
if (!field) {
auto fieldList = cls->GetFields(EFieldFind::FIND_METHOD, name);
if (fieldList.empty()) {
if (cls->parent) {
return Parent().Invoke(name, ArgsList);
}
return false;
}
return field->Invoke(ArgsList);
return fieldList[0]->Invoke(ArgsList);
}
inline bool AnyView::Invokes(const Name& name, const sarray<Any>& ArgsList)
{
auto fieldList = cls->GetFields(EFieldFind::FIND_METHOD, name);
if (fieldList.empty()) {
if (cls->parent) {
return Parent().Invoke(name, ArgsList);
}
return false;
}
if(fieldList.size() == 1)
return fieldList[0]->Invoke(ArgsList);
for (auto& field : fieldList) {
if (field.Invokes(ArgsList)) {
return true;
}
}
return false;
}
inline bool AnyView::Invokes(const Name& name, svector<Any>& ArgsList)
{
auto fieldList = cls->GetFields(EFieldFind::FIND_METHOD, name);
if (fieldList.empty()) {
if (cls->parent) {
return Parent().Invoke(name, ArgsList);
}
return false;
}
if (fieldList.size() == 1)
return fieldList[0]->Invoke(ArgsList);
for (auto& field : fieldList) {
if (field.Invokes(ArgsList)) {
return true;
}
}
return false;
}
inline AnyView AnyView::Parent() {
return { ptr, cls ? cls->parent : nullptr };

View File

@ -6,6 +6,17 @@
#include "detail/meta.inl"
#include "macro.h"
namespace refl {
template<typename T, typename... Args>
consteval FieldPtr StaticCtorField(const MemberData& data = {}) {
uint32_t flag = FIELD_CTOR_FLAG;
auto cls = &TypeInfo<void(*)(void*, real_type_t<Args>...)>::StaticClass;
Offset offset = AnyArgs::GetArgsSize(data.value, cls->GetParams());
if (data.meta.IsValid()) {
offset += data.meta.Size();
}
FieldPtr::Data method(offset);
return {FName("Ctor"),cls,method, flag};
}
template<typename T, typename Obj>
consteval FieldPtr StaticMemberField(T Obj::* ptr, const Name& name, const MemberData& data = {}) {
Offset offset = data.value.IsValid() ? sizeof(T) : 0;
@ -38,6 +49,7 @@ namespace refl {
FieldPtr::Data method(offset);
return { name, cls,method,flag };
}
/*
//用处不大---------------begin
template<_ReflCheck_Meta T>
consteval int GetStaticFieldID(const Name& name) {
@ -74,4 +86,5 @@ namespace refl {
}
}
//用处不大---------------end
*/
}

View File

@ -8,6 +8,7 @@ namespace zstd {
const T* m_ptr;
int m_count;
public:
constexpr sarray(const T& ptr) : m_ptr(&ptr), m_count(1) {}
constexpr sarray(const T* ptr, int count) : m_ptr(ptr), m_count(count) {}
constexpr sarray(const svector<T>& vec) : m_ptr(vec.front()), m_count(vec.size()) {}
constexpr sarray() : m_ptr(nullptr), m_count(0) {}
@ -24,7 +25,13 @@ namespace zstd {
}
return nullptr;
}
constexpr bool IsValid() const noexcept {
constexpr const T* operator[](int i) const noexcept {
if (i < m_count) {
return m_ptr + i;
}
return nullptr;
}
constexpr bool valid() const noexcept {
return m_count > 0;
}
constexpr bool empty() const noexcept {