std::set.find()とstatic_cast<>の一時変数返しの謎
std::set.find()
std::set の要素内容を変更できないの?と会社で言われて調べてみる。
std::set<A> sa ; std::set<A>::iterator it ; it = sa.find( 5 ) ; (*it).set_prop(7) ;
で問題なく更新できる(VC6)。ただし、setの内部実装はバイナリツリーだからキーは書き換えちゃいけません。
と思ったら、先輩の環境ではset_prop()を呼び出せない。どうやらg++ version 3.4.1(うろ覚え)ではset.find()がconst iterを返すらしい。
it = sa.find( 5 ) ; ((A)(*it)).set_prop( 7 ) ;
キャストでコンストはずせば大丈夫かと思いきや、実行しても要素内容が変わらない。この時点でsetは内部のバイナリツリーの構成が矛盾を起こさないように、set.find()はコピーを返すんだろうと推測し諦めた。けれども、const iterを返すのにコピーを返すのはおかしい(constなら書き換えられないはずだからコピーを返す必要がない、逆に言うとconst iterでない場合にコピーを返すのなら妥当だと思われる)と思い、もう一度調べ直してみた。するとconst_castを使えばOKとのこと。
it = sa.find( 5 ) ; const_cast<A &>(*it).set_prop( 7 ) ;
これでOK。ただし、移植性などを考えると、remove()してinsert()するのが礼儀っぽい。
というか、(A)のキャストで成功しないのは一時変数が返されるのが原因っぽい。(A &)なら処理系によってはOK(VC6)。
static_cast<>の一時変数返し
string str("test") ; (string)str = "modify" ;
これで、strの値が変更されないってのが驚き。ちゃんと決められてる事なんだけども。static_castや()キャストは一時変数を返すのは仕様。いつかハマらないようにメモとして残す。