Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Thank you for observable property idea #39

Open
YarikTH opened this issue Jan 7, 2023 · 1 comment
Open

Thank you for observable property idea #39

YarikTH opened this issue Jan 7, 2023 · 1 comment

Comments

@YarikTH
Copy link

YarikTH commented Jan 7, 2023

I'm working on reactive library µReact as a hobby.

Reactive variables works better when they are public members of classes, because such way they are more expressive and require less (or even no) boilerplate code.

But if they made so, then their assignment operator is exposed too, so such members can be reassigned to new values by mistake.

I've seen attempt to protect from it by declaring public members as const, but const members always have been kind of problem in C++.

So observable property approach from Getting started with observable properties comes to the rescue. To protect from reassigned public members should have class that makes construction and assignment private and allows it only for their parameterized Owner class.

So here is the result: https://godbolt.org/z/8rKPWW8fq

#include <iostream>

#include "https://raw.githubusercontent.com/YarikTH/ureact/dev/single_include/ureact/ureact_amalgamated.hpp"

class Foo : ureact::member_signal_user<Foo> {
    // the same as inheritance from ureact::member_signal_user<Foo>
    // UREACT_USE_MEMBER_SIGNALS(Foo);
   public:
    Foo(ureact::context& ctx, int aValue, int bValue) {
        // Defining reactive variables. We can reassign their values later
        a = make_var(ctx, aValue);
        b = make_var(ctx, bValue);

        // Defining reactive signal using overloaded operator
        // Its value will be updated each time its dependencies are changed
        x = a + b;
    }

    member_var_signal<int> a;
    member_var_signal<int> b;
    member_signal<int> x;
};

int main() {
    ureact::context ctx;

    Foo foo{ctx, 1, 2};

    std::cout << "x (init): " << foo.x() << "\n";  // 3

    // Assign a new value to 'a'. Value of 'x' is recalculated automatically
    foo.a <<= 10;
    std::cout << "x  (new): " << foo.x() << "\n";  // 12

    // member can't be reassignment from outside of Foo class
    // so next line won't compile
    // foo.a = make_var( ctx, 20 );
}
@ddinu
Copy link
Owner

ddinu commented Jan 9, 2023

I remember it took me a while to come up with this approach, but haven't used it anywhere else since I wrote this code. It's great to hear you found it useful, thanks for posting, it made my day.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants