{"id":13730499,"url":"https://github.com/eliasdaler/MetaStuff","last_synced_at":"2025-05-08T03:30:45.939Z","repository":{"id":67235878,"uuid":"572483303","full_name":"eliasdaler/MetaStuff","owner":"eliasdaler","description":"Archive of MetaStuff lib","archived":true,"fork":false,"pushed_at":"2022-11-30T11:24:47.000Z","size":95,"stargazers_count":9,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-05-02T02:52:26.320Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"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/eliasdaler.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,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-11-30T11:24:30.000Z","updated_at":"2025-01-06T23:17:06.000Z","dependencies_parsed_at":"2023-06-02T06:45:24.983Z","dependency_job_id":null,"html_url":"https://github.com/eliasdaler/MetaStuff","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/eliasdaler%2FMetaStuff","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eliasdaler%2FMetaStuff/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eliasdaler%2FMetaStuff/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eliasdaler%2FMetaStuff/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/eliasdaler","download_url":"https://codeload.github.com/eliasdaler/MetaStuff/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252992850,"owners_count":21837181,"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":[],"created_at":"2024-08-03T02:01:15.720Z","updated_at":"2025-05-08T03:30:45.916Z","avatar_url":"https://github.com/eliasdaler.png","language":"C++","readme":"Meta stuff WIP\n=======\n\nThis is the code I used in my game for all serialization/deserialization/introspection stuff.\n\nThis is the archive of the old repo which I accidentally deleted (oops).\nIt wasn't updated for 5 years and was abandonware at this point. It also had 400 stars on it, but whatever.\n\nFeel free to fork.\n\n[This article](https://eliasdaler.github.io/meta-stuff/) explains how it can be used and how it was made in detail.\n\nSee [metastuff-clang-generator](https://github.com/w0land/metastuff-clang-generator) for automatic registration of classes in MetaStuff!\n\nFeatures\n----\n\n- **Strongly typed and doesn't use RTTI or virtual functions in any way**. You can iterate over class members and you still know member's type, there's no type erasure and it's all very fast\n- **No dependencies**. You have to use modern C++ compiler which supports C++14, though. (VS 2015, GCC 5+, Clang 3.8)\n- **Serialization is not limited to any format**. There's no standard way of doing serialization. You can implement it yourself for your own format. (See JSON example to see how it can be done)\n- **You don't need to modify classes that you want to serialize/deserialize**. Everything is done through providing template specializations of MetaStuff's `registerMembers\u003cT\u003e` function for your classes. No modifications to classes you want to serialize are needed!\n\nThe lib is still in development, so it's not recommended to use it for anything really serious as lots of stuff can change!\nStill, use it as you like, it's MIT licensed after all.\n\nAll suggestions about improving the lib are welcome. I know it isn't perfect, so let's make it better together. :)\n\nRequirements\n----\n- Compiler with C++14 support (I managed to compile it with Visual Studio 2015, GCC 5.0, Clang 3.8)\n\nDependencies\n-----\n- Just standard library. ([JSON for Modern C++](https://github.com/nlohmann/json) is used in example, but you can use any library you want for serialization)\n\nExample\n----\n\nSee example for complete example of JSON serialization.\n\nSuppose you have classes like this:\n```c++\nstruct Person {\n    void setAge(int a)\n    {\n        if (a \u003e= 0 \u0026\u0026 a \u003c 128) { // sorry, if you're older than 128\n            age = a;\n        } else {\n            std::cout \u003c\u003c \"Can't set age. \" \u003c\u003c a \u003c\u003c \" is out of allowed range\\n\";\n        }\n    }\n\n    int getAge() const { return age; }\n\n    void setName(const std::string\u0026 name) { this-\u003ename = name; }\n\n    const std::string\u0026 getName() const { return name; }\n\n    int age;\n    std::string name;\n    float salary;\n    std::unordered_map\u003cstd::string, std::vector\u003cMovieInfo\u003e\u003e favouriteMovies;\n};\n\nstruct MovieInfo {\n    std::string name;\n    float rating;\n};\n```\nAnd you want to serialize them to some format (for example, JSON). Or perhaps you want to add some GUI which will let you edit each member easily.\nNo problem, just write these static functions,\n\n```c++\n#include \"Meta.h\"\n\nnamespace meta\n{\n\ntemplate \u003c\u003e\ninline auto registerMembers\u003cPerson\u003e()\n{\n    return members(\n        member(\"age\", \u0026Person::getAge, \u0026Person::setAge), // access through getter/setter only!\n        member(\"name\", \u0026Person::getName, \u0026Person::setName), // same, but ref getter/setter\n        member(\"salary\", \u0026Person::salary),\n        member(\"favouriteMovies\", \u0026Person::favouriteMovies)\n    );\n}\n\ntemplate \u003c\u003e\ninline auto registerMembers\u003cMovieInfo\u003e()\n{\n    return members(\n        member(\"name\", \u0026MovieInfo::name),\n        member(\"rating\", \u0026MovieInfo::rating)\n    );\n}\n\n}\n```\nNote that you can either use pointers to members or pointers to getters/setters. They will be used for doing stuff with members of registered classes. (for reading and setting values).\n\nand now you can call do this:\n```c++\nmeta::doForAllMembers\u003cSomeClass\u003e(/* your lambda */);\n```\n\nYour lambda should have one parameter which will be an instance of Member. Calling ```meta::doForAllMembers\u003cT\u003e``` gives you ability to do something with each registered member of class T.\nInside your lambda you can get member type like this (`MemberType` = `T` when `decltype(member)` = `Member\u003cClass, T\u003e`):\n```using MemberType = meta::get_member_type\u003cdecltype(member)\u003e;```\n(See **example/JsonCast.inl** for examples of such lambdas).\n\nSome docs (will be better in future!)\n---\n\nMember class has the following functions:\n\n* `const char* getName()` - returns `const char*` of member name you've set during \"registration\"\n* `const T\u0026 get(const Class\u0026 obj)` - gets const reference to the member\n* `T getCopy(const Class\u0026 obj)` - gets copy of member (useful to if only value getter is provided, can't return const T\u0026 in that case)\n* `void set(const Class\u0026 obj, V\u0026\u0026 value)` - sets value to the member, lvalues and rvalues are accepted\n* `T\u0026 getRef(const Class\u0026 obj)` - gets non const reference to the member\n\nIn general `Meta::getMembers\u003cT\u003e()` template function specialization should have a following form and should be put in header with you class (see comments in Meta.h for more info)\n\n**It's important for this function to be `inline` and be defined in header file because the compiler has to figure out return type and you don't want to define the same function in two different compilation units!**\n\n```c++\nnamespace meta\n{\n\ntemplate \u003c\u003e\ninline auto registerMembers\u003cSomeClass\u003e()\n{\n    return members(\n        member(...),\n        ...\n    );\n}\n\n}\n```\n\nYou can register members by using their data member pointer:\n```c++\nmember(\"someMember\", \u0026SomeClass::someMember)\n```\n\nOr use getters/setters:\n\n```c++\nmember(\"someMember\", \u0026SomeClass::getSomeMember, \u0026SomeClass::setSomeMember)\n```\n\nIf you provide Member with getters and setters it will use these functions for getting/setting members, otherwise the member will be accessed directly with pointer to member.\n\nAnd you can add non-const getter (not necessary):\n\n```c++\nmember(...).addNonConstGetter(\u0026SomeClass::getSomeMemberRef)\n```\n\nGetters and setters can be by-value:\n\n```c++\n// T is member type\nT SomeClass::getSomeMember() const { return someMember; }\nvoid SomeClass::getSomeMember(T value) { someMember = value; }\n```\n\n... or by reference\n```c++\n// T is member type\nconst T\u0026 SomeClass::getSomeMember() const { return someMember; }\nvoid SomeClass::getSomeMember(const T\u0026 value) { someMember = value; }\n```\n\nNon-const getter has the following form:\n```c++\n// T is member type\nT\u0026 SomeClass::getSomeMemberRef() { return someMember; }\n```\n\nGetters and setters are always called (if they're present) in `Member::get/set` functions, otherwise the pointer to member is used. The same applies to non-const getter in Member::getRef.\n\nYou can make the template specialization of `registerMembers` a friend to your registered class to be able to access and add private members. You can do it like this:\n\n```c++\nclass SomeClass {\n    friend auto meta::registerMembers\u003cSomeClass\u003e(); // Visual Studio may produce warning here\n        // Just ignore it, it's a bug (`#pragma warning (disable : 4396)` is added in Meta.h\n};\n```\n\nInheritance\n---\n\nIf you have a base class registered, you can combine its members tuple with a one from derived class. See [this example](https://gist.github.com/eliasdaler/45bf3f583cd4a41019b9802c198e6f41) of how you can do it.\n\nLicense\n---\n\nThis library is licensed under the MIT License, see LICENSE for more information.\n","funding_links":[],"categories":["C++"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feliasdaler%2FMetaStuff","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Feliasdaler%2FMetaStuff","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feliasdaler%2FMetaStuff/lists"}