{"id":13533668,"url":"https://github.com/stevinz/reflect","last_synced_at":"2025-05-13T05:30:40.612Z","repository":{"id":115346528,"uuid":"349806283","full_name":"stevinz/reflect","owner":"stevinz","description":"Small, flexible, single-header library for runtime reflection and meta data in C++11.","archived":false,"fork":false,"pushed_at":"2023-02-07T18:13:40.000Z","size":75,"stargazers_count":5,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-01T18:13:15.061Z","etag":null,"topics":["cpp-library","cpp11","meta-data","properties","reflection","reflection-library","single-header-library"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/stevinz.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2021-03-20T18:33:23.000Z","updated_at":"2024-01-16T00:38:17.000Z","dependencies_parsed_at":null,"dependency_job_id":"e3e2fed9-0852-469b-b680-b395cc898afa","html_url":"https://github.com/stevinz/reflect","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stevinz%2Freflect","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stevinz%2Freflect/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stevinz%2Freflect/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stevinz%2Freflect/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/stevinz","download_url":"https://codeload.github.com/stevinz/reflect/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253882663,"owners_count":21978528,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cpp-library","cpp11","meta-data","properties","reflection","reflection-library","single-header-library"],"created_at":"2024-08-01T07:01:22.000Z","updated_at":"2025-05-13T05:30:40.299Z","avatar_url":"https://github.com/stevinz.png","language":"C++","funding_links":[],"categories":["Libraries"],"sub_categories":["C++"],"readme":"# Reflect\n\nSmall, flexible, single-header library for aggregate (struct / class) runtime reflection and meta data using C++11 features. Minimal STL usage, no other dependencies.\n\n\u003cbr /\u003e\n\n## Installation\n- Copy 'reflect.h' to project\n\n- In ONE cpp file, define REGISTER_REFLECTION:\n```cpp\n#define REGISTER_REFLECTION\n#include \"reflect.h\"\n#include \"my_struct_1.h\"\n#include \"my_struct_2.h\"\n#include etc...\n```\n\n- Classes / Structs should be simple aggregate types (standard layout)\n    - No private or protected non-static data members\n    - No user-declared / user-provided constructors\n    - No virtual member functions\n    - No default member initializers (invalid in C++11, okay in C++14 and higher)\n    - See (https://en.cppreference.com/w/cpp/types/is_standard_layout) for more info\n\n- BEFORE using reflection functions, make one call to\n```cpp\nInitializeReflection();\n```\n\n\u003cbr /\u003e\n\n## Usage\n### Registration in Header File, example: \"transform.h\"\n```cpp\n#ifndef TRANSFORM2D_H\n#define TRANSFORM2D_H\n\n#include \"reflect.h\"\nstruct Transform2D {\n    int width;\n    int height;\n    std::vector\u003cdouble\u003e position;\n    std::string text;\n    REFLECT();\n}\n#ifdef REGISTER_REFLECTION\n    REFLECT_CLASS(Transform2D)\n    REFLECT_MEMBER(width)\n    REFLECT_MEMBER(height)\n    REFLECT_MEMBER(position)\n    REFLECT_MEMBER(text)\n    REFLECT_END(Transform2D)\n#endif\n\n#endif // TRANSFORM2D_H\n```\n\n\u003cbr /\u003e\n\n## In Code\n### Initialize class instance\n```cpp\nTransform2D t { };\nt.width = 100;\nt.height = 100;\nt.position = std::vector\u003cdouble\u003e({1.0, 2.0, 3.0});\nt.text = \"Hello world!\";\n```\n\n### TypeData Object\n```cpp\n// Class TypeData\nTypeData data = ClassData\u003cTransform2D\u003e();           // By class type\nTypeData data = ClassData(t);                       // By class instance\nTypeData data = ClassData(type_hash);               // By class type hash\nTypeData data = ClassData(\"Transform2D\");           // By class name\n\n// Member TypeData\nTypeData data = MemberData\u003cTransform2D\u003e(0);         // By class type, member index\nTypeData data = MemberData\u003cTransform2D\u003e(\"width\");   // By class type, member name\nTypeData data = MemberData(t, 0);                   // By class instance, member index\nTypeData data = MemberData(t, \"width\");             // By class instance, member name\nTypeData data = MemberData(type_hash, 0);           // By class type hash, member index\nTypeData data = MemberData(type_hash, \"width\");     // By class type hash, member name\n```\n\n### Get / Set Member Variables\n- Use the ClassMember\u003cmember_type\u003e(class_instance, member_data) function to return a reference to a member variable. This function requires the return type, a class instance (can be void* or class type), and a member variable TypeData object. Before calling ClassMember\u003c\u003e(), member variable type can be checked by comparing to types using helper function TypeHashID\u003ctype_to_check\u003e()\n```cpp\n// Member Variable by Index\nTypeData member = MemberData(t, 0);\nif (member.type_hash == TypeHashID\u003cint\u003e()) {\n    // Create reference to member\n    int\u0026 width = ClassMember\u003cint\u003e(\u0026t, member);\n    // Can now set member variable directly\n    width = 120;\n}\n\n// Member Variable by Name\nTypeData member = MemberData(t, \"position\");\nif (member.type_hash == TypeHashID\u003cstd::vector\u003cdouble\u003e\u003e()) {\n    // Create reference to member\n    std::vector\u003cdouble\u003e\u0026 position = ClassMember\u003cstd::vector\u003cdouble\u003e\u003e(\u0026t, member);\n    // Can now set member variable directly\n    position = { 2.0, 4.0, 6.0 };\n}\n```\n\n\u003cbr /\u003e\n\n## Iterating Members / Properties\n```cpp\nint member_count = ClassData(t).member_count;\nfor (int index = 0; index \u003c member_count; ++index) {\n    TypeData member = MemberData(t, index);\n    std::cout \u003c\u003c \" Index: \" \u003c\u003c member.index \u003c\u003c \", \";\n    std::cout \u003c\u003c \" Name: \"  \u003c\u003c member.name  \u003c\u003c \", \";\n    std::cout \u003c\u003c \" Title: \" \u003c\u003c member.title \u003c\u003c \", \";\n    std::cout \u003c\u003c \" Value: \";\n    if (member.type_hash == TypeHashID\u003cint\u003e()) {\n        std::cout \u003c\u003c ClassMember\u003cint\u003e(\u0026t, member);\n    } else if (member.type_hash == TypeHashID\u003cstd::string\u003e()) {\n        std::cout \u003c\u003c ClassMember\u003cstd::string\u003e(\u0026t, member);\n    } else if (member.type_hash == TypeHashID\u003cstd::vector\u003cdouble\u003e\u003e()) {\n        std::vector\u003cdouble\u003e\u0026 vec = ClassMember\u003cstd::vector\u003cdouble\u003e\u003e(\u0026t, member);\n        for (auto\u0026 number : vec) {\n            std::cout \u003c\u003c number \u003c\u003c \", \";\n        }\n    }\n}\n```\n\n\u003cbr /\u003e\n\n## Data from Unknown Class Type\n- If using with an entity component system, it's possible you may not have access to class type at runtime. Often a collection of components are stored in a container of void pointers. Somewhere in your code when your class is initialized, store the component class TypeHash:\n```cpp\nTypeHash saved_hash = ClassData(t).type_hash;\nvoid* class_pointer = (void*)(\u0026t);\n```\n- Later (if your components are stored as void pointers in an array / vector / etc. with other components) you may still access the member variables of the component without casting the component back to the original type. This is done by using the saved_hash from earlier:\n```cpp\nusing vec = std::vector\u003cdouble\u003e;\nTypeData member = MemberData(saved_hash, 3);\nif (member.type_hash == TypeHashID\u003cvec\u003e()) {\n    vec\u0026 rotation = ClassMember\u003cvec\u003e(class_pointer, member);\n    std::cout \u003c\u003c \"  Rotation X: \" \u003c\u003c rotation[0];\n    std::cout \u003c\u003c \", Rotation Y: \" \u003c\u003c rotation[1];\n    std::cout \u003c\u003c \", Rotation Z: \" \u003c\u003c rotation[2];\n}\n```\n\n\u003cbr /\u003e\n\n## User Meta Data\n### Registration in Header File, example: \"transform.h\"\n- Meta data can by stored as std::string within a class or member type. Set user meta data at compile time using CLASS_META_DATA and MEMBER_META_DATA in the class header file with (int, string) or (sting, string) pairs:\n```cpp\n#ifdef REGISTER_REFLECTION\n    REFLECT_CLASS(Transform2D)\n        CLASS_META_DATA(META_DATA_DESCRIPTION, \"Describes object in 2D space.\")\n        CLASS_META_DATA(\"icon\", \"assets/transform.png\")\n    REFLECT_MEMBER(width)\n        MEMBER_META_DATA(META_DATA_DESCRIPTION, \"Width of this object.\")\n    REFLECT_MEMBER(height)\n        MEMBER_META_DATA(META_DATA_DESCRIPTION, \"Height of this object.\")\n    REFLECT_MEMBER(position)\n        MEMBER_META_DATA(META_DATA_HIDDEN, \"true\")\n        MEMBER_META_DATA(\"tooltip\", \"Pos\")\n    REFLECT_END(Transform2D)\n#endif\n```\n\n### Get / Set Meta Data\n- BY REFERENCE, pass a TypeData object (class or member, this can be retrieved many different ways as shown earlier) to the meta data functions to get / set meta data at runtime:\n```cpp\n// TypeData from class\nTypeData\u0026 type_data = ClassData\u003cTransform2D\u003e();\n// or from member variable\nTypeData\u0026 type_data = MemberData\u003cTransform2D\u003e(\"width\");\n\n// Get meta data\nstd::string description = GetMetaData(type_data, META_DATA_DESCRIPTION);\nstd::string icon_file   = GetMetaData(type_data, \"icon\");\n\n// Set meta data\nSetMetaData(type_data, META_DATA_DESCRIPTION, description);\nSetMetaData(type_data, \"icon\", icon_file);\n```\n\n\u003cbr /\u003e\n\n## Portability\n\nTested and compiled with:\n- GCC 4.2.1\n- Emscripten 1.38.43\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstevinz%2Freflect","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fstevinz%2Freflect","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstevinz%2Freflect/lists"}