{"id":23428358,"url":"https://github.com/visualgmq/mirrow","last_synced_at":"2025-08-16T23:46:48.171Z","repository":{"id":191813077,"uuid":"685318763","full_name":"VisualGMQ/mirrow","owner":"VisualGMQ","description":"A TMP utility framework in C++17. Contain dynamic\u0026static reflection and serialization","archived":false,"fork":false,"pushed_at":"2025-05-12T06:25:03.000Z","size":350,"stargazers_count":69,"open_issues_count":1,"forks_count":8,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-06-10T17:57:39.355Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/VisualGMQ.png","metadata":{"files":{"readme":"ReadMe.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2023-08-31T01:12:30.000Z","updated_at":"2025-06-10T16:46:08.000Z","dependencies_parsed_at":"2023-08-31T22:15:18.475Z","dependency_job_id":"35c265a7-1d82-4609-841f-9934e71f588d","html_url":"https://github.com/VisualGMQ/mirrow","commit_stats":null,"previous_names":["visualgmq/mirrow"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/VisualGMQ/mirrow","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/VisualGMQ%2Fmirrow","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/VisualGMQ%2Fmirrow/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/VisualGMQ%2Fmirrow/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/VisualGMQ%2Fmirrow/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/VisualGMQ","download_url":"https://codeload.github.com/VisualGMQ/mirrow/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/VisualGMQ%2Fmirrow/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":267355147,"owners_count":24073916,"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","status":"online","status_checked_at":"2025-07-27T02:00:11.917Z","response_time":82,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":[],"created_at":"2024-12-23T07:12:13.785Z","updated_at":"2025-07-27T12:07:53.133Z","avatar_url":"https://github.com/VisualGMQ.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Mirrow - A Template Meta Programming utility framework\n\n`mirrow` is  a TMP(template meta programming) utility framework in C++17. It aimed to make some utility to help programmer do TMP easier. Referenced [meta](https://github.com/skypjack/meta) and [ponder](https://github.com/billyquith/ponder).\n\nNowadays, `mirrow` has these parts:\n\n* `util`: some common utilities\n* `srefl`: static reflection framework\n* `drefl`: dynamic reflection framework\n* `serd`: a serialize framework based on reflection(serial with `drefl`\u0026`srefl`) with TOML\n\n## :book: docs\n\n### util\n\n`util`(utility) has some convenient utility to do TMP:\n\n* `type_list`: compile-time type list. [:microscope: unittest](./test/utility/type_list.cpp)\n* `function_traits`: compile-time function info trait. [:microscope: unittest](./test/utility/function_traits.cpp)\n* `variable_traits`: compile-time variable info trait. [:microscope: unittest](./test/utility/variable_traits.cpp)\n* `const_str`: compile-time string. [:microscope: unittest](./test/utility/const_str.cpp)\n\n### srefl\n\nstatic reflection framework. :microscope: [do reflect unittest](./test/srefl/srefl.cpp), [get reflected info unittest](./test/srefl/reflect.cpp)\n\nTo reflect your class, you must do like this:\n\n```cpp\n// your class\nclass Foo final {\npublic:\n    void foo() {}\n    void foo(int) {}\n    void foo(float) {}\n    void another() {}\n\n    int value_1 = 1;\n    int value_2 = 2;\n};\n\n// include srefl_begin.hpp\n#include \"mirrow/srefl/srefl_begin.hpp\"\n// do your reflection\nsrefl_class(Foo,\n    ctors()\n    fields(\n        field(static_cast\u003cvoid(Foo::*)(void)\u003e(\u0026Foo::foo)),\n        field(static_cast\u003cvoid(Foo::*)(int)\u003e(\u0026Foo::foo)),\n        field(static_cast\u003cvoid(Foo::*)(float)\u003e(\u0026Foo::foo)),\n        field(\u0026Foo::another),\n        field(\u0026Foo::value_1),\n        field(\u0026Foo::value_2)\n    )\n)\n// include srefl_end.hpp\n#include \"mirrow/srefl/srefl_end.hpp\"\n```\n\n[srefl_begin.hpp](./include/mirrow/srefl/srefl_begin.hpp) provide a bunch of macros to help you regist your class. And [srefl_end.hpp](./include/mirrow/srefl/srefl_end.hpp) will `#undef` these macros to avoid pollute your codes.\n\nThen, use `srefl_class(\u003cyour class\u003e, ...)` to start regist your class. use `ctors()` to regist constructors(optional), use `fields(...)` to start regist member/static variable/functions.\n\nAfter reflect, you can use `auto refl = reflect\u003cFoo\u003e();` to get reflected informations. And visit member variables:\n\n```cpp\nrefl.visit_member_variables([\u0026vars](auto\u0026\u0026 value) {\n    vars.push_back(value.name());\n});\n```\n\n*visit function/static fields is WIP, it is easy to implement but currently I don't need them*\n\n### drefl\n\ndynamic reflection framework.\n\n#### any\n\n`any` is similar to `std::any`, but support ownership  :microscope:[unittest](./test/drefl/any.cpp)\n\n`any` has 3 ownership(defined in `any::access_type`):\n\n*   `Null`: don't contain data\n*   `ConstRef`: const reference to a value\n*   `Ref`: mutable reference to a value\n*   `Copy`: the data's ownership is any itself, when any destruct, data will destruct together\n\nuse `any_make_xxx` to create an any from ownership:\n\n```cpp\nint a = 123;\nauto cref = mirrow::drefl::any_make_constref(a);\t// make a const reference\nauto ref = mirrow::drefl::any_make_ref(a);\t// make a reference\nauto new_value = mirrow::drefl::any_make_copy(a); // copy a to any inner data\n```\n\nand use member function `constref()`, `ref()`, `copy()`, `steal()` to translate ownership.\n\n\n\nuse `try_cast()` \u0026 `try_cast_const()` to cast any to a determined type. use `try_cast()` on `ConstRef` any will throw a `bad_any_access` exception and return `nullptr`.\n\n#### factory\n\n`factory` is where you reflect your type:microscope:[unittest](./test/drefl/factory.cpp)\n\nregister your class by:\n\n```cpp\nstruct Person {\n    std::string name;\n    float height;\n    const bool hasChild;\n    const Person* couple;\n};\n\n// in main():\nmirrow::drefl::factory\u003cPerson\u003e::instance()\n              .regist(\"Person\")\n              .property(\"name\", \u0026Person::name)\n              .property(\"height\", \u0026Person::height)\n              .property(\"hasChild\", \u0026Person::hasChild)\n              .property(\"couple\", \u0026Person::couple);\n```\n\nor register your enum by:\n\n```cpp\nenum class MyEnum {\n        Value1 = 1,\n        Value2 = 2,\n        Value3 = 3,\n    };\n\n// in main():\nauto\u0026 inst = mirrow::drefl::factory\u003cMyEnum\u003e::instance()\n    .regist(\"MyEnum\")\n    .add(\"Value1\", MyEnum::Value1)\n    .add(\"Value2\", MyEnum::Value2)\n    .add(\"Value3\", MyEnum::Value3);\t\n```\n\nthen use\n\n```cpp\nauto info = mirrow::drefl::typeinfo\u003cPerson\u003e();\n```\n\nto get registered type information;\n\n**NOTE: currently we don't support register member function.**\n\n\n\nthere are may type information you can access(by member function`as_xxx()`):\n\n*   `enum_info`: enumerates\n*   `numeric`: numerics(`int`,`float`,`char`...)\n*   `boolean`: boolean\n*   `string`:`std::string` or `std::string_view` (may add `const char*` support later)\n*   `pointer`: pointers like `T*`, `T* const`, `T**`...\n*   `array`: `std::vector`, `std::array`, `std::list`, `T[N]`\n*   `class`: other classes\n\n*future support:*\n\n*   `map`: `std::unordered_map`, `std::map`\n*   `set`: `std::unordered_set`, `std::set`\n*   `optional`: `std::optional`\n*   `smart points`: `std::unique_ptr`. `std::shared_ptr`\n*   `pair`: `std::pair`\n\n\n### serd\n\nA serialize/deserialize tools based on dynamic/static reflection.\n\n`serd` provide two serialize/deserialize method: dynamic and static, which need you use dynamic/static reflection to provide type info first.\n\ndynamic reflection based serialize [:microscope:  unittest](./test/serd/drefl_serd.cpp)\nstatic reflection based serialize [:microscope:  unittest](./test/serd/srefl_serd.cpp)\n\nAfter reflected type, you can do serialize like:\n\n```cpp\ntype instance;  // create an instance\n\n// use static reflection based serialize\ntoml::table tbl;\nmirrow::serd::srefl::serialize(instance, tbl);\n// use static reflection based deserialize\nmirrow::serd::srefl::deserialize(tbl, instance);\n\n// convert instance to any to prepare serialize\nmirrow::drefl::reference_any data{instance};\n// use dynamic reflection based serialize\ntoml::table tbl = mirrow::serd::drefl::serialize(data);\n// use dynamic reflection based deserialize\nmirrow::serd::drefl::deserialize(tbl, data);\n```\n\nIf you don't know which toml node would be serialize/deserialize, you can use `mirrow::serd::srefl::serialize_destination_type_t\u003cyour-type\u003e` to get the type.\n\n#### custom serialize function\n\nall `serialize` and `deserialize` function will iterate all member fields in your type info and \\[de\\]serialize them. If field not exists when deserialize, it will log and ignore this field.\n\nThere are some inner-support type:\n\n* numeric(integer like `int`, `char` ..., and floating point(`float`, `double`))\n* `bool`\n* `std::vector`\n* `std::array`\n* `std::optional`\n* `std::unordered_map`\n* `std::unordered_set`\n\nIf you want do specific \\[de\\]serialize method on your own type, here:\n\nfor static \\[de\\]serialize, need two step:\n\n```cpp\nnamespace mirrow::serd::srefl {\n\n// 1. tell serd which toml node you want to serialize to\n// use SFINEA\nnamespace impl {\n\ntemplate \u003c\u003e\nstruct serialize_destination_type\u003cyour_own_type\u003e {\n    // we want [de]serialize to/from toml::value\n    using type = toml::value\u003cyour_own_type\u003e;\n};\n\n}\n\n\n// 2. provide your [de]serialize method\n// also use SFINEA, serialize function\ntemplate \u003ctypename T\u003e\nstd::enable_if_t\u003cstd::is_same_v\u003cyour_own_type, T\u003e\u003e\nserialize(const T\u0026 value, serialize_destination_type_t\u003cT\u003e\u0026 node) {\n    // try put value into node\n    ...\n}\n\n// also use SFINEA, deserialize function\ntemplate \u003ctypename T\u003e\nstd::enable_if_t\u003cstd::is_same_v\u003cT, your_own_type\u003e\u003e\ndeserialize(const toml::node\u0026 node, T\u0026 elem) {\n    // try parse elem from node\n    ...\n}\n\n}\n```\n\nfor dynamic \\[de\\]serialize, you need regist your function into `serialize_method_storage` at runtime:\n\n```cpp\nmirrow::serd::drefl::serialize_method_storage::instance().regist(type_info, serialize_fn, deserialize_fn);\n```\n\nthe second and thrid param is your serialize/deserialize function, must be:\n\n```cpp\n// serialize\nvoid serialize(toml::node\u0026, const any\u0026)\u003e;\n// deserialize\nvoid deserialize(const toml::node\u0026, any\u0026)\u003e;\n```\n\nafter these, you can use serialize/deserialize:\n\n```cpp\nPerson p;\nmirrow::drefl::any any = mirrow::drefl::any_make_ref(p);\n\n// serialize to toml node\nauto tbl = ::mirrow::serd::drefl::serialize(any);\n\n// deserialize from toml node\n::mirrow::serd::drefl::deserialize(p, tbl);\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvisualgmq%2Fmirrow","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvisualgmq%2Fmirrow","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvisualgmq%2Fmirrow/lists"}