ルギア君の戯言

雑多な記事。

const_iterator

まあ、なんでもいいんだけど、STL には const_iterator っていうのがあるよね。


あの本に使い方が載っていないんだけど、昨日その存在意義が漸くわかったw


例えば、

using namespace std;

set<map<string, int> >           set1;
set<map<string, int> >::iterator ps;
map<string, int>::iterator       pm;

set1.insert(...);
...
set1.insert(...); // データを登録する

// 普通、iterator
for(ps = set1.begin(); ps != set2.end(); ps++) {
  for(pm = ps->begin(); pm != ps->end(); pm++) {
    cout << pm->first << ": " << pm->second << endl;
  }
}
// のような使い方をしますよね。
// set には less<T> が必要ですから、less<map<string, int> > が必要になりますね。それを自分で定義する時に、
class myless {
  public:
    bool operator() (map<string, int> &d1, map<string, int> &d2) const;
};
// って const 宣言しますよね。これを定義する時にも、
bool myless::operator() (map<string, int> &d1, map<string, int> &d2) const {
  map<string, int>::iterator pp1, pp2;
  pp1 = d1.begin();
  pp2 = d2.begin();
  for(; pp1 != d1.end() && pp2 != d2.end(); pp1++, pp2++) {
    if(pp1->first != pp2->first) {
      return pp1->first < pp2->first;
    }
  }
  return false;
}
// のように使いますよね。

しかし、この operator () はエラーになります。
const 宣言されている関数内では hoge.begin() は const_iterator を返すからみたいです。実は昨日のエラーはそのエラーでした。
typedef は展開してしまうので非常にわかりにくいのです。困りますよね。
え? でも const_iterator だったら pp1++ はできないんじゃいかと小一時間(ry
const_iterator はそんな不便なものではありません。
あくまで const_iterator というのは、*pp1 = ... ができないだけというだけで、pp1++ ができないわけじゃないということがようやくわかり、

bool myless::operator() (map<string, int> &d1, map<string, int> &d2) const {
  map<string, int>::const_iterator pp1, pp2;
  pp1 = d1.begin();
  pp2 = d2.begin();
  for(; pp1 != d1.end() && pp2 != d2.end(); pp1++, pp2++) {
    if(pp1->first != pp2->first) {
      return pp1->first < pp2->first;
    }
  }
  return false;
}

っていうふうに修正すればいいわけですよね。
ちなみに、pp1++ のできない iterator を故意的に作ることは可能ですが iterator なので、それでは用を成しませんw

  const map<string, int>::const_iterator pp = ...

のようにね。