{"id":26225952,"url":"https://github.com/nativeinstruments/matchine","last_synced_at":"2025-06-15T12:06:44.020Z","repository":{"id":55972860,"uuid":"158554587","full_name":"NativeInstruments/matchine","owner":"NativeInstruments","description":"A collection of C++ tools to have more fun with sum types (fast pattern matching, etc.)","archived":false,"fork":false,"pushed_at":"2021-10-29T06:28:10.000Z","size":31,"stargazers_count":86,"open_issues_count":2,"forks_count":4,"subscribers_count":18,"default_branch":"master","last_synced_at":"2025-04-19T18:13:12.676Z","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/NativeInstruments.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":"2018-11-21T13:47:01.000Z","updated_at":"2025-03-20T06:09:51.000Z","dependencies_parsed_at":"2022-08-15T10:40:10.206Z","dependency_job_id":null,"html_url":"https://github.com/NativeInstruments/matchine","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/NativeInstruments/matchine","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NativeInstruments%2Fmatchine","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NativeInstruments%2Fmatchine/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NativeInstruments%2Fmatchine/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NativeInstruments%2Fmatchine/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/NativeInstruments","download_url":"https://codeload.github.com/NativeInstruments/matchine/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NativeInstruments%2Fmatchine/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":259971378,"owners_count":22940012,"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":"2025-03-12T19:18:22.803Z","updated_at":"2025-06-15T12:06:44.002Z","avatar_url":"https://github.com/NativeInstruments.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# MATCHINE\n\n**Matchine** is a small collection of C++ tools developed at [Native Instruments](https://www.native-instruments.com) for more fun with sum types, such variants, inheritance hierarchies, etc.\n\nThe three main tools are\n\n* `ni::overload` allows to create a single object that is a set of overloaded functions (free, lambdas, functors) following the C++ proposal [P0051R2](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0051r2.pdf). Its main application is to construct visitors inplace for `std::visit` but it's not limited to that.\n\n* `ni::match` and `ni::matcher` allows to have a similar syntax of `std::visit` and `ni::overload` for open sum types, e.g. std::any, inheritance hierarchies, etc. It provides a simple pattern matching mechanism for types based on the signature of the provided functions.\n\n* `ni::type_hierarchy` allows to build inheritance based polymorphic types without using the slow RTTI mechanism. This improves the performance of casts by an order of magnitude.\n\n\n__Disclaimer.__ This documentation is work in progress, please check back soon for more details.\n\n## Installation\n\nThe library is header only. So simply clone and go. A [`CMakeLists.txt`](CMakeLists.txt) is provided.\n\n\n\n## Quick Introduction\n\n\n### `ni::overload`\n\n```c++\n#include \u003cni/functional/overload.h\u003e\n#include \u003cvector\u003e\n#include \u003cvariant\u003e\n#include \u003cstring\u003e\n#include \u003ciostream\u003e\n\nstruct MyType {};\nusing var_t = std::variant\u003cdouble, int, MyType\u003e;\n\nint main()\n{\n    std::vector\u003cvar_t\u003e  vars = { var_t{3.14}, var_t{1337}, var_t{MyType{}} };\n    for (auto const\u0026 var : vars)\n    {\n        // instead of requiring to construct a custom function object type elsewhere\n        // one is able to overload several lambdas bound into one object.\n        auto visitor = ni::overload\n        (   [](double x) { return \"float: \" + std::to_string(x); }\n        ,   [](int n) { return \"int: \" + std::to_string(n); }\n        ,   [](auto) { return std::string(\"\u003cunknown type\u003e\"); }\n        );\n        std::cout \u003c\u003c std::visit(visitor, var) \u003c\u003c std::endl;\n    }\n}\n```\nThis will print:\n```\nfloat: 3.140000\nint: 1337\n\u003cunknown type\u003e\n```\n\n\n### `ni::match`\n\nAssume we have a polymorphic (i.e. sum) type, e.g. user input events:\n```c++\nstruct Event { virtual ~Event(){} };\nstruct MouseEvent : Event {\n    int x, y;\n    MouseEvent(int x_, int y_) : x{x_}, y{y_} {}\n};\nstruct KeyEvent : Event {\n    char key;\n    KeyEvent(char k) : key{k} {}\n};\nstruct MyEvent : Event {};\n\n```\nFurther we have a sequence of these events here simulated by putting different events into a vector:\n```c++\nusing namespace std;\n\nvector\u003cshared_ptr\u003cEvent\u003e\u003e events =\n{   make_shared\u003cMouseEvent\u003e(13, 37)\n,   make_shared\u003cKeyEvent\u003e('k')\n,   make_shared\u003cMyEvent\u003e()\n};\n\n```\n`ni::match` calls the correct lambda depending on the detected event type:\n```c++\nfor (auto const\u0026 event : events)\n{\n    auto s = ni::match(*event)\n    (   [](MouseEvent const\u0026 m) {\n            return to_string(m.x) + \", \" + to_string(m.y); }\n    ,   [](KeyEvent const\u0026 k) { return to_string(k.key); }\n    ,   ni::otherwise(string(\"\u003cunknown type\u003e\"))\n    );\n    std::cout \u003c\u003c s \u003c\u003c std::endl;\n}\n```\n\nThis will print:\n```\n13, 37\n107\n\u003cunknown type\u003e\n```\n\n\n### `ni::type_hierarchy`\n\n`ni::type_hierarchy` allows to build inheritance based polymorphic types without using the slow RTTI mechanism. This improves the performance of casts by an order of magnitude.\n\nLet's model user input events (key press, mouse move, etc.). A possible way to do this is to use inheritance and might look like this:\n```c++\nstruct Event { virtual ~Event() = default; };\n\nstruct MouseEvent : Event {\n    int x, y;\n    MouseEvent(int x_, int y_) : x{x_}, y{y_} {}\n}\n\nstruct MouseButtonDownEvent : MouseEvent {\n    enum button_t { left, right };\n    button_t button;\n    MouseButtonDownEvent(int x_, int y_, button_t b)\n    :   MouseEvent{x_, y_}\n    ,   button{b}\n    {}\n}\n\n// struct MouseButtonUpEvent : MouseEvent { ... }\n// struct KeyPressEvent : Event { ... }\n```\nThis approach has one major drawback: casting between the types uses RTTI, which is flexible, but due to that also slow because it has to handle many edge cases. If we limit ourselves to tree-like hierarchies the identification of types can be \n\n```c++\nstruct EventBase { ... };   // place to put common state shared by all objects.\n\n// get the root type from the hierarchy which serves as reference/pointer to base class.\nusing Event = ni::type_hierarchy::from_base\u003cEventBase\u003e;\n\n// derive custom types, the first template argument must always be the derived type\n// itself. This is required due to the missing reflections in C++ and is used to\n// assign a unique id to the new type.\nstruct MouseEvent : ni::sub_type\u003cMouseEvent, Event\u003e {\n    int x, y;\n    MouseEvent(int x_, int y_) : x{x_}, y{y_} {}\n};\nstruct KeyEvent : ni::sub_type\u003cKeyEvent, Event\u003e {\n    // ...\n};\n\n// 2nd level event\nstruct MouseButtonDownEvent : ni::sub_type\u003cMouseButtonDownEvent, MouseEvent\u003e {\n    // ...\n};\n\n// etc..\n\n```\nSee [benchmarks](benchmarks/README.md) for a speed comparison.\n\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnativeinstruments%2Fmatchine","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnativeinstruments%2Fmatchine","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnativeinstruments%2Fmatchine/lists"}