構造体のインスタンスが const で修飾されているとき メンバに値を代入する方法 〜危険なコードと安全なコード〜

適当な構造体 TTest のインスタンスが const で修飾されているとき(const TTest x),そのメンバに値を代入したい,でもそのためだけにそのインスタンス(x)から const を外すのは嫌,という場合を考えよう.あるいは const メンバ関数(メンバ変数を変更しないメンバ関数)で,テンポラリなメンバ変数を変更したい,でもそのメンバ関数を非 const にするのは嫌,という場合でもいい.結論から言えば, mutable を使うと解決できる.
構造体とそのインスタンス

struct TTest 
{
  int a;
  int b;
};
const TTest x= {10,2};

を考える. x は const 修飾されているから,当然

x.a=5;

のようなコードはエラー. g++ なら

error: assignment of data-member 'TTest::a' in read-only structure

というエラーを吐く.むりやり値を代入するには,

((TTest&)x).a= 5;
// or
const_cast<TTest&>(x).a= 5;

のようなコードを書くと言う手段がある.前者は C 言語流のむりやりキャストで,後者は C++ のキャスト.後者の方が const を外すことを意識してプログラムしている,あるいはコードを読むと意識的に const を外したことがわかるという点でベターだ.しかし,いずれも乱暴なコードで,危険性もある.変数 x の宣言を見ると,この変数が変わることはない,と思うからだ.

そこで,メンバ変数 a については,書き換えてもよいことにする.例えばテンポラリ変数(一時的に使われる変数)のような場合だ.具体的には ,宣言の頭に mutable キーワードをつけて,

struct TTest
{
  mutable int a;
  int b;
};

と書く.これによって, TTest のインスタンスが const であっても a を変化させてもよい,ということをコンパイラに伝えることができる.つまり,

const TTest x= {10,2};
x.a=5;

がエラーではなくなる.

このように mutable をつける方法は,キャストの方法よりもいくらか安全だ.なぜなら,構造体 TTest のメンバを見ると a がインスタンスが const でも変更される可能性があることに気づくからだ.
const 修飾したメンバ関数から mutable 修飾したメンバ変数を変更することも可能である.