Boost の万能ファンクタ Boost.Function は、そのコピーの際、中に格納された関数オブジェクトも一緒にコピーしてくれます:
#include <boost/function.hpp> #include <iostream> #include <boost/format.hpp> // 萌え using namespace std; using boost::format; // テスト用ファンクタ struct counter { explicit counter( int count_ = 0 ) : count( count_ ) {} int operator()() { return ++count; } int count; }; int main() { // カウンタを作る counter c1; // function に入れる boost::function<int()> f1 = c1, f2; cout << "f1 = c1;\n"; // c1() と f1() の両方を呼んでみる // format 萌え cout << format("c1(): %1%\n") % c1(); cout << format("f1(): %1%\n") % f1(); // f2 に f1 の中身を入れる f2 = f1; cout << "f2 = c2;\n"; // f1() と f2() をそれぞれ呼び出す cout << format("f1(): %1%\n") % f1(); cout << format("f2(): %1%\n") % f2(); // 一応、参照で渡すこともできる cout << "f1 = boost::ref(c1);\n"; f1 = boost::ref(c1); // c1() と f1() の両方を呼んでみる cout << format("c1(): %1%\n") % c1(); cout << format("f1(): %1%\n") % f1(); return 0; // なくてもいい }
結果:
f1 = c1; c1(): 1 f1(): 1 f2 = c2; f1(): 2 f2(): 2 f1 = boost::ref(c1); c1(): 2 f1(): 3
この動作は凄く妥当なものなので文句をつけるつもりはありませんが、時々、参照で渡したいこともあったりなかったり。
そういう場合の解決策も無論あって、テストコードの最後にも書いたとおり、 boost::ref
を使えばおkです。
が、その場合、例えば「 std::vector< boost::function<void()> >
に入れたいけど、でも元ファンクタへの参照も保持したい」って場合はどうなるよ、という問題が存在したりします。
そういう場合、できれば boost::shared_ptr
を使いたい所ですが、でも boost::shared_ptr<counter>
をそのまま使うと operator()()
が定義されていない、という問題点が。
かといって shared_ptr<counter>
をメンバに持ち、 operator()()
を実装したクラスを用意するのは、少々面倒。
なので、この問題を回避する一般的な方法が Boost にないか、ちょっと調べてみようと思います。
というか、もし知ってたら教えてくださいお願いします m(_ _)m
12/20 追記: どうやら Boost には無いらしいので、銀天ライブラリの新関数 ptr_fun
により対処することにしました。