404 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			404 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
#pragma once
 | 
						||
#include <array>
 | 
						||
#include "uclass.h"
 | 
						||
#include <iostream>
 | 
						||
namespace refl {
 | 
						||
	template <class T>
 | 
						||
	concept _ReflCheck_Metas = requires(const Name & name) { MetaImpl<T>::MyMetas::GetMeta(name); };
 | 
						||
 | 
						||
	template<typename 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_pointer_v<T>){
 | 
						||
				using RT = std::remove_pointer_t<T>;
 | 
						||
				cls.flag = CLASS_POINTER_FLAG;
 | 
						||
				if constexpr (!std::is_same_v<RT, void>) {
 | 
						||
					cls.parent = &TypeInfo<RT>::StaticClass;
 | 
						||
				}
 | 
						||
			}
 | 
						||
			else if constexpr (is_array<T>::value) {
 | 
						||
				using RT = typename is_array<T>::type;
 | 
						||
				cls.flag =  CLASS_ARRAY_FLAG;
 | 
						||
				if constexpr (std::is_pointer_v<RT>) {
 | 
						||
					cls.flag |= CLASS_POINTER_FLAG;
 | 
						||
				}
 | 
						||
				cls.parent = &TypeInfo<RT>::StaticClass;
 | 
						||
			}
 | 
						||
			else {
 | 
						||
				cls.vtable.Construct = &MyUClass::Construct<T>;
 | 
						||
				cls.vtable.Destruct = &UClass::Destruct<T>;
 | 
						||
			}
 | 
						||
			if constexpr (_ReflCheck_Metas<T>) {
 | 
						||
				cls.vtable.GetMeta = &MetaImpl<T>::MyMetas::GetMeta;
 | 
						||
			}
 | 
						||
			return cls;
 | 
						||
		}
 | 
						||
		void Set(void* ptr,const T& t) {
 | 
						||
			*(T*)ptr = t;
 | 
						||
		}
 | 
						||
		T& Get(void* ptr) {
 | 
						||
			return *(T*)ptr;
 | 
						||
		}
 | 
						||
	};
 | 
						||
	/*
 | 
						||
	* 模板优化
 | 
						||
	* 成员参数转化为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>::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... Types>
 | 
						||
	class UClass_Tuple : public UClass {
 | 
						||
		using UClass::UClass;
 | 
						||
		using MyUClass = UClass_Tuple<Types...>;
 | 
						||
		using MyTuple = std::tuple<Types...>;
 | 
						||
	public:
 | 
						||
		std::array<FieldPtr, sizeof...(Types)> Fields;
 | 
						||
		static bool construct(void* ptr, const UClass* cls, const sarray<Any>& ArgsList) {
 | 
						||
			new(ptr)MyTuple();
 | 
						||
			return true;
 | 
						||
		}
 | 
						||
		static void destruct(void* ptr) {
 | 
						||
			((MyTuple*)ptr)->~MyTuple();
 | 
						||
		}
 | 
						||
		template <typename T, std::size_t Index>
 | 
						||
		static FieldPtr field_in_tuple() {
 | 
						||
			constexpr uint32_t flag = FIELD_MEMBER_FLAG | FIELD_ATTRIBUTE_FLAG;
 | 
						||
			const MyTuple* tuple_ptr = nullptr;
 | 
						||
			const auto& element = std::get<Index>(*tuple_ptr);
 | 
						||
			const std::ptrdiff_t offset = reinterpret_cast<const char*>(&element) - reinterpret_cast<const char*>(tuple_ptr);
 | 
						||
			MemberData member;
 | 
						||
			member.offset = offset;
 | 
						||
			return { IndexNames[Index], &TypeInfo<T>::StaticClass, member, flag};
 | 
						||
		}
 | 
						||
		template <std::size_t... Is>
 | 
						||
		void BuildFields(std::index_sequence<Is...>) {
 | 
						||
			auto ptr = &Fields[0];
 | 
						||
			(..., (*ptr = field_in_tuple<Types, Is>(), ptr++));
 | 
						||
		}
 | 
						||
		UClass_Tuple():UClass(type_name<MyTuple>().View(), sizeof(MyTuple)) {
 | 
						||
			assert(sizeof...(Types) < IndexNames.size());
 | 
						||
			BuildFields(std::index_sequence_for<Types...>{});
 | 
						||
			vtable.Construct = &MyUClass::construct;
 | 
						||
			vtable.Destruct = &MyUClass::destruct;
 | 
						||
			vtable.GetFields = &MyUClass::GetFields;
 | 
						||
		}
 | 
						||
		const sarray<const FieldPtr> GetFields(EFieldFind find, const Name& name) const {
 | 
						||
			return sarray<const FieldPtr>(&Fields[0], sizeof...(Types));
 | 
						||
		}
 | 
						||
		static const sarray<const FieldPtr> GetFields(const UClass* _cls, EFieldFind find, const Name& name) {
 | 
						||
			auto cls = static_cast<const MyUClass*>(_cls);
 | 
						||
			return cls->GetFields(find, name);
 | 
						||
		}
 | 
						||
	};
 | 
						||
	template<typename First,typename Second>
 | 
						||
	class UClass_Pair : public UClass {
 | 
						||
		using UClass::UClass;
 | 
						||
		using MyUClass = UClass_Pair<First, Second>;
 | 
						||
		using MyPair = std::pair<First, Second>;
 | 
						||
	public:
 | 
						||
		std::array<FieldPtr, 2> Fields;
 | 
						||
		static bool construct(void* ptr, const UClass* cls, const sarray<Any>& ArgsList) {
 | 
						||
			new(ptr)MyPair();
 | 
						||
			return true;
 | 
						||
		}
 | 
						||
		static void destruct(void* ptr) {
 | 
						||
			((MyPair*)ptr)->~MyPair();
 | 
						||
		}
 | 
						||
		template<typename T, int Index>
 | 
						||
		static FieldPtr field_in_pair() {
 | 
						||
			constexpr uint32_t flag = FIELD_MEMBER_FLAG | FIELD_ATTRIBUTE_FLAG;
 | 
						||
			const MyPair* pair_ptr = nullptr;
 | 
						||
			MemberData member;
 | 
						||
			if constexpr (Index == 0) {
 | 
						||
				const auto& first = pair_ptr->first;
 | 
						||
				const std::ptrdiff_t offset = reinterpret_cast<const char*>(&first) - reinterpret_cast<const char*>(pair_ptr);
 | 
						||
				member.offset = offset;
 | 
						||
			}
 | 
						||
			else {
 | 
						||
				const auto& second = pair_ptr->second;
 | 
						||
				const std::ptrdiff_t offset = reinterpret_cast<const char*>(&second) - reinterpret_cast<const char*>(pair_ptr);
 | 
						||
				member.offset = offset;
 | 
						||
			}
 | 
						||
			return { IndexNames[Index], &TypeInfo<T>::StaticClass, member, flag };
 | 
						||
		}
 | 
						||
		UClass_Pair() :UClass(type_name<MyPair>().View(), sizeof(MyPair)) {
 | 
						||
			Fields[0] = field_in_pair<First, 0>();
 | 
						||
			Fields[1] = field_in_pair<Second, 1>();
 | 
						||
			vtable.Construct = &MyUClass::construct;
 | 
						||
			vtable.Destruct = &MyUClass::destruct;
 | 
						||
			vtable.GetFields = &MyUClass::GetFields;
 | 
						||
		}
 | 
						||
		const sarray<const FieldPtr> GetFields(EFieldFind find, const Name& name) const {
 | 
						||
			return sarray<const FieldPtr>(&Fields[0], 2);
 | 
						||
		}
 | 
						||
		static const sarray<const FieldPtr> GetFields(const UClass* _cls, EFieldFind find, const Name& name) {
 | 
						||
			auto cls = static_cast<const MyUClass*>(_cls);
 | 
						||
			return cls->GetFields(find, name);
 | 
						||
		}
 | 
						||
	};
 | 
						||
	class UClass_Container : public UClass {
 | 
						||
	public:
 | 
						||
		using UClass::UClass;
 | 
						||
		struct iterator {
 | 
						||
			void* ptr;
 | 
						||
			void* val;
 | 
						||
		};
 | 
						||
		//container
 | 
						||
		using size_impl = size_t(*)(const void*);
 | 
						||
		using to_iterator_impl = void(*)(iterator& ,const void*);
 | 
						||
		using insert_impl = void (*)(const void*, const void*);
 | 
						||
		//iterator
 | 
						||
		using iterator_impl = void (*)(iterator*);
 | 
						||
	public:
 | 
						||
		size_impl vsize;
 | 
						||
		to_iterator_impl vbegin;
 | 
						||
		to_iterator_impl vend;
 | 
						||
		insert_impl vinsert;
 | 
						||
		iterator_impl viterator_add;
 | 
						||
		iterator_impl viterator_sub;
 | 
						||
		template<typename T>
 | 
						||
		static void insert(const void* ptr, const void* obj) {
 | 
						||
			using value_type = typename T::value_type;
 | 
						||
			if constexpr (is_sequence_v<T>) {
 | 
						||
				((T*)ptr)->push_back(*(value_type*)obj);
 | 
						||
			}
 | 
						||
			else if constexpr (is_map_v<T>) {
 | 
						||
				((T*)ptr)->insert(*(value_type*)obj);
 | 
						||
			}
 | 
						||
		}
 | 
						||
	};
 | 
						||
	template<is_container_v T, typename value_type>
 | 
						||
	class UClass_Container_impl : public UClass_Container {
 | 
						||
		using UClass_Container::UClass_Container;
 | 
						||
		using MyUClass = UClass_Container_impl<T, value_type>;
 | 
						||
	public:
 | 
						||
		static bool construct(void* ptr, const UClass* cls, const sarray<Any>& ArgsList) {
 | 
						||
			new(ptr)T();
 | 
						||
			return true;
 | 
						||
		}
 | 
						||
		static void destruct(void* ptr) {
 | 
						||
			((T*)ptr)->~T();
 | 
						||
		}
 | 
						||
		static void begin(iterator& pit,const void* ptr) {
 | 
						||
			auto it = ((T*)ptr)->begin();
 | 
						||
  			memcpy(&pit, &it, sizeof(it));
 | 
						||
			pit.val = &*it;
 | 
						||
		}		
 | 
						||
		static void end(iterator& pit, const void* ptr) {
 | 
						||
			auto it = ((T*)ptr)->end();
 | 
						||
			memcpy(&pit, &it, sizeof(it));
 | 
						||
			pit.val = &*it;
 | 
						||
		}
 | 
						||
		static void add(iterator* pit) {
 | 
						||
			auto it = ++(*(typename T::iterator*)pit);
 | 
						||
			memcpy(pit, &it, sizeof(it));
 | 
						||
			pit->val = &*it;
 | 
						||
		}
 | 
						||
		static void sub(iterator* pit) {
 | 
						||
			auto it = --(*(typename T::iterator*)pit);
 | 
						||
			memcpy(pit, &it, sizeof(it));
 | 
						||
			pit->val = &*it;
 | 
						||
		}
 | 
						||
		UClass_Container_impl() : UClass_Container(type_name<T>().View(), sizeof(T)) {
 | 
						||
			parent = &TypeInfo<value_type>::StaticClass;
 | 
						||
			flag = CLASS_CONTAINER_FLAG;
 | 
						||
			vtable.Construct = &MyUClass::construct;
 | 
						||
			vtable.Destruct = &MyUClass::destruct;
 | 
						||
			if constexpr (is_sequence_v<T>) {
 | 
						||
				flag |= CLASS_SEQUENCE_FLAG;
 | 
						||
			}
 | 
						||
			else if constexpr (is_map_v<T>) 
 | 
						||
			{
 | 
						||
				flag |= CLASS_MAP_FLAG;
 | 
						||
			}
 | 
						||
			auto __size = &T::size;
 | 
						||
			vsize = *(size_impl*)&__size;
 | 
						||
			vbegin = &MyUClass::begin;
 | 
						||
			vend = &MyUClass::end;
 | 
						||
			vinsert = &MyUClass::insert<T>;
 | 
						||
 | 
						||
			viterator_add = &MyUClass::add;
 | 
						||
			viterator_sub = &MyUClass::sub;
 | 
						||
		};
 | 
						||
	};
 | 
						||
	template<typename T, typename MyMeta>
 | 
						||
	class UClass_Meta : public UClass {
 | 
						||
	public:
 | 
						||
		using FieldsType = decltype(MyMeta::__MakeFields());
 | 
						||
		FieldsType Fields{ 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 (_ReflCheck_Parent<MyMeta>) {
 | 
						||
				parent = &TypeInfo<typename MyMeta::MyParent>::StaticClass;
 | 
						||
				flag |= CLASS_PARENT_FLAG;
 | 
						||
			}
 | 
						||
			if constexpr (_ReflCheck_Metas<T>) {
 | 
						||
				vtable.GetMeta = &MetaImpl<T>::MyMetas::GetMeta;
 | 
						||
			}
 | 
						||
			vtable.GetFields = &UClass_Meta::GetFields;
 | 
						||
			vtable.Construct = &UClass::Construct<T>;
 | 
						||
			vtable.Destruct = &UClass::Destruct<T>;
 | 
						||
			MetaTable[name] = this;
 | 
						||
		}
 | 
						||
		const FieldPtr* GetField(int index) const {
 | 
						||
			return &Fields[index];
 | 
						||
		}
 | 
						||
		const sarray<const FieldPtr> GetFields(EFieldFind find, const Name& name) const {
 | 
						||
			constexpr int length = std::tuple_size<FieldsType>::value;
 | 
						||
			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 {};
 | 
						||
			}
 | 
						||
			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);
 | 
						||
		}
 | 
						||
	};
 | 
						||
	template<typename T>
 | 
						||
	struct TypeInfoImpl {
 | 
						||
		using MyUClass = UClass_Auto<T>;
 | 
						||
		inline constexpr static MyUClass StaticClass = MyUClass::BuildClass();
 | 
						||
	};
 | 
						||
	template<>
 | 
						||
	struct TypeInfoImpl<void> {
 | 
						||
		inline constexpr static UClass StaticClass = { type_name<void>().View(), 0 };
 | 
						||
	};
 | 
						||
	template<_ReflCheck_UClass T>
 | 
						||
	struct TypeInfoImpl<T> {
 | 
						||
		using MyUClass = UClass_Meta<T, typename MetaImpl<T>::MyMeta>;
 | 
						||
		inline static MyUClass StaticClass = MyUClass();
 | 
						||
	};
 | 
						||
	template<typename... Types>
 | 
						||
	struct TypeInfoImpl<std::tuple<Types...>> {
 | 
						||
		using MyUClass = UClass_Tuple<Types...>;
 | 
						||
		inline static MyUClass StaticClass = MyUClass();
 | 
						||
	};
 | 
						||
	template<typename First, typename Second>
 | 
						||
	struct TypeInfoImpl<std::pair<First, Second>> {
 | 
						||
		using MyUClass = UClass_Pair<First, Second>;
 | 
						||
		inline static MyUClass StaticClass = MyUClass();
 | 
						||
	};
 | 
						||
	template<is_container_v T>
 | 
						||
	struct TypeInfoImpl<T> {
 | 
						||
		using MyUClass = UClass_Container_impl<T, typename T::value_type>;
 | 
						||
		inline static MyUClass StaticClass = MyUClass();
 | 
						||
	};
 | 
						||
	// 函数指针类型的偏特化
 | 
						||
	template<typename R, typename... Args>
 | 
						||
	struct TypeInfoImpl<R(*)(Args...)> {
 | 
						||
		using MyUClass = UMethod_Auto<R, Args...>;
 | 
						||
		inline constexpr static MyUClass StaticClass = MyUClass::BuildClass();
 | 
						||
	};
 | 
						||
} |