4

I have a class with a method (getter) that performs some relatively expensive operation, so I want to cache its result. Calling the method does not change behavior of the object, but it needs to store its result in this, so it can't be const.

The problem is that I now have another method that is const and I need to invoke my getter. Is there some generally accepted solution to this problem? Should I bypass the constness checking in the getter to make it const, (Coudn't that cause problems with optimizing compiler?) or I have to propagate the non-constness to all methods that use this getter?

Example:

class MyClass
{
public:
    Foo &expensiveGetter() /*const?*/
    {
        if (cachedValue == nullptr) {
            cachedValue = computeTheValue();
        }
        return *cachedValue;
    }

    void myMethod() /* How to make this const? */
    {
        auto &foo = expensiveGetter();
        // etc.
    }

private:
    Foo *cachedValue = nullptr;
}

I am looking for something like the RefCell in Rust.

jiwopene
  • 3,077
  • 17
  • 30
  • 2
    [One common approach](https://stackoverflow.com/questions/4554031/when-have-you-used-c-mutable-keyword) is to make `cachedValue` a `mutable` member of `MyClass` – Nathan Pierson Mar 19 '22 at 18:07
  • Could you make an answer from this? – jiwopene Mar 19 '22 at 18:10
  • one of my favorite c++ questions to ask a candidate in a job interview who had self identified as 'expert level c++' was = "what does mutable mean?" , never had a correct answer – pm100 Mar 19 '22 at 18:50

1 Answers1

10

This is one of the situations the mutable specifier fits particularly well. When a class member is mutable, that member can be changed even if the enclosing class is const.

So, if MyClass::cachedValue is a mutable Foo* instead of a Foo*, you can have const member functions in MyClass that make changes to cachedValue and then all calling code can just act on a const MyClass as normal.

Nathan Pierson
  • 5,461
  • 1
  • 12
  • 30