The mutable
keyword permits modification of a class member declared mutable
. This is permitted even if the containing object is declared const
.
#include <unordered_map> #include <iostream> struct FactorialHelper { // Overloaded call operator long long operator()(int n) { long long result = 1; // If cache contains factorial of n, then load it, else calculate it and store in cache if(cache.find(n) != cache.end()) { result = cache[n]; } else { for(int i = 1; i <= n; ++i) { result *= i; } cache[n] = result; } return result; } private: std::unordered_map<int, long long> cache; }; int main() { FactorialHelper factorial; std::cout << factorial(5); }
This code compiles without any errors and outputs the number
, as it should. 120 5! = 1 * 2 * 3 * 4 * 5 = 120
But our public API isn’t perfect, and doesn’t allow using our class in a constant context:
#include <iostream> #include "factorial.h" class SomeClass { long long someFunction(int a, int b, int c) const { return factorial((a + b) % c); } private: FactorialHelper factorial; }; int main() { SomeClass object; object.someFunction(2, 10, 5); // ^ Error: candidate function not viable: 'this' argument has type 'const FactorialHelper', but method is not marked const const FactorialHelper f; std::cout << f(5); // ^ Error: candidate function not viable: 'this' argument has type 'const FactorialHelper', but method is not marked const }
To fix that, we decide to mark our overloaded call operator as const
:
struct FactorialHelper {
long long operator()(int n) const {
// ...
}
// ...
};
But now, we are faced with another error. Since our method is marked as const
, the compiler does not allow us to change the state of the cache by adding a new value to it.
This is where the mutable
keyword comes in.
Let’s change our code like this:
struct FactorialHelper {
long long operator()(int n) {
// ...
}
private:
mutable std::unordered_map<int, long long> cache;
};
Now everything works well, even in a const
context.
#include <iostream> #include "factorial.h" struct SomeClass { long long someFunction(int a, int b, int c) const { return factorial((a + b) % c); } private: FactorialHelper factorial; }; int main() { SomeClass object; std::cout << object.someFunction(2, 10, 5) << std::endl; const FactorialHelper f; std::cout << f(5) << std::endl; }
RELATED TAGS
CONTRIBUTOR
View all Courses