Boost 以前の C++ では,例えば std::list<EnemyBase*> に敵クラスの派生クラスのポインタを格納して,それら全ての draw メソッドを呼び出そうと思ったら,
#include <algorithm> //for_each のため
#include <functional> //mem_fun 等のため
#include <list>
std::list<EnemyBase*> el;
std::for_each(el.begin(), el.end(),
std::mem_fun(&EnemyBase::draw));
なんてことをしてやらなければなりませんでした.自分もしてました.
いやぁ,ほんと 3 つ目の引数のところがアホみたいに難しい.これを真面目に理解しようと思ったら 3 日は余裕で潰せると思います.ちなみに私は未だに完全には理解していません(ぉ
もしも el がポインタのコンテナじゃなくて,
std::list<Enemy> el;
だったりした日には,
std::for_each(el.begin(), el.end(),
std::mem_fun_ref(&Enemy::draw));
ですよ.何ですか,mem_fun_ref って? (※ちなみに mem_fun_ref も functional に入っています)
Eff* C++ とか,やねうら本を読み込めばこんな名前になった経緯なんかが分かったりします.
C++ が変態言語と言われるのも無理ありませんよね.
大きく話が逸れました.今回は for_each を boost::shared_ptr に使うときのお話です.
スマートポインタ boost::shared_ptr で敵の基底クラスを扱うとします.そしてそれをコンテナに格納します.つまり
#include <boost/shared_ptr.hpp>
#include <algorithm> //for_each のため
#include <functional> //mem_fun, mem_fun_ref のため
#include <list>
std::list< shared_ptr<EnemyBase> > el;
さて,ここで for_each を使おうとすると…
for_each(el.begin(), el.end(), std::mem_fun(&EnemyBase::draw));
for_each(el.begin(), el.end(), std::mem_fun_ref(&EnemyBase::draw));
//↑両方とも NG !!
なんてしようものなら無残,コンパイルエラーになります.
そこで登場するのが boost::mem_fn です.
先程のソースを以下のように修正します.
#include <boost/shared_ptr.hpp>
#include <algorithm> //for_each のため
#include <boost/mem_fn.hpp>
#include <list>
std::list< shared_ptr<EnemyBase> > el;
for_each(el.begin(), el.end(),
boost::mem_fn(&EnemyBase::draw));
これで解決です.
…さて,この mem_fn,実はめっちゃ賢い子です.なんと今まで mem_fun, mem_fun_ref と書いていたものは,どちらも mem_fn で統一出来るようになります!つまり,
std::list<EnemyBase*> el; //enemy base list
std::for_each(el.begin(), el.end(),
boost::mem_fn(&EnemyBase::draw));
も
std::list<Enemy> el;
std::for_each(el.begin(), el.end(),
boost::mem_fn(&Enemy::draw));
もどちらもコンパイルが通るのです!いやぁ,賢いね.
…とは言え, -> と . を混同しちゃったことになるので,人によってはこれを嫌がるかもしれません.自分も少しそう感じます.
ところで,lambda を使って
#include <boost/lambda/lambda.hpp> //_1 のため
std::for_each(el.begin(), el.end(), boost::lambda::_1->draw());
みたいに,もっと直感的に出来ないのか?というのも調べたのですが,どうやら出来ないようです.一応
bind を使って無理矢理やる方法もあるようなのですが,これなら mem_fn を使う方がマシというものでしょう(^^;
----
参考サイト
C++のforeachが混乱中? (
クレインハウス日記)
はぎ (2008-10-16T07:53:09)
かって鑑賞会やろうぜ!><
か (2008-10-16T13:58:47)
ていうかそもそも買うかどうか悩んでいるのにどうして鑑賞会の心配しているんだ私!?