2015-12-17 3 views
0

Я рассматриваю лучший способ реализации делегатов на C++, и до сих пор я склонен использовать обратные вызовы std::function. Однако некоторые из моих классов выдают несколько уведомлений делегатов (например, opened, closed и changed_state). Экземпляры, заинтересованные в получении уведомлений делегатов, должны назначать один из своих методов (тот факт, что он может быть закрытым, является плюсом) для события, которое он заинтересован в прослушивании. Однако следует ожидать, что, когда какой-либо экземпляр подписывается на любого из делегатов, он будет подписаться на все из них. Это означает, что не произойдет, что событие Foo выдается одному экземпляру, а событие Bar выдается другому. Есть ли способ, которым я мог бы выполнить это условие? Ни в коем случае не следует назначать обратные вызовы для разных экземпляров (предполагать атомарность).Делегаты с несколькими уведомлениями в C++

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

Примечание: Я знаю, что это другие обсуждения по теме делегатов C++, но обычно они рассматривают один тип события, а не несколько.

Пример того, что я рассматриваю:

class Connector 
{ 
public: 

    typedef struct 
    { 
    std::function<void()> opened; 
    std::function<void()> closed; 
    std::function<void()> changed_state; 
    } Delegate; 

    Delegate delegate; 
}; 

// Somewhere else 
Connector c; 
Listener l; 

// This should not be manual. Ideally: c.delegate = l; 
c.delegate.opened = l.handle_opened; 
c.delegate.closed = l.handle_closed; 
c.delegate.changed_state = l.handle_changed_state; 
+0

Почему не вы добавляете к вашему Коннектору метод 'subscribe', который соединяет слушателя и ваш коннектор? –

+0

@GrigoriyChudnov Я думаю, что мой ответ на Jarod42 также применим! –

ответ

0

Добавить operator= для этого:

class Connector 
{ 
public: 
    struct Delegate 
    { 
    Delegate& operator = (const Listener& l) 
    { 
     opened = l.handle_opened; 
     closed = l.handle_closed; 
     changed_state = l.handle_changed_state; 
     return *this; 
    } 

    std::function<void()> opened; 
    std::function<void()> closed; 
    std::function<void()> changed_state; 
    }; 

    Delegate delegate; 
}; 

, а затем вы можете иметь свой синтаксис:

c.delegate = l; 
+0

Это требует, чтобы методы слушателя были общедоступными, чего я пытался избежать. Честно говоря, я думал об этом, и я не думаю, что найду решение. Я думаю, мне нужен какой-то компромисс. –

+0

Вы можете предоставить оператор преобразования внутри 'Listener' для преобразования в' Delegate', но один из 'Deleguate' или' Listener' должен предоставить некоторый публичный доступ. – Jarod42