問題は、そうでないときに、関数をフリー関数として呼び出していることです。これはメンバー関数であり、オブジェクトのコンテキストで呼び出す必要があります。
(obj.*f)();
Boost.Bind は、これに取り組む慣用的な方法を提供します。
#include<boost/bind.hpp>
// ...
Impl i(boost::bind(&Base::fnc, obj));
Impl次のようにコンストラクタを定義できます。
#include<boost/function.hpp>
// ...
Impl(boost::function<void ()> fnc)
{
fnc(); // boost::bind translates it to obj.fnc()
}
オブジェクトのみがImpl関数を呼び出すオブジェクトを認識している場合は、Boost.Bind のプレースホルダーを使用できます。
Impl i(boost::bind(&Base::fnc, boost::_1));
そして、Implコンストラクタは次のようになります
Impl(boost::function<void (Base)> fnc, Base& b)
{
fnc(b); // boost::bind translates it to b.fnc()
}
ファンクターを受け入れる側でテンプレートを使用する方が賢明な場合があります。
template<class Op>
Impl(Op fnc) { ... }
クライアントはブーストの有無にかかわらず、任意のメンバー関数を渡すことができるためです。ただし、その代償として、コンパイラのエラー メッセージがわかりにくくなる可能性があります。