There is a constant class method that is often called. I decided to cache its results, so that if the class parameters have not changed, it will return the cached value, otherwise it will be re-read. However, this violates the constancy of the method, although nothing changes for the class user. What is the best way to do this in order to cache and not lose constancy? Can somehow change the class architecture?

Here's how I imagine it:

class A { int cached_value; int parameter; bool is_value_cached = false; public: void set_parameter(int x) { parameter = x; is_value_cached = false; } int foo() const { // const error if (!is_value_cached) { // ...compute value according to parameter... cached_value = 42; // assign value to cached_value is_value_cached = true; } return cached_value; } }; 
  • But why pretend that the method does not change the state of the object, declaring it with a const qualifier, if it can change the state of the object? As an alternative, you can try to write an external cacher, in which there will be something like a type parameter -> cached_value. This will by the way be useful when you have several instances of the class, or the parameter values ​​in them can be repeated. - VTT
  • @VTT it does not change the interface that the user is thinking about, but only some hidden part. It is necessary that const correctness is preserved, because this class is further used in constant methods, etc. - steven
  • one
    @steven, you can redo a little blood. is_value_cached - take out the public getter. And you make a method like recalc() non-constant and blocking object. Then you can make a wrapper class, which will first call the is_value_cached object you is_value_cached , and then, depending on the state of recalc() and get_cached_value() . Even everything seems to be wrapped in a nice template :) - goldstar_labs
  • one
    @goldstar_labs: In C ++, the concepts of logical and physical constancy are not related in any way. This is entirely a matter of your design. You have complete freedom in the realization of your idea of ​​"logical" constancy, however far removed from physical constancy. The flow example illustrates only the curvature of the user, who for some reason imagines that constancy implies multi-threading reentrability. Nothing like C ++ constancy promises. - AnT

1 answer 1

mutable just for such purposes came up.

It is enough to add it to the declarations of the fields that you want to change in the constant method:

 mutable int cached_value; mutable bool is_value_cached = false; 
  • I understand it works. Are there any side effects from such an ad? mutable somehow stored in a different way that they can be changed? - steven
  • @steven No, there are no side effects. "somehow stored in a different way that they can be changed?" If you have no mutable fields in your class, then the constant global (and maybe some other) instances of the class can be thrown by the compiler into memory with write protection. With mutable fields, he can no longer do that. - HolyBlackCat
  • one
    @steven Yes, mutable generates a lot of very unpleasant side effects. First of all, the const qualifier in the class interface no longer says that the method will not change the state of the class. As noted above, the compiler will not be able to place objects into read-only memory, but nothing prevents it from being done by the user (true story 1: shared memory, the reader process crashes with an access error when calling the const method, debriefing starts, figuring out which * **** shoved into the jungle class mutable counter). - VTT
  • one
    @steven Next, if you want to put some of the calculations at the compilation stage, or to tie some templates, it turns out that constexpr and mutable do not get along very well (true story 2). In short, in C ++, weak and incomplete support for const-correctness is implemented, and so it is not necessary to take away the users virtually the only means of the language, which at least somehow makes it possible to judge the change in the state of the object. - VTT
  • @VTT and how then to cache or capture mutexes in constant methods? - steven