boost::bind и boost::function указатели на перегруженные или шаблонные функции-члены

У меня есть механизм обратного вызова, задействованные классы:

class App
{
    void onEvent(const MyEvent& event);
    void onEvent(const MyOtherEvent& event);

    Connector connect;
}

class Connector
{  
   template <class T> void Subscribe(boost::function <void (const T&)> callback);
}

App::App()
{
    connect.Subscribe<MyEvent>(&App::OnEvent<MyEvent>);
}

Во-первых, этот код не компилируется, это иллюстрация.

Использование шаблонов усложняет мой пример, но я оставил их, потому что это влияет на мою проблему. Мне кажется определенным, что моя подписка должна быть шаблонной, потому что класс Connector не знает, сколько типов событий он обрабатывает. Когда я пытаюсь создать:

boost::function f = &App::OnEvent, 

Я попытался создать OnEvent как функцию шаблона со специализациями, но кажется, что компилятор обрабатывает мои функции OnEvent как перегрузки, а не специализации шаблона, иначе я получаю специализацию шаблона не в пространстве имен, если я пытаюсь явно объявить его как

template <> OnEvent(const MyEvent& e) ...

Я могу получить следующее для компиляции:

boost::function <void (App*, const MyEvent&)> f = &App::OnEvent;
f(this, e); 

Это компилируется, запускается и работает.

boost::function<void (const MyEvent&)> g = boost::bind(&App::OnEvent, this);

не. Я думаю, это потому, что я неправильно указываю адрес перегруженной функции.

Теперь, объяснив все это плюшевому мишке, я думаю, что мой вопрос: «Как мне правильно создать указатель функции на перегруженную или шаблонную функцию-член и привязать к ней этот указатель?»


person swarfrat    schedule 16.12.2009    source источник
comment
Я погуглил, у меня точно такая же проблема с генерацией событий, каковы шансы!   -  person arynaq    schedule 15.04.2017


Ответы (2)


Я думаю, вам нужно устранить неоднозначность адреса перегруженной функции. Вы можете сделать это, явно приведя указатель функции к функции с правильными параметрами.

boost::bind( static_cast<void (App::*)( MyEvent& )>(&App::OnEvent) , this, _1);

Аналогичная проблема + решение на gamedev.net

person christopher_f    schedule 16.12.2009
comment
Жаль, что у вас может быть только один принятый ответ, но это то, чего мне не хватало. Спасибо за ссылку. - person swarfrat; 17.12.2009
comment
Я рад, что мне снова нужен этот ответ сейчас, когда у меня достаточно репутации, чтобы проголосовать за него! - person DataGraham; 10.05.2011

ты захочешь сделать

boost::function<void (const MyEvent&)> g = boost::bind(&App::OnEvent, this, _1);

Вы должны уметь выполнять g(event); с этим

Я не совсем уверен, чего вы пытаетесь достичь здесь, но на данный момент это должно решить одну из ваших проблем.

person Charles    schedule 16.12.2009
comment
Я пробовал, и я думаю, что это правильное использование привязки, проблема заключается в отсутствии соответствующего вызова функции для привязки (‹неразрешенный тип перегруженной функции›, App* const, boost::arg‹1›&). Я также пытался сделать это с помощью шаблона OnEvent в классе App, чтобы обойти это, предоставив специализацию по типу аргумента для событий, на которые я хочу подписаться, и явно указав параметр шаблона. Но я еще не разобрался с этим. - person swarfrat; 16.12.2009
comment
Этот код заставит g(event) работать, но он не будет точно работать с шаблонами, как я думаю, вы хотите. Если вы пытаетесь сделать то, что, как я думаю, вы пытаетесь сделать, вам лучше забыть этот шаблон и вместо этого использовать объявление интерфейса события. Мне было бы интересно посмотреть, как boost::function будет работать с шаблонным определением функции, но я не думаю, что это возможно. Вы можете проверить Boost::Fusion и пример Interpreter в каталоге lib. Это самый продвинутый инструмент реализации Boost::function, который я знаю. библиотеки/типы_функций/пример/интерпретатор.hpp - person Charles; 16.12.2009
comment
Я удалил шаблоны со стороны OnEvent (подписка по-прежнему шаблонна), и это работает для одного события. Но как только я перегружаю OnEvent, он уже не может определить, какой именно. Я понимаю, почему, поскольку указатель на функцию знает свой тип, а boost::bind — нет. - person swarfrat; 16.12.2009