Visual Studio 2010 での C++ 標準コンテナ set の仕様変更

ISO C++98 では、set/multiset の要素を変更することが可能でしたが、C++0x では変更不可と決定されました(set の要素はキーなので不変であるはずという理由)。このため、set/multiset の iterator は iterator/const_iterator ともに const_iterator になっています。set/multiset から iterator で要素のオブジェクトを取得してメンバーの値を書き換えているようなプログラムは、そのままではビルドできなくなっています。

'const Hoge' から 'Hoge &' へ 'this' ポインターを変換できません。

STL Breaking Changes in Visual Studio 2010 Beta 1 (Visual C++ Team Blog)

一番最初に思いつく対応策は、iterator が指している要素を const_cast で書き換え可能にすることですが、このやり方は非推奨です。推奨される対応方法は、

  • オブジェクトのキーと変更可能なメンバー(Value)を分離して map/multimap でデータを管理する
  • set/multiset から取り出した要素を別オブジェクトにコピーして値を修正し、元の要素はコンテナから削除してコピーの方を挿入する ・・・というようにコーディングする
  • set/multiset, comparator> のように set の要素を shared_ptr にする

Visual Studio 2010 beta 1 では、_HAS_IMMUTABLE_SETS というマクロが yvals.h に定義されていて値が1になっています。この値を0にすることで、set/multiset の仕様を C++98 と同じにすることができますが、Visual Studio 2010 beta 1 より後のリリースでこのマクロは廃止されるそうです。ということでコードの修正が必須になります。