Search code examples
c++language-lawyerconstantsatomicmutable

In what sense const allows only atomic changes to mutable member variables?


I'm reading Functional Programming in C++ from Ivan Čukić, and I am having a hard time interpreting a point in the summary of Chapter 5:

  • When you make a member function const, you promise that the function won't change any data in the class (not a bit of the object will change), or that any changes to the object (to members declared as mutable) will be atomic as far as the users of the object are concerned.

If the part in italic was simply are limited to members declared as mutable I would have been happy with it. However, this rewording of mine seems to correspond to what the author put in parenthesis. What is out of parenthesis is what is puzzling me: what is the meaning of atomic in that sentence?


Solution

  • The author is making a claim about best practices, not about the rules of the language.

    You can write a class in which const methods alter mutable members in ways that are visible to the user, like this:

    struct S {
        mutable int value = 0;
        int get() const {
            return value++;
        }
    };
    const S s;
    std::cout << s.get();  // prints 0
    std::cout << s.get();  // prints 1
    // etc
    

    You can do that, and it wouldn't break any of the rules of the language. However, you shouldn't. It violates the user's expectation that the const method should not change the internal state in an observable way.

    There are legitimate uses for mutable members, such as memoization that can speed up subsequent executions of a const member function.

    The author suggests that, as a matter of best practices, such uses of mutable members by const member functions should be atomic, since users are likely to expect that two different threads can call const member functions on an object concurrently.

    If you violate this guideline, then you're not directly breaking any rules of the language. However, it makes it likely that users will use your class in a way that will cause data races (which are undefined behaviour). It takes away the user's ability to use the const qualifier to reason about the thread-safety of your class.