22項 setとmultisetのキーのインプレース変更を避けよう
setとmultisetのキーのインプレース変更を避けよう
setやmultisetが比較に使う"キー"の値を変更すると、未定義の結果になります。
set<int> s; s.insert(0); *(s.begin()) = 1; //この結果は未定義
処理系によっては、"*(s.begin())"がconst T&を返すため、上のコードがコンパイルできないものがあります。
これは、"キー"の値を変更させないようにするための実装です。viausl C++ 2012はconst T&を返しました。
"*(s.begin())"がconst T&を返す処理系では、キーの値以外の値も変更できなくなるという問題が起こります。
EmpIDSet::iterator i = se.find(selectedID); if(i != se.end()) { i->setTitle("Corporate Deity"); //titleは"キー"でないため変更したいが、 //iがconst T*なので、できない。 }
キーの値以外の値を変更するには、const_castを使います。
EmpIDSet::iterator i = se.find(selectedID); if(i != se.end()) { const_cast<Employee&>(*i).setTitle("Corporate Deity"); }
もしくは、一時的なオブジェクトを利用します。
EmpIDSet se; Employee selectedID; ... EmpIDSet::iterator i = se.find(selectedID); // 1, 変更する要素を検索 if(i != se.end()) { Employee e(*i); // 2, 要素をコピー se.erase(i++); // 3, 要素を削除 e.setTitle("Corporate Deity"); // 4, コピーを変更する se.insert(i, e); // 5, 新しい値を挿入 }