1

Suppose I have several nested structs in C++, like this:

struct Size { int width, height; }; struct Position { int x, y; }; struct Layout { Size size; Position position; }; class Container { public: Layout layout; void onLayoutChanged(); // should be called when any field inside layout changes }; 

If I do something like container.layout.size.width = 100;, I want container.onLayoutChanged() to be automatically called.

Is there a clean or idiomatic way in C++ to achieve this kind of automatic notification whenever any nested field changes? Ideally, without having to manually trigger the notification every time.

Are there any patterns or utilities in modern C++ (C++17/20/23) that help with this kind of problem?

15
  • The "Best way" is really dependent on the framwork you use and other requirements. So any answer is probably opinion based. But in general apply the SOLID principles. The more you can decouple your C++ code from UI code the better it is in the long run. Even if "it seems more work now" (tm). Also developing a library/framework with a handle like "Newbie Programmer" ??? Commented Jul 19 at 9:33
  • @PepijnKramer Let's say the most memory efficient way and I don't think SOLID is really related to my case although I always use it anyways. And yeah, the name's just for fun lol Commented Jul 19 at 9:56
  • I assume you're looking for something other than getter/setter functions? Like because the code you want to run on change isn't fixed for the lifetime of the program for all instances of this struct Change object? You want different hooks for different instances? Commented Jul 19 at 20:57
  • @PeterCordes Yeah, you're right. Commented Jul 20 at 5:54
  • 1
    @PeterCordes Well, yeah I can. But one thing, I wanna actually notify the holder of that field when it changes, so should I store a pointer to the holder or implement some other pattern? Commented Jul 20 at 10:20

1 Answer 1

1

You would need to change the type of width such that its operator= calls a std::function<void(int)> callback.

Not at all canonical. The canonical way is to make Layout a class with protected fields and public setters.

Sign up to request clarification or add additional context in comments.

6 Comments

And the setter functions would do what, call a function-pointer if its non-null? The OP talked about trying to save memory by not having a large std::function object in every instance. Oh, that was an old version of the question. Yeah, now they've made it easy, with a non-virtual function in an outer class which you could just call from a setter function, so there's zero per-instance memory overhead, but every instance will call the same onLayoutChanged() function. Perhaps they're wondering where to put the setter function and how to have it call a function of a containing class...
Yeah actually, I didn't know how to say that properly. Silly me :(
Putting the setter in class Container itself would of course be the simplest, so container.set_layout_size_width(100). I'm not sure if there's a good way to let you write container.layout.size.set_width(100) and have it call container.onLayoutChanged() - I don't think there's a standard way to go from a struct Size *this to a pointer to the class Container which has it as a member of a member.
So I should just store a Container* in Layout and its fields?
@Newbieprogrammer: No, that would waste memory. Put the setter functions in class Container so this is already known without needing the object to store pointers into itself. Unless you need changes to one container to notify a different container, then yes, that could gain you something you couldn't get for free.
Sure, I'll try doing that.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.