Проблема в том, что вы вызываете функцию как бесплатную функцию, когда это не так.Это функция-член, и вам нужно вызывать ее в контексте объекта:
(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) { ... }
, потому что тогда клиентможет передать любую функцию-член, с или без повышения.Но цена в том, что у вас могут быть трудные для понимания сообщения об ошибках компилятора.