{"id":13420124,"url":"https://github.com/Cylix/Reflex","last_synced_at":"2025-03-15T06:31:55.812Z","repository":{"id":33693158,"uuid":"37346072","full_name":"Cylix/Reflex","owner":"Cylix","description":"C++14 Reflection Library","archived":false,"fork":false,"pushed_at":"2017-09-07T00:49:24.000Z","size":64,"stargazers_count":134,"open_issues_count":0,"forks_count":17,"subscribers_count":10,"default_branch":"master","last_synced_at":"2024-07-31T22:53:23.961Z","etag":null,"topics":["cpp","cpp14","reflection"],"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/Cylix.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}},"created_at":"2015-06-12T21:45:38.000Z","updated_at":"2024-06-11T01:26:56.000Z","dependencies_parsed_at":"2022-07-19T22:48:19.996Z","dependency_job_id":null,"html_url":"https://github.com/Cylix/Reflex","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Cylix%2FReflex","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Cylix%2FReflex/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Cylix%2FReflex/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Cylix%2FReflex/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Cylix","download_url":"https://codeload.github.com/Cylix/Reflex/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":221548295,"owners_count":16840986,"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","cpp14","reflection"],"created_at":"2024-07-30T22:01:26.909Z","updated_at":"2024-10-26T15:31:42.007Z","avatar_url":"https://github.com/Cylix.png","language":"C++","readme":"# Reflex\nC++14 Reflection Library.\n\n## Requirements\n* C++14\n* Boost.PP includes\n\n## Compiling\nThe library is `headers only`, so there is nothing to build and to link with your program.\n\nInstead, you just have to include `\u003creflex/reflex\u003e` in your source files and everything will work as expected.\n\nHowever, you may need to install the library includes somewhere in your computer: for this, we use `cmake`. Just follow these steps:\n\n```bash\ngit clone https://github.com/Cylix/reflex.git\ncd reflex\nmkdir build\ncd build\ncmake -DCMAKE_INSTALL_PREFIX=/destination/path ..\nmake install\n```\n\n## Examples and Tests\nIf you want to build the examples or the tests, follow these steps:\n\n```bash\ngit clone https://github.com/Cylix/reflex.git\ncd reflex\n./install_deps.sh # necessary only for building tests\nmkdir build\ncd build\ncmake .. -DBUILD_TESTING=true # tests\ncmake .. -DBUILD_EXAMPLES=true # examples\ncmake .. -DBUILD_TESTING=true -DBUILD_EXAMPLES=true # tests and examples\nmake -j\n```\n\n## Register class\nIn order to enable reflection, we must explicitly \"register\" our class.\n\nFor this, `reflex` provides a simple macro: `REGISTER_CLASS_FUNCTIONS(type, list of functions)`.\n* `Type` is the type on which we want to enable reflection\n* `List of functions` is the list of member functions (non-static and static member functions) we want to be able to call during reflection. These functions can have any signature (there is no restriction concerning the return value type, the number of parameters and the types of these parameters).\n\nThe list of functions must be formatted in a specific way: `(fct1)(fct2)(fct3)...`.\nThis format is the format used by Boost.PP (which is used in this library) and must be respected in order to compile.\n\nFor example, if we have the following class:\n\n```cpp\nclass SomeClass {\npublic:\n    int fct(void) {\n        std::cout \u003c\u003c \"fct()\" \u003c\u003c std::endl;\n    }\n\n    static void other_fct(const std::string\u0026, float) {\n        std::cout \u003c\u003c \"other_fct()\" \u003c\u003c std::endl;\n    }\n};\n```\n\nWe just need to do `REGISTER_CLASS_FUNCTIONS(SomeClass, (fct)(other_fct))` and this will register `SomeClass` and its two member functions for reflection.\n\nFor namespaced classes, `REGISTER_CLASS_FUNCTIONS` can take an extra parameter: `REGISTER_CLASS_FUNCTIONS((some_namespace)(nested_namespace), SomeClass, (fct)(other_fct))`.\nNamespaces use the Boost.PP syntax with parentheses.\nThe macro must be called outside any namespaces in order to avoid conflicts.\n\n## Register C-Style functions\nReflection is not only limited to class member functions. It can be also used on C-style functions.\n\nFor this, `reflex` provides a simple macro: `REGISTER_FUNCTIONS(list of functions)`.\n* `List of functions` is the list of functions we want to be able to call during reflection. These functions can have any signature (there is no restriction concerning the return value type, the number of parameters and the types of these parameters).\n\nThe list of functions must be formatted in a specific way: `(fct1)(fct2)(fct3)...`.\nThis format is the format used by Boost.PP (which is used in this library) and must be respected in order to compile.\n\nFor example, if we have the following class:\n\n```cpp\nint fct(void) {\n    std::cout \u003c\u003c \"fct()\" \u003c\u003c std::endl;\n}\n\nvoid other_fct(const std::string\u0026, float) {\n    std::cout \u003c\u003c \"other_fct()\" \u003c\u003c std::endl;\n}\n};\n```\n\nWe just need to do `REGISTER_FUNCTIONS((fct)(other_fct))` and this will register the two functions for reflection.\n\nFor namespaced functions, `REGISTER_FUNCTIONS` can take an extra parameter: `REGISTER_FUNCTIONS((some_namespace)(nested_namespace), (fct)(other_fct))`.\nNamespaces use the Boost.PP syntax with parentheses.\nThe macro must be called outside any namespaces in order to avoid conflicts.\n\n## Making Reflection\nEach time we register a type and its member functions, it stores this type into the `reflection_manager` singleton class.\n\nThis class is the class which does the reflection. By calling `reflection_manager::invoke\u003cRetVal, Params...\u003e(\"class_name\", \"function_name\", ...)`, this will call `class_name::function_name` (on a new object).\n\nA facility function with a more elegant syntax is also provided: `reflection_maker\u003cRetVal(Params...)\u003e::invoke(\"class_name\", \"function_name\", ...)`. It provides the std::function template syntax which is more readable.\n\nIf we take the previous example, by calling `reflex::reflection_maker\u003cvoid(const std::string\u0026, float)\u003e::invoke(\"SomeClass\", \"other_fct\", some_str, some_float);`, we will invoke `SomeClass::fct`.\n\n`reflection_maker::invoke` is overloaded for C-Style functions: `reflection_maker\u003cRetVal(Params...)\u003e::invoke(\"function_name\", ...)`.\n\n## Making Reflection with instance\nBy default, reflection for member function is done on a new object.\n\nIt is however possible to make reflection on a custom object instance.\n\n`reflex::reflection_maker\u003cvoid(const std::string\u0026, float)\u003e::invoke(\u0026some_obj, \"SomeClass\", \"other_fct\", some_str, some_float);` will invoke `SomeClass::other_fct` on some_obj instance.\n\nThis feature is available for pointer, std::shared_ptr and std::unique_ptr of the object.\n\n# How does it work\n`REGISTER_CLASS_FUNCTIONS` and `REGISTER_FUNCTIONS` macros are based on the `REGISTER_REFLECTABLE` macro\nThe `REGISTER_REFLECTABLE` macro uses variadic macro parameters and works with Boost.PP in order to iterate through the list of functions.\n\nThis macro will create a static object of type `reflectable\u003cSomeClass\u003e`.\nFor example `REGISTER_CLASS_FUNCTIONS(SomeClass, (fct)(other_fct))` will generates the following code:\n\n```cpp\nstatic reflectable\u003cSomeClass\u003e reflectable_SomeClass(\n    \"SomeClass\",\n    { \"fct\", \u0026SomeClass::fct },\n    { \"other_fct\", \u0026SomeClass::other_fct }\n);\n```\n\nAnother example: `REGISTER_FUNCTIONS((fct)(other_fct))` will generates the following code:\n\n```cpp\nstatic reflectable\u003creflex::Void\u003e reflectable_(\n    \"\",\n    { \"fct\", \u0026fct },\n    { \"other_fct\", \u0026other_fct }\n);\n```\n\n\nThis generation is done at compile time but the registration is only effective at runtime at the beginning of the execution. Registering a class for reflection will impact on the compilation time and at program startup (when all static variables are initialized).\n\nThe constructor of a reflectable object registers itself into the reflectable_manager that we can use for reflection.\n\nIf you want to read more about the implementation of this library, you may be interested in an article I've written about it: [Reflection in C++14](http://blog.simon-ninon.fr/reflection-in-c-plus-plus-14/).\n\n## Examples\nSome examples are provided in this repositories:\n* [reflection_non_member_function.cpp](examples/reflection_non_member_function.cpp) shows reflection for c-style functions and static member functions.\n* [reflection_with_instance.cpp](examples/reflection_with_instance.cpp) provides an example of basic reflection on member functions.\n* [reflection_without_instance.cpp](examples/reflection_without_instance.cpp) details how to make reflection on member functions with an existing object instance.\n\n## To Do\n| Type | Description | Priority | Status |\n|------|-------------|----------|--------|\n| Improvement | Improve test coverage | High | To Do |\n| Improvement | Add full documentation | Moderate | To Do |\n| Improvement | Clear syntax for templates (\u003cReturnType, Params...\u003e -\u003e \u003cReturnType(Params)\u003e whenever it is possible) | Low | To Do |\n| Improvement | Handling case of multiple REGISTER_FUNCTIONS (or multiple REGISTER_CLASS_FUNCTIONS for same type) in a single project | Moderate | To Do |\n| Feature | Reflection for variables | Low | To Do |\n| Feature | Reflection for overloads | Medium | To Do |\n\n## Author\n[Simon Ninon](http://simon-ninon.fr)\n","funding_links":[],"categories":["TODO scan for Android support in followings","C++"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FCylix%2FReflex","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FCylix%2FReflex","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FCylix%2FReflex/lists"}