This blog post is going to be about the C++ keyword `mutable`

, it is also going to go into using `mutable`

for data caching. To motivate this I am going to give an example
from Python. If I have a class with a property which is expensive to compute I want to cache it and only recalculate it when necessary.

#==============================================================================
class DataClass(object):
def __init__(self):
self.__data = None
@property
def data(self):
if (self.__data is None):
# work out self.__data
return self.__data

In the preceding example I have used the dynamic typing of python to essentially
combine data and a boolean. So if it is None it will be calculated and if not the cached value will be returned.

Now my goal is to replicate this in C++.

The full code to this post (and more!) is available from my bit bucket at mutable.

C++ is a statically typed language so we cannot use the exact same approach here.
So what I have done is make a class to encapsulate this idea. As the type of data is irrelevant to this class I have made it a template class. Here is the public API of the class
I have called Validated.

template <typename T>
class Validated {
public:
Validated();
Validated(const T& data);
bool valid() const;
void invalidate();
void set_data(const T& data);
operator T();
operator T() const;

This dictates the behaviour of the class so if it has a data value then it is valid and if one has not been set then it is invalid. It also (unusually) contains an implicit type converter to the data type. This is so it can be naturally treated as the data it is validating. This is normally done using an explicit function, for example the c_str() function on a standard string (also see item 5 in More Effective C++), however I feel that the Validated class is just a wrapper around the data so it should natively handle it’s operations.

The code behind this is quite straight forwards and can be seen here.

This approach can also be accomplished by privately inheriting (implementation inheritance) from a Validated base class. I think that this is a very generic concept and so should be a template

Now for the use of this class and the keyword mutable. My example is going to be a triangle and calculating it’s area. So here is the API for my `Triangle`

class, and a Point struct to hold the coordinates.

struct Point {
Point(double new_x, double new_y) {
x = new_x;
y = new_y;
}
double x;
double y;
};
class Triangle {
public:
Triangle(const Point& point_1, const Point& point_2, const Point& point_3);
void set_first_point(const Point& point);
double area() const;

This is a quite straightforward class but it is the implementation which is interesting here. Here are the private members of Triangle.

private:
Point m_point_1;
Point m_point_2;
Point m_point_3;
mutable Validated<double> m_area;

This is where the point of this post comes in, the mutable `Validated`

double. Here is a possible implementation of the area() function.

double Triangle::area() const
{
double a = sqrt(
(m_point_2.x - m_point_1.x) * (m_point_2.x - m_point_1.x) +
(m_point_2.y - m_point_1.y) * (m_point_2.y - m_point_1.y)
);
double b = sqrt(
(m_point_3.x - m_point_2.x) * (m_point_3.x - m_point_2.x) +
(m_point_3.y - m_point_2.y) * (m_point_3.y - m_point_2.y)
);
double c = sqrt(
(m_point_1.x - m_point_3.x) * (m_point_1.x - m_point_3.x) +
(m_point_1.y - m_point_3.y) * (m_point_1.y - m_point_3.y)
);
double cos_C = (a*a + b*b - c*c) / (2 * a * b);
return 0.5 * a * b * sin(acos(cos_C);
}

This is not that computationally expensive a function but suppose we are calling it a lot, so we decide to cache the result in a member variable `m_area`

.
We have two choices here as we are going to be setting a member variable we could change the method to not be const. This works fine but working out the area
is logically not going to change the triangle in any way so we call it logically const. The fact that you are caching the area is an implementation detail
that should not be reflected in the public API of the class. So this is why the keyword mutable is used. It means you can change that variable in a const method.
This is why I declared the m_area variable as mutable. Combining this with the Validated class the function becomes this.

double Triangle::area() const
{
if (!m_area.valid()) {
double a = sqrt(
(m_point_2.x - m_point_1.x) * (m_point_2.x - m_point_1.x) +
(m_point_2.y - m_point_1.y) * (m_point_2.y - m_point_1.y)
);
double b = sqrt(
(m_point_3.x - m_point_2.x) * (m_point_3.x - m_point_2.x) +
(m_point_3.y - m_point_2.y) * (m_point_3.y - m_point_2.y)
);
double c = sqrt(
(m_point_1.x - m_point_3.x) * (m_point_1.x - m_point_3.x) +
(m_point_1.y - m_point_3.y) * (m_point_1.y - m_point_3.y)
);
double cos_C = (a*a + b*b - c*c) / (2 * a * b);
m_area.set_data(0.5 * a * b * sin(acos(cos_C)));
}
return m_area;
}

So the Validated class wrapper is used to cache the value and the member is mutable so that the method can be const.

In the BitBucket repository there is an executable which shows that the cached value is being used.
It also shows the `Validated::invalidate()`

method being used in a non-const method on the Triangle class.

If you want to know more about how to NOT use mutable this is a very good article
on it which shows some common but incorrect examples of use.

Thanks for reading and putting up with the sporadic and long posts.