{"id":19420243,"url":"https://github.com/mousebyte/memprop","last_synced_at":"2026-06-13T02:01:57.810Z","repository":{"id":76430247,"uuid":"332879515","full_name":"mousebyte/memprop","owner":"mousebyte","description":"Member property implementation suitable for use in UI libraries.","archived":false,"fork":false,"pushed_at":"2021-01-30T21:52:18.000Z","size":50,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-02-25T04:13:07.808Z","etag":null,"topics":["cpp","cpp20","properties"],"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/mousebyte.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":"2021-01-25T20:48:58.000Z","updated_at":"2021-01-30T21:52:20.000Z","dependencies_parsed_at":null,"dependency_job_id":"8317955e-6431-4a39-b7fe-aa5a37c2efbe","html_url":"https://github.com/mousebyte/memprop","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/mousebyte/memprop","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mousebyte%2Fmemprop","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mousebyte%2Fmemprop/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mousebyte%2Fmemprop/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mousebyte%2Fmemprop/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mousebyte","download_url":"https://codeload.github.com/mousebyte/memprop/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mousebyte%2Fmemprop/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34269364,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-13T02:00:06.617Z","response_time":62,"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":["cpp","cpp20","properties"],"created_at":"2024-11-10T13:21:58.923Z","updated_at":"2026-06-13T02:01:57.794Z","avatar_url":"https://github.com/mousebyte.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# memprop\nMemprop is a member property implementation suitable for use in UI libraries. Features change notifications, access control, and bindings. Requires a compiler with C++20 Concepts support.\n\n## Installation\nMemprop is a header only library. It depends on [mousebyte/sigslot20](https://github.com/mousebyte/sigslot20) for property change notifications. As long as you have `sigslot/signal.hpp` available in your project, all you need is the Memprop include directory.\n### Install with CMake\nYou can install Memprop either as a subdirectory/submodule of your project, or to the system using the install target.\nFirst, clone the Memprop repo using `git clone` or `git submodule add`. Then update memprop's submodules. If you're not interested in running the test cases, the only one you'll need is sigslot.\n```\ncd memprop\ngit submodule update --init ./lib/sigslot20\n```\nIf you're using memprop as a subdirectory of your project, just add it to your `CMakeLists.txt`:\n```cmake\noption(MEMPROP_COMPILE_TESTS \"\" OFF)\nadd_subdirectory(memprop)\n\nadd_executable(MyExe main.cpp)\ntarget_link_libraries(MyExe PRIVATE Mousebyte::memprop)\n```\nOtherwise, you can install it wherever you like.\n```\nmkdir build\ncd build\ncmake .. -B. -DMEMPROP_COMPILE_TESTS=OFF -DCMAKE_INSTALL_PREFIX=/path/to/install\ncmake --build . --target install\n```\n\n## Usage\n### Public properties\nThere are a number of different property types to choose from based on use case. The simplest property type is `public_property`, which any caller can get or set. The first template argument to any property is always the type of the owning class. Getters and setters are provided as member function pointers.\n```c++\nclass foo {\n    bool set_StringProp(std::string\u0026 out, std::string const\u0026 in)\n        {\n        out = in.substr(0, 32); // perform some custom processing or validation\n        return true;            // return false to suppress Changed signal\n        }\n        \npublic:\n    // Public property with default setter and getter\n    memprop::public_property\u003cfoo, int\u003e IntProp {this};\n    // Public property with custom setter\n    memprop::public_property\u003cfoo, int, \u0026foo::set_StringProp\u003e StringProp;\n    \n    foo() : StringProp(this, \"bar\") // Non-backed property constructors can accept an initial value\n        {\n        }\n};\n```\n### Readonly properties\nReadonly properties are identical to public properties, but can only be set from within the owner type.\n```c++\nclass foo {\npublic:\n    memprop::readonly_property\u003cfoo, int\u003e RoProp {this};\n    \n    void bar()\n        {\n        RoProp = 17; // Can be set from inside foo\n        }\n};\n\nvoid baz(foo\u0026 f)\n    {\n    int i = f.RoProp; // Can read the value from outside\n    //f.RoProp = 22;     Error: produces an access violation\n    }\n```\n### Backed properties\nBoth public and readonly properties have variants which use a backing field. These properties require a custom getter and setter.\n```c++\nclass foo {\n    int _anInt;\n    \n    int const\u0026 get_int() const  // Getter returns a const reference\n        {\n        return _anInt;\n        }\n        \n    bool set_int(int const\u0026 v)  // Setter for backed property takes a const reference\n        {\n        if(v \u003c= 100) {\n            _anInt = v;\n            return true;\n            }\n        return false;\n        }\n        \npublic:\n    memprop::backed_public_property\u003cfoo, int, \u0026foo::get_int, \u0026foo::set_int\u003e BackedProp {this};\n};\n```\n### Computed properties\nThe last type of property is the `computed_property`, which has a custom getter and no setter whatsoever.\n```c++\nclass foo {\n    float magic_number() const\n        {\n        //do some magic\n        }\n        \npublic:\n    memprop::computed_property\u003cfoo, float, \u0026foo::magic_number\u003e ComputedProp {this};\n};\n```\n### Change notifications\nAll property types except `computed_property` have a member signal, `Changed`, which is invoked each time the property's value is set from the property object. A const reference to the property's new value is passed to each slot. For more information on the signals used in this library, check out the [sigslot20](https://github.com/mousebyte/sigslot20) repo.\n### Property binding\nA property can be bound to the value of another property with the `bind()` member function. Readonly properties can only be bound to the value of another property from within their owner class. The only property type which does not support binding is `computed_property`.\n\nA custom converter object can be passed to `bind()`. Converters must have an `operator()` which expects a const reference to the source value type, and returns the target value type.\n```c++\n#include \u003cstring\u003e\n\nclass foo {\npublic:\n    memprop::public_property\u003cfoo, int\u003e FooIntProp {this};\n    memprop::public_property\u003cfoo, std::string\u003e FooStringProp {this};\n};\n\nclass bar {\npublic:\n    memprop::public_property\u003cbar, int\u003e BarIntProp {this};\n    memprop::readonly_property\u003cbar, int\u003e BarReadonlyIntProp {this};\n};\n\nstruct custom_converter {\n    std::string operator()(int const\u0026 v)\n        {\n        return std::to_string(v);\n        }\n};\n\nvoid do_some_binding()\n    {\n    foo f;\n    bar b;\n    \n    // FooIntProp will now be set whenever BarReadonlyIntProp is set\n    auto binding = f.FooIntProp.bind(b.BarReadonlyIntProp);\n    \n    //b.BarReadonlyIntProp.bind(f.FooIntProp);  Error: can't bind to readonly property outside of bar\n    \n    // Bindings can be managed through the handle returned by bind()\n    binding-\u003edisconnect();\n    \n    // Bindings can be bi-directional, setting either property will update the other\n    f.FooIntProp.bind(b.BarIntProp);\n    b.BarIntProp.bind(f.FooIntProp);\n    \n    // Bindings can be unset through the property\n    f.FooIntProp.unbind();\n    \n    // a custom converter can be passed to modify the incoming value\n    f.FooStringProp.bind(b.BarIntProp, custom_converter{});\n    }\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmousebyte%2Fmemprop","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmousebyte%2Fmemprop","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmousebyte%2Fmemprop/lists"}