参考:
1. A Flexible Reflection System in C++: Part 1 (preshing.com)
2. C++ Reflection | Austin Brunkhorst
2做的更好。反射的代码是自动生成的。
目的
为了学习这个理念,先是从0 感受一个最简单的实现:
假设:
struct Node { std::string key; int value; }
可以实现:
int main() { using namespace std::string_literals; Node node = {"apple",3}; auto *metaStruct = dynamic_cast<RF::MetaType_Struct*>(RF::MetaTypeResolver<Node>::get()); metaStruct->dump(&node); std::cout << "after changed\n"; metaStruct->setMember(&node, "key", "Houdini"s); metaStruct->setMember(&node, "value", 123); metaStruct->dump(&node); return 0; }
运行时输出:
Node{ key=std::string{apple} value=int{3} } after changed Node{ key=std::string{Houdini} value=int{123} }
V0 一个结构体 2个成员:
#include <iostream> #include <vector> #include <any> #include <concepts> namespace RP_Reflection{ struct MetaType{ std::string typeName; // for example int, std::string size_t size; MetaType(std::string valueTypeName, size_t size) : typeName{std::move(valueTypeName)}, size{size} {} virtual ~MetaType() =default; [[nodiscard]] virtual std::string getFullTypeName() const { return typeName;} virtual void dump(const void *data) const= 0; virtual void set(void *data, std::any ) {} }; // meta->string struct MetaType_Int: MetaType{ explicit MetaType_Int() : MetaType{"int", sizeof(int)}{} void dump(const void *ptr) const override{ std::cout <<"int{" << *(static_cast<const int*>(ptr)) << "}";} void set(void *ptr, std::any v ) override{ *static_cast<int*>(ptr) = std::any_cast<int>(v); } }; // meta->int struct MetaType_String: MetaType{ MetaType_String() : MetaType("std::string", sizeof(std::string)){} void dump(const void *ptr) const override{ std::cout <<"std::string" << "{"<< *(static_cast<const std::string*>(ptr))<< "}";} void set(void *ptr, std::any v ) override{ *static_cast<std::string*>(ptr) = std::move(std::any_cast<std::string>(std::move(v))); } }; // meta->struct struct MetaType_Struct: MetaType{ struct MetaMember{ std::string fieldName; size_t offset; MetaType *type; }; std::vector<MetaMember> members; explicit MetaType_Struct(void (*init)(MetaType_Struct *)): MetaType{"",0} { init(this); } void dump(const void *ptr)const override{ std::cout << typeName << "{"<< std::endl; for(const auto &member : members){ std::cout << std::format(" {}=", member.fieldName); member.type->dump(static_cast<const char*>(ptr) + member.offset); std::cout << "\n"; } std::cout << "}\n"; } void setMember(void *ptr,const char *name, std::any data){ for(auto &member : members){ if(member.fieldName != name ) continue; member.type->set( static_cast<char*>(ptr) + member.offset, std::move(data)); } } }; // Declare the function template that handles primitive types such as int, std::string, etc.: template<typename T> MetaType *GetPrimitiveMetaType(); // check class is MetaType template<typename T> concept isMetaType = std::is_base_of_v<MetaType, std::remove_cvref_t<std::remove_pointer_t<T>> >; // check a class that was reflected template<typename T> concept isReflectedClass = requires(T){ { T::reflection } -> isMetaType; }; // TemplateMethod Get MetaType template<typename T> struct MetaTypeResolver{ static MetaType *get(){ if constexpr (isReflectedClass<T>) return &T::reflection; else return GetPrimitiveMetaType<T>(); } }; template<> MetaType *GetPrimitiveMetaType<int>(){ static MetaType_Int metaInt; return &metaInt; } template<> MetaType *GetPrimitiveMetaType<std::string>(){ static MetaType_String metaStr; return &metaStr; } } // end of namespace namespace RF = RP_Reflection; struct Node { std::string key; int value; // REFLECTION CODE HERE static RF::MetaType_Struct reflection; static void initReflection(RF::MetaType_Struct *); }; RF::MetaType_Struct Node::reflection(Node::initReflection); void Node::initReflection(RF::MetaType_Struct *ms) { ms->typeName = "Node"; ms->size = sizeof(Node); ms->members = { {"key", offsetof(Node, key), RF::MetaTypeResolver<decltype(Node::key)>::get()}, {"value", offsetof(Node, value), RF::MetaTypeResolver<decltype(Node::value)>::get()}, }; } int main() { using namespace std::string_literals; Node node = {"apple",3}; auto *metaStruct = dynamic_cast<RF::MetaType_Struct*>(RF::MetaTypeResolver<Node>::get()); metaStruct->dump(&node); std::cout << "after changed\n"; metaStruct->setMember(&node, "key", "Houdini"s); metaStruct->setMember(&node, "value", 123); metaStruct->dump(&node); return 0; }
输出:
Node{ key=std::string{apple} value=int{3} } after changed Node{ key=std::string{Houdini} value=int{123} }
标签:std,Node,Reflection,MetaType,int,void,Runtime,string From: https://www.cnblogs.com/gearslogy/p/18001393