it->とか書いたことないなぁ(多分嘘)
きむら(K)さんのところから。
STLの解説とかで (*it).first とか書いてあるのはあくまで説明用であって普通は it->first と書く。
404 Not Found
- > 演算子を使った場合には解析でドジじる場合がある (多重定義されたとき?)ので前者のように書け。 とどこかで見たようなおぼえがあるんだけど。 おしえてえらいひと。
あら、説明用というか、なんというか、できるだけアロー演算子(なんか懐かしい響き)などというおかしなものに囚われたくないので、
ドットでアクセスしてたけど。
おしえてエロイ人!
operator->が定義できるが、operator.は定義できないのが、C++の節操だと思っている昨今でござる。
と、酒を飲んでいる勢いで書いたけれど、思い出した。
- >で書いた場合、連想コンテナにおいて問題が発生することがある。
例えばsetなのだけれど、要素はconstでないのだが、実装によってはconstであることがある。
標準化委員会ではset/multisetの値はconstにしない、と決めているのにも関わらずだ。(map/multimapのキーはconst)
typedef set<Hoge> HogeSet; HogeSet hogeSet; Hoge selectedId; ... HogeSet::iterator it = hogeSet.find(selectedId); if (it != hogeSet.end()) { it->setTitle("Foo"); // 実装によってはこれがコンパイルできない!!!! }
で、Effective STLではこう言っている。
- 移植性が問題ではない場合、setまたはmultisetの要素の値を変更しようとし、STLの実装で変更が可能なら、そのまま実行しよう。要素のキー部分、つまりコンテナのソート順に関係する要素の部分を変更しないことだけには注意しよう。
- 移植性が問題である場合、setとmultisetの要素は変更できない。(少なくともキャストなしでは変更できない)と仮定しよう。
で、ここで重要なのが「参照」にキャストしなければならない、ということ。
if (it != hogeSet.end()) { const_cast<Hoge>(*it).setTitle("Foo"); }
このコードはitが指すオブジェクトを撮り、キャストの結果をHogeに対する参照として扱うようにコンパイラに指示できる。
itはポインタではなくiteratorなので
const_cast<Hoge*>(it)->setTitle("Foo");
がうまくいかない事に注意せよ。
手元のgccやcwでもsetの要素は変更できなかった。
以下にテストコードを示す。
class Hoge { public: Hoge(int id) : id_(id), title_("Hoge") {} int id() const { return id_; }; const string& title() const { return title_; } void setTitle(const string& title) { title_ = title; } private: int id_; string title_; }; struct IdLess: public binary_function<Hoge, Hoge, bool> { bool operator() (const Hoge& lhs, const Hoge& rhs) const { return lhs.id() < rhs.id(); } }; typedef set<Hoge, IdLess> HogeSet; int main() { HogeSet hogeSet; Hoge selectedId(1); Hoge hoge0(0); Hoge hoge100(100); Hoge hoge3(3); Hoge hoge1(1); hogeSet.insert(hoge0); hogeSet.insert(hoge100); hogeSet.insert(hoge3); hogeSet.insert(hoge1); HogeSet::iterator it = hogeSet.find(selectedId); if (it != hogeSet.end()) { //it->setTitle("Foo"); // これはコンパイルできない! const_cast<Hoge&>(*it).setTitle("Foo"); // 正しい! //const_cast<Hoge*>(it)->setTitle("Foo"); // これもコンパイルできない! } for (HogeSet::iterator it = hogeSet.begin(); it != hogeSet.end(); ++it) { cout << (*it).title() << endl; } }
普段は->でいいんじゃねー、って話があるかもしれんけど。