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