Trusted answers to developer questions
Trusted Answers to Developer Questions

Related Tags

c++
mutable
keyword
communitycreator

What is a mutable type specifier in C++?

Danil

The mutable keyword permits modification of a class member declared mutable. This is permitted even if the containing object is declared const.

Code

#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 1205! = 1 * 2 * 3 * 4 * 5 = 120, as it should.

But our public API isn’t perfect, and doesn’t allow using our class in a constant context:

main.cpp
factorial.h
#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.

main.cpp
factorial.h
#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

c++
mutable
keyword
communitycreator
RELATED COURSES

View all Courses

Keep Exploring