🚀 C++ RTTI反射系统深度设计文档
🌌 核心架构图
架构说明:
- Object基类:所有反射类的共同基类,提供
GetType()
接口- RTTI系统:核心反射引擎,管理类型元数据
- 类型注册表:全局类名字典,支持动态创建和类型查找
- 字段元数据:存储字段类型、偏移量和访问方法
🔄 类型注册流程
注册流程关键点:
- 类注册:
RTTI_S
宏创建内部RTTI类并初始化元数据 - 字段注册:
RTTI_FIELD
计算字段偏移量并推导类型 - 完成注册:
RTTI_E
宏结束注册过程
🧠 内存布局与访问原理
🧩 关键代码实现:
// 基于偏移量的内存访问
template <typename TValue>
TValue& RTTI::Field::GetValue(Object* obj) noexcept {return *(TValue*)((char*)obj + Offset);
}// 偏移量计算宏
#define RTTI_OFFSET_OF(class, field) \(reinterpret_cast<size_t>(&reinterpret_cast<char&>( \reinterpret_cast<class*>(0)->field)))
内存访问原理:
- 偏移量计算:在注册时计算字段在类中的内存偏移
- 直接内存访问:通过
对象指针 + 偏移量
直接访问字段内存 - 零开销:无虚函数调用,无中间层,直接操作内存
🔍 类型推导系统
🧬 类型推导核心代码:
template <typename T>
struct TypeTraits {static constexpr bool IsContainer = false;static constexpr bool IsPointer = false;// ... 其他类型特征
};// 容器类型特化
template <typename T>
struct TypeTraits<std::vector<T>> {static constexpr bool IsContainer = true;using ElementType = T;static constexpr ListType ContainerType = ListType_kVector;
};// 智能指针特化
template <typename T>
struct TypeTraits<std::shared_ptr<T>> {static constexpr bool IsPointer = true;using PointeeType = T;static constexpr ReferenceType PtrType = ReferenceType_kSharedPointer;
};// 类型推导入口
template <typename T>
Field CreateField(const std::string& name, size_t offset) {if constexpr (TypeTraits<T>::IsContainer) {using Element = typename TypeTraits<T>::ElementType;Field field(name, offset, FieldType::Container);field.ElementType = CreateField<Element>("", 0);return field;}else if constexpr (TypeTraits<T>::IsPointer) {using Pointee = typename TypeTraits<T>::PointeeType;Field field(name, offset, FieldType::Reference);field.PointeeType = CreateField<Pointee>("", 0);return field;}// ... 其他类型处理
}
类型推导特点:
- 编译期推导:使用模板特化和constexpr在编译期完成类型分析
- 递归处理:支持嵌套类型如
vector<shared_ptr<GameObject>>
- 类型特征萃取:通过TypeTraits提取类型特征信息
📦 容器操作原理
🧪 容器访问示例:
// 获取容器元素指针
void* RTTI::Field::GetElementPointer(Object* obj, int index) {switch (ContainerType) {case ListType_kVector:auto& vec = *reinterpret_cast<std::vector<char>*>((char*)obj + Offset);return vec.data() + index * ElementType.Size;case ListType_kQueue:auto& que = *reinterpret_cast<std::queue<char>*>((char*)obj + Offset);// 特殊处理队列访问return AccessQueueElement(que, index);// 其他容器类型处理}
}// 修改vector元素
template <typename TValue>
bool RTTI::Field::SetValue(Object* obj, int index, const TValue& value) {if (ListType == ListType_kVector) {auto& vec = GetValue<std::vector<TValue>>(obj);if (index >= 0 && index < vec.size()) {vec[index] = value;return true;}}return false; // 边界检查失败
}
容器操作关键:
- 类型安全访问:通过模板确保类型正确性
- 边界检查:防止越界访问
- 零拷贝:直接操作容器内存,避免不必要的拷贝
🧲 智能指针支持
🔌 智能指针操作:
// 获取智能指针指向的对象
template <typename T>
T* RTTI::Field::GetPointedObject(Object* obj) {if (ReferenceType == ReferenceType_kSharedPointer) {auto& ptr = GetValue<std::shared_ptr<T>>(obj);return ptr.get();}else if (ReferenceType == ReferenceType_kUniquePointer) {auto& ptr = GetValue<std::unique_ptr<T>>(obj);return ptr.get();}return nullptr;
}// 重置智能指针
template <typename T>
void RTTI::Field::ResetPointer(Object* obj, T* newPtr) {if (ReferenceType == ReferenceType_kSharedPointer) {auto& ptr = GetValue<std::shared_ptr<T>>(obj);ptr.reset(newPtr);}else if (ReferenceType == ReferenceType_kUniquePointer) {auto& ptr = GetValue<std::unique_ptr<T>>(obj);ptr.reset(newPtr);}
}
智能指针支持特点:
- 安全访问:通过get()方法获取原始指针,避免直接暴露
- 生命周期管理:支持reset等操作管理对象生命周期
- 空指针检测:自动处理空指针情况
⚙️ 宏系统实现原理
🔬 宏展开示例:
// 原始代码
RTTI_S(GameObject)
RTTI_FIELD(position)
RTTI_E// 展开后
class __RTTI__GameObject : public RTTI {
public:static __RTTI__GameObject r;__RTTI__GameObject() {GlobalRegistry::Register("GameObject", []{ return new GameObject(); },this);// 注册字段RegisterField("position", offsetof(GameObject, position),TypeTraits<Vector3>::GetTypeInfo());}
};
__RTTI__GameObject __RTTI__GameObject::r;// 在GameObject类中添加
virtual RTTI* GetType() const override {return &__RTTI__GameObject::r;
}
宏系统优势:
- 简化注册:用户只需简单宏调用即可完成复杂注册
- 自动生成代码:在预处理阶段生成必要的RTTI代码
- 隔离复杂性:用户无需了解底层实现细节
⚡ 性能优化设计
性能优化措施:
-
内存访问优化:
// 直接内存访问,无函数调用开销 #define DIRECT_ACCESS(ptr, offset) \(*reinterpret_cast<std::decay_t<decltype(ptr)>*>( \reinterpret_cast<char*>(ptr) + offset))
-
编译期类型解析:
template <typename T> constexpr FieldType DeduceFieldType() {if constexpr (std::is_integral_v<T>) return FieldType::Int;else if constexpr (std::is_floating_point_v<T>) return FieldType::Float;// ... 其他类型 }
-
快速注册表查找:
class GlobalRegistry { private:static std::unordered_map<std::string, RTTI*> typeMap;static std::unordered_map<std::string, CreatorFunc> creatorMap;public:template <typename T>static void Register(const std::string& name) {typeMap[name] = T::GetStaticType();creatorMap[name] = []{ return new T(); };} };
🧪 完整操作示例
典型使用场景:
// 动态创建对象
GameObject* obj = RTTI::New("GameObject");// 获取类型信息
RTTI* type = obj->GetType();// 遍历所有字段
for (auto& field : type->GetFields()) {std::cout << "Field: " << field.Name << " Type: " << field.TypeName();
}// 修改字段值
if (auto* posField = type->GetField("position")) {Vector3 newPos(10, 20, 30);posField->SetValue(obj, newPos);
}
🔧 框架扩展机制
🧩 扩展示例:
// 添加自定义容器支持
template <typename T>
struct is_custom_container : std::false_type {};template <typename T>
struct is_custom_container<MyVector<T>> : std::true_type {};// 在类型推导中添加处理分支
template <typename T>
Field CreateField(const std::string& name, size_t offset) {if constexpr (is_custom_container<T>::value) {Field field(name, offset, FieldType::CustomContainer);// 实现自定义访问方法field.GetElement = [](void* container, int index) {return &static_cast<MyVector<char>*>(container)->GetElement(index);};return field;}// ... 其他类型
}// 序列化扩展
void Serialize(Object* obj, std::ostream& out) {RTTI* type = obj->GetType();for (auto& field : type->GetFields()) {out << field.Name << ": ";if (field.IsBasicType()) {// 基础类型序列化}else if (field.IsContainer()) {// 容器序列化}}
}
扩展能力:
- 新容器支持:通过模板特化添加新容器类型
- 序列化:基于反射自动序列化/反序列化
- 脚本绑定:自动生成脚本语言绑定代码
- 编辑器集成:自动生成属性面板
📊 类型系统总览
详细类型支持矩阵
类型类别 | 具体类型 | C++示例 | RTTI表示 |
---|---|---|---|
基础类型 | 整数 | int , int32_t | BasicType_kInt |
浮点数 | float , double | BasicType_kFloat | |
字符串 | std::string | BasicType_kString | |
布尔 | bool | BasicType_kBoolean | |
容器类型 | 动态数组 | std::vector | ListType_kVector |
队列 | std::queue | ListType_kQueue | |
静态数组 | std::array | ListType_kStatic | |
集合 | std::set | ListType_kSet | |
指针类型 | 原始指针 | GameObject* | ReferenceType_kPointer |
共享指针 | std::shared_ptr | ReferenceType_kSharedPointer | |
唯一指针 | std::unique_ptr | ReferenceType_kUniquePointer | |
值类型 | 自定义类 | Vector3 | FieldType_Custom |
🏆 框架优势总结
-
高性能设计:
- 直接内存访问(零抽象开销)
- 编译期类型解析(零运行时成本)
- 哈希表快速查找(O(1)复杂度)
-
强大类型支持:
// 支持复杂嵌套类型 class Scene {std::vector<std::shared_ptr<GameObject>> objects;std::map<int, std::array<float, 4>> colorPalette;RTTI_FIELD(objects);RTTI_FIELD(colorPalette); };
-
安全保证:
- 类型安全访问
- 容器边界检查
- 空指针检测
-
可扩展架构:
// 轻松添加新功能 RTTI_REGISTER_EXTENSION(Serialization, {// 序列化实现 });
🧩 RTTI 轻量框架运行库实现
- DEMO:
#include "RTTI.h"
#include "Object.h"struct Vector3 : public Object {float x, y, z;Vector3(float x = 0, float y = 0, float z = 0) : x(x), y(y), z(z) {}RTTI_S(Vector3);RTTI_FIELD(x);RTTI_FIELD(y);RTTI_FIELD(z);RTTI_E;
};struct GameObject : public Object {std::string name;Vector3 position;std::shared_ptr<GameObject> child;std::vector<int> scores;std::queue<std::string> messages;GameObject() {scores = { 90, 85, 95 };messages.push("Hello");messages.push("World");}RTTI_S(GameObject);RTTI_FIELD(name);RTTI_FIELD(position);RTTI_FIELD(child);RTTI_FIELD(scores);RTTI_FIELD(messages);RTTI_E;
};static void InitMetadata() {RTTI_I(Vector3);RTTI_I(GameObject);
}std::string GetTypeName(const RTTI::Field* field) {// 优先处理容器元素类型if (field->ListType != RTTI::ListType_kNull && field->Type) {return field->Type->GetName();}// 处理引用类型if (field->ReferenceType != RTTI::ReferenceType_kNull && field->Type) {return field->Type->GetName();}// 基本类型处理switch (field->BaiscType) {case RTTI::BasicType_kInt: return "int";case RTTI::BasicType_kUInt: return "uint";case RTTI::BasicType_kFloat: return "float";case RTTI::BasicType_kString: return "string";case RTTI::BasicType_kClass:return field->Type ? field->Type->GetName() : "unknown_class";default: return "unknown";}
}void PrintFieldInfo(RTTI::Field* field) {std::cout << " " << field->Name << " [";// 打印容器类型if (field->ListType != RTTI::ListType_kNull) {switch (field->ListType) {case RTTI::ListType_kVector: std::cout << "vector<"; break;case RTTI::ListType_kQueue: std::cout << "queue<"; break;case RTTI::ListType_kStatic: std::cout << "array<"; break;default: std::cout << "container<";}std::cout << GetTypeName(field);std::cout << ">";if (field->ListType == RTTI::ListType_kStatic) {std::cout << ", size=" << field->ArraySize;}}// 打印引用类型else if (field->ReferenceType != RTTI::ReferenceType_kNull) {switch (field->ReferenceType) {case RTTI::ReferenceType_kSharedPointer:std::cout << "shared_ptr<"; break;case RTTI::ReferenceType_kUniquePointer:std::cout << "unique_ptr<"; break;default: std::cout << "ref<";}std::cout << GetTypeName(field) << ">";}// 打印基本类型else {std::cout << GetTypeName(field);}std::cout << "]\n";
}int main() {InitMetadata();// 动态创建对象GameObject* obj = (GameObject*)RTTI::New("GameObject");obj->name = "Player1";// 获取类型信息RTTI* type = obj->GetType();std::cout << "Type: " << type->GetName() << "\n";// 遍历所有字段std::cout << "\nFields Info:\n";for (auto& [name, field] : type->GetAllFields()) {PrintFieldInfo(const_cast<RTTI::Field*>(&field));}// 反射访问基本类型RTTI::Field* nameField = type->GetField("name");std::string nameValue = nameField->GetValue<std::string>(obj);std::cout << "\nName: " << nameValue << "\n";// 反射访问嵌套对象RTTI::Field* posField = type->GetField("position");Vector3& pos = posField->GetValue<Vector3>(obj);std::cout << "Position: (" << pos.x << ", " << pos.y << ", " << pos.z << ")\n";// 修改容器字段 - vectorRTTI::Field* scoresField = type->GetField("scores");scoresField->SetValue(obj, 1, 100); // 修改第二个元素// 访问容器字段 - queueRTTI::Field* msgField = type->GetField("messages");std::string* lastMsg = nullptr;if (msgField->GetLastValuePointer(obj, &lastMsg)) {*lastMsg = "Modified!"; // 修改队列尾部std::cout << "Last message: " << *lastMsg << "\n";}// 反射创建智能指针对象RTTI::Field* childField = type->GetField("child");GameObject* childObj = (GameObject*)RTTI::New("GameObject");childObj->name = "Child";childField->SetValue2(obj, std::shared_ptr<GameObject>(childObj));// 获取智能指针字段std::shared_ptr<GameObject>& childRef =childField->GetValue<std::shared_ptr<GameObject>>(obj);std::cout << "Child name: " << childRef->name << "\n";delete obj;return 0;
}
- Object.h:
#pragma once#include <unordered_map>
#include <iostream>#include <list>
#include <vector>
#include <queue>
#include <set>
#include <stack>
#include <array>
#include <mutex>
#include <vector>
#include <functional>
#include <type_traits>#ifndef offset_of
#define offset_of(type, member) ((size_t)&reinterpret_cast<char const volatile&>((((type*)0)->member)))
#endif#ifndef container_of
#define container_of(ptr, type, member) ((type*)((char*)static_cast<const decltype(((type*)0)->member)*>(ptr) - offset_of(type, member)))
#endif#ifndef type_of
#define type_of(type) (type::TypeOf())
#endifclass Object {friend class RTTI;public:virtual RTTI* GetType() noexcept = 0;virtual int GetHashCode() noexcept { return (int)std::hash<uint64_t>()(reinterpret_cast<uint64_t>(this));}
};template <typename T>
constexpr T& constant_of(const T& v) noexcept {return const_cast<T&>(v);
}
- RTTI.h:
#pragma once#include "Object.h"#define RTTI_S(clazz) \public: static std::string GetClassName() noexcept { return #clazz; } \private: class __RTTI__ : public RTTI { \typedef clazz _Ty; \public: \static __RTTI__& c() noexcept { \static __RTTI__ r; \return r; \} \virtual std::string GetName() const noexcept override { return #clazz; } \__RTTI__() noexcept { \__rtti_ptrs[#clazz] = this; \__rtti_news[#clazz] = []() noexcept -> Object* { return new clazz(); }; \
#define RTTI_E \} \}; \public: static RTTI* TypeOf() noexcept { return &__RTTI__::c(); } \public: virtual RTTI* GetType() noexcept override { return &__RTTI__::c(); }#define RTTI_FIELD(var) \__rtti_fields[#var] = __RTTI_IMPL__::__RTTI_IMPL_FIELD_CLASS__::RTTI_GetField_0<std::remove_reference<decltype(((_Ty*)0)->var)>::type>(#var, offset_of(_Ty, var));#define RTTI_I(clazz) type_of(clazz);class Object;class RTTI {
protected:typedef Object* (*NewObjectFx)();static std::unordered_map<std::string, NewObjectFx> __rtti_news;static std::unordered_map<std::string, RTTI*> __rtti_ptrs;public:enum kBasicType {BasicType_kClass,BasicType_kString,BasicType_kChar,BasicType_kSByte,BasicType_kByte,BasicType_kShort,BasicType_kUShort,BasicType_kInt,BasicType_kUInt,BasicType_kLong,BasicType_kULong,BasicType_kBoolean,BasicType_kFloat,BasicType_kDouble,BasicType_kDecimal,};enum kReferenceType {ReferenceType_kNull,ReferenceType_kPointer,ReferenceType_kReference,ReferenceType_kWeakPointer,ReferenceType_kUniquePointer,ReferenceType_kSharedPointer,};enum kListType {ListType_kNull,ListType_kArray,ListType_kList,ListType_kVector,ListType_kStack,ListType_kQueue,ListType_kStatic,ListType_kSet,ListType_kMultiSet,};class Field final {public:const std::string Name;const int Offset = 0;const RTTI* Type = NULL;const bool Constant = false;const kBasicType BaiscType = BasicType_kClass;const kReferenceType ReferenceType = ReferenceType_kNull;const kListType ListType = ListType_kNull;const int SizeOf = 0;const int ArraySize = 0;public:const Field& operator=(const Field& reft) const noexcept {Field& left = const_cast<Field&>(*this);constant_of(left.Name) = reft.Name;constant_of(left.Offset) = reft.Offset;constant_of(left.Type) = reft.Type;constant_of(left.Constant) = reft.Constant;constant_of(left.BaiscType) = reft.BaiscType;constant_of(left.ListType) = reft.ListType;constant_of(left.SizeOf) = reft.SizeOf;constant_of(left.ArraySize) = reft.ArraySize;constant_of(left.ReferenceType) = reft.ReferenceType;return left;}template <typename TValue>TValue& GetValue(Object* obj) noexcept;template <typename TValue>bool GetValue(Object* obj, int index, TValue& out) noexcept;template <typename TValue>bool SetValue(Object* obj, int index, const TValue& value) noexcept;template <typename TValue>bool GetValuePointer(Object* obj, int index, TValue** out) noexcept;template <typename TValue>TValue& SetValue(Object* obj, const TValue& value) noexcept;template <typename TValue>TValue& SetValue2(Object* obj, TValue&& value) noexcept;template <typename TValue>bool GetFirstValuePointer(Object* obj, TValue** out) noexcept;template <typename TValue>bool GetLastValuePointer(Object* obj, TValue** out) noexcept;template <typename TValue>bool GetFirstValue(Object* obj, TValue& out) noexcept;template <typename TValue>bool GetLastValue(Object* obj, TValue& out) noexcept;private:template <typename TList, typename TValue>bool GetFirstValuePointer2(Object* obj, TValue** out) noexcept;template <typename TList, typename TValue>bool GetLastValuePointer2(Object* obj, TValue** out) noexcept;};Field* GetField(const std::string& method) noexcept;const std::unordered_map<std::string, RTTI::Field>& GetAllFields() noexcept { return __rtti_fields; }virtual std::string GetName() const noexcept = 0;static RTTI* GetType(const std::string& class_name) noexcept;Object* New() noexcept;static Object* New(const std::string& class_name) noexcept;protected:std::unordered_map<std::string, RTTI::Field> __rtti_fields;
};namespace __RTTI_IMPL__ {class __RTTI_IMPL_FIELD_CLASS__{template <typename T>struct HAS_MEMBER_TYPE_OF_FUNCTION final {private:template <typename U>static auto SFINAE_TEST(T*) noexcept -> decltype(std::declval<U>().GetType(), std::true_type());template <typename U>static std::false_type SFINAE_TEST(...) noexcept;public:static constexpr bool value = decltype(SFINAE_TEST<T>(NULL))::value;};template <typename T>struct is_shared_ptr : std::false_type {};template <typename T>struct is_shared_ptr<std::shared_ptr<T>> : std::true_type {};template <typename T>struct is_weak_ptr : std::false_type {};template <typename T>struct is_weak_ptr<std::weak_ptr<T>> : std::true_type {};template <typename T>struct is_unique_ptr : std::false_type {};template <typename T>struct is_unique_ptr<std::unique_ptr<T>> : std::true_type {};template <typename T>struct is_vector : std::false_type {};template <typename T>struct is_vector<std::vector<T>> : std::true_type {};template <typename T>struct is_list : std::false_type {};template <typename T>struct is_list<std::list<T>> : std::true_type {};template <typename T>struct is_stack : std::false_type {};template <typename T>struct is_stack<std::stack<T>> : std::true_type {};template <typename T>struct is_queue : std::false_type {};template <typename T>struct is_queue<std::queue<T>> : std::true_type {};template <typename T>struct is_set : std::false_type {};template <typename T>struct is_set<std::set<T>> : std::true_type {};template <typename T>struct is_multiset : std::false_type {};template <typename T>struct is_multiset<std::multiset<T>> : std::true_type {};template <typename T>struct is_array : std::false_type {};template <typename T, std::size_t N>struct is_array<std::array<T, N>> : std::true_type {typedef T type;static constexpr std::size_t length = N;};template <typename T>struct is_static_array : std::false_type {};template <typename T, std::size_t N>struct is_static_array<T[N]> : std::true_type {static constexpr std::size_t length = N;};public:template <typename _Ty>static RTTI* RTTI_GetType() noexcept {if constexpr (std::is_base_of<Object, _Ty>::value && HAS_MEMBER_TYPE_OF_FUNCTION<_Ty>::value) {RTTI* type = RTTI::GetType(_Ty::GetClassName());if (NULL != type) {return type;}return _Ty::TypeOf();}else {return NULL;}}template <typename _Ty>static RTTI::Field RTTI_GetField_0(const std::string& name, int offset) noexcept {using _Ty2 = typename std::remove_const<_Ty>::type;return RTTI_GetField_1<_Ty2>(name, offset, std::is_const<_Ty>::value);}template <typename _Ty>static RTTI::Field RTTI_GetField_1(const std::string& name, int offset, bool constant) noexcept {if constexpr (is_vector<_Ty>::value) {using _Ty2 = typename std::remove_reference<decltype(*((_Ty*)0)->begin())>::type;return RTTI_GetField_2<_Ty2>(name, offset, constant, RTTI::ListType_kVector);}else if constexpr (is_static_array<_Ty>::value) { /* std::is_array<_Ty>::value */using _Ty2 = typename std::remove_reference<decltype(*(*(_Ty*)0))>::type;return RTTI_GetField_2<_Ty2>(name, offset, constant, RTTI::ListType_kStatic, is_static_array<_Ty>::length);}else if constexpr (is_array<_Ty>::value) {using _Ty2 = typename std::remove_reference<typename is_array<_Ty>::type>::type;return RTTI_GetField_2<_Ty2>(name, offset, constant, RTTI::ListType_kArray, is_array<_Ty>::length);}else if constexpr (is_list<_Ty>::value) {using _Ty2 = typename std::remove_reference<decltype(*((_Ty*)0)->begin())>::type;return RTTI_GetField_2<_Ty2>(name, offset, constant, RTTI::ListType_kList);}else if constexpr (is_set<_Ty>::value) {using _Ty2 = typename std::remove_reference<decltype(*((_Ty*)0)->begin())>::type;return RTTI_GetField_2<_Ty2>(name, offset, constant, RTTI::ListType_kSet);}else if constexpr (is_multiset<_Ty>::value) {using _Ty2 = typename std::remove_reference<decltype(*((_Ty*)0)->begin())>::type;return RTTI_GetField_2<_Ty2>(name, offset, constant, RTTI::ListType_kMultiSet);}else if constexpr (is_stack<_Ty>::value) {using _Ty1 = decltype(((_Ty*)0)->top());using _Ty2 = typename std::remove_const<typename std::remove_reference<_Ty1>::type>::type;return RTTI_GetField_2<_Ty2>(name, offset, constant, RTTI::ListType_kStack);}else if constexpr (is_queue<_Ty>::value) {using _Ty1 = decltype(((_Ty*)0)->front());using _Ty2 = typename std::remove_const<typename std::remove_reference<_Ty1>::type>::type;return RTTI_GetField_2<_Ty2>(name, offset, constant, RTTI::ListType_kQueue);}else {return RTTI_GetField_2<_Ty>(name, offset, constant, RTTI::ListType_kNull);}}template <typename _Ty>static RTTI::Field RTTI_GetField_2(const std::string& name, int offset, bool constant, RTTI::kListType list_type, int array_size = 0) noexcept {RTTI::Field field{ name, offset, NULL, constant, RTTI::BasicType_kClass, RTTI::ReferenceType_kNull, list_type, sizeof(_Ty), array_size };RTTI::kBasicType& basic_type = constant_of(field.BaiscType);if constexpr (std::is_same<_Ty, int32_t>::value || std::is_same<_Ty, int>::value || std::is_same<_Ty, long>::value) {basic_type = RTTI::BasicType_kInt;}else if constexpr (std::is_same<_Ty, uint32_t>::value || std::is_same<_Ty, unsigned int>::value || std::is_same<_Ty, unsigned long>::value) {basic_type = RTTI::BasicType_kUInt;}else if constexpr (std::is_same<_Ty, int64_t>::value || std::is_same<_Ty, long long>::value || std::is_same<_Ty, long long int>::value) {basic_type = RTTI::BasicType_kLong;}else if constexpr (std::is_same<_Ty, uint64_t>::value || std::is_same<_Ty, unsigned long long>::value || std::is_same<_Ty, unsigned long long int>::value) {basic_type = RTTI::BasicType_kULong;}else if constexpr (std::is_same<_Ty, double>::value || std::is_same<_Ty, double_t>::value) {basic_type = RTTI::BasicType_kDouble;}else if constexpr (std::is_same<_Ty, long double>::value) {basic_type = RTTI::BasicType_kDecimal;}else if constexpr (std::is_same<_Ty, bool>::value) {basic_type = RTTI::BasicType_kBoolean;}else if constexpr (std::is_same<_Ty, short>::value || std::is_same<_Ty, int16_t>::value) {basic_type = RTTI::BasicType_kSort;}else if constexpr (std::is_same<_Ty, unsigned short>::value || std::is_same<_Ty, uint16_t>::value) {basic_type = RTTI::BasicType_kUSort;}else if constexpr (std::is_same<_Ty, int8_t>::value) {basic_type = RTTI::BasicType_kSByte;}else if constexpr (std::is_same<_Ty, uint8_t>::value) {basic_type = RTTI::BasicType_kByte;}else if constexpr (std::is_same<_Ty, char>::value) {basic_type = RTTI::BasicType_kChar;}else if constexpr (std::is_same<_Ty, std::string>::value) {basic_type = RTTI::BasicType_kString;}else if constexpr (std::is_pointer<_Ty>::value) {using _Ty2 = typename std::remove_pointer<_Ty>::type;constant_of(field.ReferenceType) = RTTI::ReferenceType_kPointer;constant_of(field.Type) = RTTI_GetType<_Ty2>();constant_of(field.SizeOf) = sizeof(_Ty2);}else if constexpr (is_weak_ptr<_Ty>::value) {using _Ty2 = typename std::remove_pointer<typename _Ty::element_type>;constant_of(field.ReferenceType) = RTTI::ReferenceType_kWeakPointer;constant_of(field.Type) = RTTI_GetType<_Ty2>();constant_of(field.SizeOf) = sizeof(_Ty2);}else if constexpr (is_shared_ptr<_Ty>::value) {using _Ty2 = typename std::remove_pointer<decltype(((_Ty*)0)->get())>::type;constant_of(field.ReferenceType) = RTTI::ReferenceType_kSharedPointer;constant_of(field.Type) = RTTI_GetType<_Ty2>();constant_of(field.SizeOf) = sizeof(_Ty2);}else if constexpr (is_unique_ptr<_Ty>::value) {using _Ty2 = typename std::remove_pointer<decltype(((_Ty*)0)->get())>::type;constant_of(field.ReferenceType) = RTTI::ReferenceType_kUniquePointer;constant_of(field.Type) = RTTI_GetType<_Ty2>();constant_of(field.SizeOf) = sizeof(_Ty2);}else if constexpr (std::is_reference<_Ty>::value) {using _Ty2 = typename std::remove_reference<_Ty>::type;constant_of(field.ReferenceType) = RTTI::ReferenceType_kReference;constant_of(field.Type) = RTTI_GetType<_Ty2>();constant_of(field.SizeOf) = sizeof(_Ty2);}else {constant_of(field.Type) = RTTI_GetType<_Ty>();}return field;}};
}template <typename TValue>
TValue& RTTI::Field::GetValue(Object* obj) noexcept {return *(TValue*)((char*)obj + Offset);
}template <typename TValue>
TValue& RTTI::Field::SetValue(Object* obj, const TValue& value) noexcept {TValue& data = *(TValue*)((char*)obj + Offset);data = value;return data;
}template <typename TValue>
TValue& RTTI::Field::SetValue2(Object* obj, TValue&& value) noexcept {TValue& data = *(TValue*)((char*)obj + Offset);data = value;return data;
}template <typename TValue>
bool RTTI::Field::GetValue(Object* obj, int index, TValue& out) noexcept {TValue* ppv{ NULL };if (!GetValuePointer(obj, index, &ppv)) {return false;}out = *ppv;return true;
}template <typename TValue>
bool RTTI::Field::GetValuePointer(Object* obj, int index, TValue** out) noexcept {if (NULL == out || index < 0) {return false;}else if (ListType == ListType_kStatic || ListType == ListType_kArray) {if (index >= ArraySize) {return false;}TValue& data_ref = GetValue<TValue>(obj);TValue* data_ptr = std::addressof(data_ref);*out = data_ptr + index;return true;}else if (ListType == ListType_kVector) {using _Ty2 = std::vector<TValue>;_Ty2& vc = GetValue<_Ty2>(obj);if (index >= (int)vc.size()) {return false;}*out = vc.data() + index;return true;}else {return false;}
}template <typename TValue>
bool RTTI::Field::SetValue(Object* obj, int index, const TValue& value) noexcept {TValue* ppv{ NULL };if (!GetValuePointer(obj, index, &ppv)) {return false;}*ppv = value;return true;
}template <typename TList, typename TValue>
bool RTTI::Field::GetFirstValuePointer2(Object* obj, TValue** out) noexcept {TList& list = GetValue<TList>(obj);auto tail = list.begin();auto endl = list.end();if (tail == endl) {return false;}auto& ref = *tail;*out = (TValue*)std::addressof(ref);return true;
}template <typename TList, typename TValue>
bool RTTI::Field::GetLastValuePointer2(Object* obj, TValue** out) noexcept {TList& list = GetValue<TList>(obj);auto tail = list.rbegin();auto endl = list.rend();if (tail == endl) {return false;}auto& ref = *tail;*out = (TValue*)std::addressof(ref);return true;
}template <typename TValue>
bool RTTI::Field::GetFirstValuePointer(Object* obj, TValue** out) noexcept {if (NULL == out) {return false;}else if (ListType == ListType_kStatic || ListType == ListType_kArray) {if (ArraySize < 1) {return false;}TValue& data_ref = GetValue<TValue>(obj);*out = std::addressof(data_ref);return true;}else if (ListType == ListType_kVector) {using _Ty2 = std::vector<TValue>;_Ty2& vc = GetValue<_Ty2>(obj);if (vc.empty()) {return false;}*out = vc.data();return true;}else if (ListType == ListType_kList) {using _Ty2 = std::list<TValue>;return GetFirstValuePointer2<_Ty2>(obj, out);}else if (ListType == ListType_kSet) {using _Ty2 = std::set<TValue>;return GetFirstValuePointer2<_Ty2>(obj, out);}else if (ListType == ListType_kMultiSet) {using _Ty2 = std::multiset<TValue>;return GetFirstValuePointer2<_Ty2>(obj, out);}else if (ListType == ListType_kStack) {using _Ty2 = std::stack<TValue>;_Ty2& stack = GetValue<_Ty2>(obj);if (stack.empty()) {return false;}*out = std::addressof(stack.top());return true;}else if (ListType == ListType_kQueue) {using _Ty2 = std::queue<TValue>;_Ty2& queue = GetValue<_Ty2>(obj);if (queue.empty()) {return false;}*out = std::addressof(queue.front());return true;}else {return false;}
}template <typename TValue>
bool RTTI::Field::GetLastValuePointer(Object* obj, TValue** out) noexcept {if (NULL == out) {return false;}else if (ListType == ListType_kStatic || ListType == ListType_kArray) {if (ArraySize < 1) {return false;}TValue& data_ref = GetValue<TValue>(obj);*out = std::addressof(data_ref) + (ArraySize - 1);return true;}else if (ListType == ListType_kVector) {using _Ty2 = std::vector<TValue>;_Ty2& vc = GetValue<_Ty2>(obj);if (vc.empty()) {return false;}*out = std::addressof(*vc.rbegin());return true;}else if (ListType == ListType_kList) {using _Ty2 = std::list<TValue>;return GetLastValuePointer2<_Ty2>(obj, out);}else if (ListType == ListType_kSet) {using _Ty2 = std::set<TValue>;return GetLastValuePointer2<_Ty2>(obj, out);}else if (ListType == ListType_kMultiSet) {using _Ty2 = std::multiset<TValue>;return GetLastValuePointer2<_Ty2>(obj, out);}else if (ListType == ListType_kStack) {using _Ty2 = std::stack<TValue>;_Ty2& stack = GetValue<_Ty2>(obj);std::size_t stack_size = stack.size();if (stack_size != 1) {return false;}*out = std::addressof(stack.top());return true;}else if (ListType == ListType_kQueue) {using _Ty2 = std::queue<TValue>;_Ty2& queue = GetValue<_Ty2>(obj);if (queue.empty()) {return false;}*out = std::addressof(queue.back());return true;}else {return false;}
}template <typename TValue>
bool RTTI::Field::GetFirstValue(Object* obj, TValue& out) noexcept {TValue* ppv{ NULL };if (!GetFirstValuePointer(obj, &ppv)) {return false;}out = *ppv;return true;
}template <typename TValue>
bool RTTI::Field::GetLastValue(Object* obj, TValue& out) noexcept {TValue* ppv{ NULL };if (!GetLastValuePointer(obj, &ppv)) {return false;}out = *ppv;return true;
}
- RTTI.cpp:
#include "RTTI.h"std::unordered_map<std::string, RTTI::NewObjectFx> RTTI::__rtti_news;
std::unordered_map<std::string, RTTI*> RTTI::__rtti_ptrs;Object* RTTI::New(const std::string& class_name) noexcept {if (class_name.empty()) {return NULL;}auto tail = __rtti_news.find(class_name);auto endl = __rtti_news.end();if (tail == endl) {return NULL;}NewObjectFx f = tail->second;return f();
}RTTI* RTTI::GetType(const std::string& class_name) noexcept {if (class_name.empty()) {return NULL;}auto tail = __rtti_ptrs.find(class_name);auto endl = __rtti_ptrs.end();if (tail == endl) {return NULL;}return tail->second;
}Object* RTTI::New() noexcept {std::string class_name = GetName();return New(class_name);
}RTTI::Field* RTTI::GetField(const std::string& method) noexcept {if (method.empty()) {return NULL;}auto tail = __rtti_fields.find(method);auto endl = __rtti_fields.end();if (tail == endl) {return NULL;}return &tail->second;
}
本反射系统通过创新的内存访问机制和编译期类型推导,在保持C++性能优势的同时提供了强大的运行时反射能力。