Исследовал пути решения простенькой задачи.
Задача1. Есть иерархия классов
class Base {};
class Derived : public Base {};
...
2. Есть функторы, принимающие ссылки на Base, Derived, etc...
3. Есть динамический массив функторов из п.2
Задача: обработать объект из иерархии Base функторами из массива п.3.
Исходные данныеФункторы, входящие в массив:
void Handler1(Base&);
void Handler2(Derived&);
Вспомогательный "конвертер" функторов для приведения к их одному типу:
template <typename T>
void HandlerConversion(void (*Handler)(T&), Base& c)
{
if (T* t = dynamic_cast<T*>(&c))
Handler(*t);
}
LokiВспомнив, что функторы есть в Loki, попробовал начать с этой библиотеки:
typedef Loki::Functor<void, LOKI_TYPELIST_1(Control&)> ControlFunctor;
typedef std::vector<ControlFunctor> FunctorVector;
И тут началось...
Такой вод код работает:
template <class T>
void RegisterHandler(FunctorVector& v, void (*Handler)(T&))
{
Loki::Functor<void, LOKI_TYPELIST_2(void(*)(T&), Control&)> cf(HandlerConversion<T>);
v.push_back(Loki::BindFirst(cf, Handler));
}
А такой вот вылетает с ошибкой из-за проблем с auto_ptr внутри Loki::Functor:
template <class T>
void RegisterHandler(FunctorVector& v, void (*Handler)(T&))
{
v.push_back(Loki::BindFirst(Loki::Functor<void, LOKI_TYPELIST_2(void(*)(T&), Control&)>(HandlerConversion<T>), Handler));
}
Дальше - больше. Если объявить переменную
FunctorVector v;
внутри тестовой main(), то все работает отлично, а если как глобальную переменную - вылетает при выходе из main(). Помогает
v.clear();
в конце main(). Жесть какая-то. Подобную веселую реализацию Loki::Functor не решился использовать в рабочем проекте.
BoostBoost тоже имеет реализацию функторов - boost::function:
typedef boost::function<void (Base&)> ControlFunctor;
typedef std::vector<ControlFunctor> FunctorVector;
Здесь все гораздо проще:
template <class T>
void RegisterHandler(FunctorVector& v, void (*Handler)(T&))
{
v.push_back(boost::bind(HandlerConversion<T>, Handler, _1));
}
И главное - работает как часы (в отличие от Loki).