{"id":15674980,"url":"https://github.com/thelartians/revisited","last_synced_at":"2025-05-06T23:32:36.782Z","repository":{"id":88218307,"uuid":"138604516","full_name":"TheLartians/Revisited","owner":"TheLartians","description":"🧑‍🤝‍🧑 The visitor pattern revisited. An inheritance-aware acyclic visitor template, any and any-function templates.","archived":false,"fork":false,"pushed_at":"2020-05-26T19:00:38.000Z","size":190,"stargazers_count":15,"open_issues_count":0,"forks_count":2,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-03-31T04:04:14.005Z","etag":null,"topics":["acyclic","any","anyfunction","compile-time","cplusplus","cpp","fast","function","inheritance","multimethods","multiple-dispatch","template","visitor","visitor-pattern"],"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/TheLartians.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}},"created_at":"2018-06-25T14:15:30.000Z","updated_at":"2024-06-26T19:42:42.000Z","dependencies_parsed_at":null,"dependency_job_id":"46015241-8761-487e-a12f-e8b27888bd23","html_url":"https://github.com/TheLartians/Revisited","commit_stats":null,"previous_names":[],"tags_count":27,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TheLartians%2FRevisited","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TheLartians%2FRevisited/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TheLartians%2FRevisited/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TheLartians%2FRevisited/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/TheLartians","download_url":"https://codeload.github.com/TheLartians/Revisited/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252787531,"owners_count":21804278,"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":["acyclic","any","anyfunction","compile-time","cplusplus","cpp","fast","function","inheritance","multimethods","multiple-dispatch","template","visitor","visitor-pattern"],"created_at":"2024-10-03T15:54:07.135Z","updated_at":"2025-05-06T23:32:36.738Z","avatar_url":"https://github.com/TheLartians.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Actions Status](https://github.com/TheLartians/Revisited/workflows/MacOS/badge.svg)](https://github.com/TheLartians/Revisited/actions)\n[![Actions Status](https://github.com/TheLartians/Revisited/workflows/Windows/badge.svg)](https://github.com/TheLartians/Revisited/actions)\n[![Actions Status](https://github.com/TheLartians/Revisited/workflows/Ubuntu/badge.svg)](https://github.com/TheLartians/Revisited/actions)\n[![Actions Status](https://github.com/TheLartians/Revisited/workflows/Style/badge.svg)](https://github.com/TheLartians/Revisited/actions)\n[![Actions Status](https://github.com/TheLartians/Revisited/workflows/Install/badge.svg)](https://github.com/TheLartians/Revisited/actions)\n[![codecov](https://codecov.io/gh/TheLartians/Revisited/branch/master/graph/badge.svg)](https://codecov.io/gh/TheLartians/Revisited)\n\n# Revisited\n\nA C++17 acyclic visitor template and inheritance-aware any and any-function class. Using revisited::Visitor greatly reduces the boilerplate code required for implementing the [visitor pattern](https://en.wikipedia.org/wiki/Visitor_pattern) in C++. It uses only [compile time type information](https://github.com/TheLartians/StaticTypeInfo) and has better performance than solutions relying on run time type information such as `dynamic_cast`.\n\n## Examples\n\nSee the [examples directory](https://github.com/TheLartians/Visitor/tree/master/examples) for full examples.\n\n### Revisited Examples\n\n#### Simple Visitor\n\n```cpp\n#include \u003cmemory\u003e\n#include \u003ciostream\u003e\n#include \u003crevisited/visitor.h\u003e\n\nstruct Base: public virtual revisited::VisitableBase { };\nstruct A: public Base, public revisited::Visitable\u003cA\u003e { };\nstruct B: public Base, public revisited::Visitable\u003cB\u003e { };\n\nstruct Visitor: public revisited::Visitor\u003cA \u0026,B \u0026\u003e {\n  void visit(A \u0026){ std::cout \u003c\u003c \"Visiting A\" \u003c\u003c std::endl; }\n  void visit(B \u0026){ std::cout \u003c\u003c \"Visiting B\" \u003c\u003c std::endl; }\n};\n\nint main() {\n  std::shared_ptr\u003cBase\u003e a = std::make_shared\u003cA\u003e();\n  std::shared_ptr\u003cBase\u003e b = std::make_shared\u003cB\u003e();\n  \n  Visitor visitor;\n  a-\u003eaccept(visitor); // -\u003e Visiting A\n  b-\u003eaccept(visitor); // -\u003e Visiting B\n}\n```\n\n#### Derived Classes\n\nrevisited::Visitor also understands derived classes and classes with multiple visitable base classes. Virtual visitable base classes are also supported. When visiting a derived object, the first class matching the visitor is used (starting from parent classes). Multiple and virtual inheritance is fully supported.\n\n```cpp\n// C is inherited from A (both can be visited)\nstruct C: public revisited::DerivedVisitable\u003cC, A\u003e { };\n// D is inherited from A and B (A and B can be visited)\nstruct D: public revisited::JoinVisitable\u003cA, B\u003e { };\n// E is virtually inherited from  A and B (E, A and B can be visited)\nstruct E: public revisited::DerivedVisitable\u003cE, revisited::VirtualVisitable\u003cA, B\u003e\u003e { };\n```\n\n### revisited::Any Examples\n\n#### Implicit casting\n\n```cpp\nrevisited::Any v;\nv = 42;\nstd::cout \u003c\u003c v.get\u003cint\u003e() \u003c\u003c std::endl; // -\u003e 42\nstd::cout \u003c\u003c v.get\u003cdouble\u003e() \u003c\u003c std::endl; // -\u003e 42\nv = \"Hello Any!\";\nstd::cout \u003c\u003c v.get\u003cstd::string\u003e() \u003c\u003c std::endl; // -\u003e Hello Any!\n```\n\n#### Reference aware casting\n\n```cpp\nint x = 42;\nrevisited::Any a = std::reference_wrapper(x);\nstd::cout \u003c\u003c a.get\u003cdouble\u003e() \u003c\u003c std::endl; // -\u003e 42\nstd::cout \u003c\u003c \u0026a.get\u003cint\u0026\u003e() == \u0026x \u003c\u003c std::endl; // -\u003e 1\n```\n\n#### Inheritance aware casting\n\n```cpp\n// inheritance aware\nstruct MyClassBase{ int value; };\nstruct MyClass: public MyClassBase{ MyClass(int value):MyClassBase{value}{ } };\nrevisited::Any v;\nv.setWithBases\u003cMyClass, MyClassBase\u003e(42);\nstd::cout \u003c\u003c v.get\u003cMyClassBase \u0026\u003e().value \u003c\u003c std::endl; // -\u003e 42\nstd::cout \u003c\u003c v.get\u003cMyClass \u0026\u003e().value \u003c\u003c std::endl; // -\u003e 42\n```\n\n### revisited::AnyFunction Examples\n\n```cpp\nrevisited::AnyFunction f;\nf = [](int x, float y){ return x + y; };\nstd::cout \u003c\u003c f(40,2).get\u003cint\u003e() \u003c\u003c std::endl; // -\u003e 42\n```\n\n## Installation and usage\n\nWith [CPM](https://github.com/TheLartians/CPM), revisited::Visitor can be used in a CMake project simply by adding the following to the project's `CMakeLists.txt`.\n\n```cmake\nCPMAddPackage(\n  NAME Revisited\n  GIT_REPOSITORY https://github.com/TheLartians/Visitor.git\n  VERSION 2.0\n)\n\ntarget_link_libraries(myProject Revisited)\n```\n\nAlternatively, the repository can be cloned locally and included it via `add_subdirectory`. Installing revisited::Visitor will make it findable in CMake's `find_package`.\n\n## Performance\n\nrevisited::Visitor uses meta-programming to determine the inheritance hierarchy at compile-time for optimal performance. Compared to the traditional visitor pattern revisited::Visitor requires an additional virtual calls (as the type of the visitor and the visitable object are unknown). With compiler optimizations enabled, these calls should be hardly noticeable in real-world applications.\n\nThere is an benchmark suite included in the repository that compares the pure cost of the different approaches.\n\n```bash\ncmake -Hbenchmark -Bbuild/bench -DCMAKE_BUILD_TYPE=Release\ncmake --build build/bench -j8\n./build/bench/RevisitedBenchmark\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthelartians%2Frevisited","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fthelartians%2Frevisited","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthelartians%2Frevisited/lists"}