183 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			183 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
#pragma once
 | 
						||
#include <array>
 | 
						||
#include "uclass.h"
 | 
						||
namespace refl {
 | 
						||
	template<_ReflCheck_Ctor T>
 | 
						||
	class UClass_Auto : public UClass {
 | 
						||
	public:
 | 
						||
		using UClass::UClass;
 | 
						||
		using MyUClass = UClass_Auto<T>;
 | 
						||
	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>){
 | 
						||
				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;
 | 
						||
			}
 | 
						||
			return cls;
 | 
						||
		}
 | 
						||
		void Set(void* ptr,const T& t) {
 | 
						||
			*(T*)ptr = t;
 | 
						||
		}
 | 
						||
		T& Get(void* ptr) {
 | 
						||
			return *(T*)ptr;
 | 
						||
		}
 | 
						||
	};
 | 
						||
	template<_ReflCheck_Ctor T, int N>
 | 
						||
	class UClass_Array : public UClass {
 | 
						||
	public:
 | 
						||
		using UClass::UClass;
 | 
						||
		using MyUClass = UClass_Array<T, N>;
 | 
						||
	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>) {
 | 
						||
				cls.flag = CLASS_POINTER_FLAG | CLASS_ARRAY_FLAG;
 | 
						||
			}
 | 
						||
			else {
 | 
						||
				cls.flag = CLASS_TRIVIAL_FLAG | CLASS_ARRAY_FLAG;
 | 
						||
			}
 | 
						||
			return cls;
 | 
						||
		}
 | 
						||
	};
 | 
						||
	/*
 | 
						||
	* 模板优化
 | 
						||
	* 成员参数转化为const void*
 | 
						||
	* 引用参数转化为指针
 | 
						||
	* 返回引用转化为指针
 | 
						||
	*/
 | 
						||
	template<typename R, typename... Args>
 | 
						||
	class UMethod_Auto : public UClass {
 | 
						||
		using UClass::UClass;
 | 
						||
		using MethodType = R(*)(Args...);
 | 
						||
		using MyUClass = UMethod_Auto<R, Args...>;
 | 
						||
	public:
 | 
						||
		std::array<const UClass*, sizeof...(Args) + 1> UList{};
 | 
						||
		consteval sarray<const UClass*> GetParams()const {
 | 
						||
			return sarray<const UClass*>(&UList.front(), UList.size());
 | 
						||
		}
 | 
						||
		static sarray<const UClass*> GetParams(const UClass* cls) {
 | 
						||
			auto& UList = static_cast<const MyUClass*>(cls)->UList;
 | 
						||
			return sarray<const UClass*>(&UList.front(),UList.size());
 | 
						||
		}
 | 
						||
		//这里顺序似乎是不确定的,但是我实际运用是对的
 | 
						||
		//如果使用make_index_sequence,会多一次函数调用
 | 
						||
		//为什么包裹一层迭代器,就不会出现警告了
 | 
						||
		static void Call(const FieldPtr* field, const sarray<Any>& ArgsList) {
 | 
						||
			assert(sizeof...(Args) <= ArgsList.size());
 | 
						||
			if constexpr (std::is_same_v<R, void>) {
 | 
						||
				MethodType fptr = (MethodType)field->data.method.fptr;
 | 
						||
				auto param = ArgsList.end();
 | 
						||
				fptr((param--->CastTo<Args>())...);
 | 
						||
			}
 | 
						||
			else {
 | 
						||
				MethodType fptr = (MethodType)field->data.method.fptr;
 | 
						||
				auto param = ArgsList.end();
 | 
						||
				auto ret = ArgsList.front();
 | 
						||
				if (ret->cls == &TypeInfo<R*>::StaticClass) {
 | 
						||
					*(R*)ret->ptr = fptr((param--->CastTo<Args>())...);
 | 
						||
				}
 | 
						||
				else {
 | 
						||
					fptr((param--->CastTo<Args>())...);
 | 
						||
				}
 | 
						||
			}
 | 
						||
		}
 | 
						||
	protected:
 | 
						||
		consteval void BuildUList() {
 | 
						||
			if constexpr (!std::is_same_v<R, void>) {
 | 
						||
				UList[0] = &TypeInfo<R*>::StaticClass;
 | 
						||
			}
 | 
						||
			if constexpr (sizeof...(Args) > 0) {
 | 
						||
				auto ptr = &UList[1];
 | 
						||
				(..., (*ptr = &TypeInfo<args_type_t<Args>*>::StaticClass, ptr++));
 | 
						||
			}
 | 
						||
		}
 | 
						||
	public:
 | 
						||
		//为了简化判断,cls 对象 统统指向 T*
 | 
						||
		consteval static MyUClass BuildClass() {
 | 
						||
			MyUClass cls(type_name<MethodType>().View(), sizeof(MethodType));
 | 
						||
			cls.vtable.GetParams = &MyUClass::GetParams;
 | 
						||
			cls.vtable.Call = &MyUClass::Call;
 | 
						||
			cls.flag = CLASS_TRIVIAL_FLAG;
 | 
						||
			cls.BuildUList();
 | 
						||
			return cls;
 | 
						||
		}
 | 
						||
	};
 | 
						||
	template<typename T, typename P = void>
 | 
						||
	class UClass_Meta : public UClass {
 | 
						||
	public:
 | 
						||
		using FieldsType = decltype(T::MyMeta::__MakeFields());
 | 
						||
		FieldsType Fields{ T::MyMeta::__MakeFields() };
 | 
						||
		UClass_Meta() : UClass(type_name<T>().View(), sizeof(T)){
 | 
						||
			if constexpr (std::is_trivially_copyable_v<T>) {
 | 
						||
				flag = CLASS_TRIVIAL_FLAG;
 | 
						||
			}
 | 
						||
			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::__GetMeta(name); }) {
 | 
						||
				vtable.GetMeta = &T::__GetMeta;
 | 
						||
			}
 | 
						||
			vtable.GetField = &UClass_Meta::GetField;
 | 
						||
		}
 | 
						||
		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;
 | 
						||
			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; 
 | 
						||
				}
 | 
						||
			}
 | 
						||
			return nullptr;
 | 
						||
		} 
 | 
						||
	};
 | 
						||
 | 
						||
	//基础类型的偏特化
 | 
						||
	template<_ReflCheck_Ctor_NoUClass T>
 | 
						||
	struct TypeInfoImpl<T> {
 | 
						||
		using UClass = UClass_Auto<T>;
 | 
						||
		inline constexpr static UClass StaticClass = UClass::BuildClass();
 | 
						||
	};
 | 
						||
 | 
						||
	// 函数指针类型的偏特化
 | 
						||
	template<typename R, typename... Args>
 | 
						||
	struct TypeInfoImpl<R(*)(Args...)> {
 | 
						||
		using UClass = UMethod_Auto<R, Args...>;
 | 
						||
		inline constexpr static UClass StaticClass = UClass::BuildClass();
 | 
						||
	};
 | 
						||
	template<_ReflCheck_UClass T>
 | 
						||
	struct TypeInfoImpl<T> {
 | 
						||
		using MyUClass = typename T::MyMeta::MyUClass;
 | 
						||
		inline static MyUClass StaticClass = MyUClass();
 | 
						||
	};
 | 
						||
	template<typename T, int N>
 | 
						||
	struct TypeInfoImpl<T[N]> {
 | 
						||
		using UClass = UClass_Array<T,N>;
 | 
						||
		inline constexpr static UClass StaticClass = UClass::BuildClass();
 | 
						||
	};
 | 
						||
} |