例えば、multimapで同じキーを持つ要素の個数を調べたいとしましょう。
#include <iostream> #include <map> #include <algorithm> #include <functional> using namespace std; struct S { }; int main() { multimap<int,S *> m; for(int n = 0; n < 3; n++) { m.insert(make_pair(1, new S())); m.insert(make_pair(2, new S())); } auto r = m.equal_range(2); int size = 0; for(auto p = r.first; p != r.second; ++p) size++; cout << size << endl; // 3 for(auto p = m.begin(); p != m.end(); ++p) delete p->second; }
もちろんこのように辿っていけば数えることができますが、こんなことでループ回したくないですね。次のように再帰で関数も書けますが、これだけのために関数を作りたくありません。
template<typename T> int count(T begin, T end) { return begin == end ? 0 : 1 + count(++begin, end); }
そこでSTLのアルゴリズムにそのものズバリはないかと探すと、なさそうです。ズバリじゃなくていいならfind_ifという関数があります。第3引数に叙述関数オブジェクトを指定しなければなりませんが、常にtrueを返す関数オブジェクトというのも用意されていないので、それも適当に作ります。
auto null = make_pair(0, NULL); const int size = count_if(r.first, r.second, bind2nd(not_equal_to<pair<int,S *>>(), null));
常に等しくないならなんでもいいだろう、と思ってコンパイルすると、
error C2440: '初期化中' : 'const int' から 'S *' に変換できません。
と怒られてしまいました。よく見たら、NULLがintと思われているんですね。この問題でつまづいたのは初めてかも。こうしたら一応通りました。
auto null = make_pair(0, (S *)NULL);
もちろん、C++0xならnullptrが使えて、
auto null = make_pair(0, nullptr);
もっとも、C++0xならラムダが使えて常にtrueを返すようにすればよいです。
const int size = count_if(r.first, r.second, [] (pair<int,S *> p) { return true; });