Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
int вот тут boost::signal<int(), Sum> signal должен быть string?boost::asio::io_service IoService;
boost::signal<void(int int)> TapDownSignal;
//В чужом потоке
void Application::OnTapDown(int x, int y)
{
IoService.post(boost::bind(boost::ref(TapDownSignal), x, y));
}
//В основном потоке:
void ResourceManager::Update(int dt)
{
...
IoService.run_one();
}
struct MyStruct
{
void method(int x)
{
}
};
boost::signal<void(int x)> mySignal;
MyStruct myStruct;
mySignal.connect(std::bind(&MyStruct::method, &myStruct, _1));
boost::signal<void()> signal1;
boost::signal<void()> signal2;
signal2.connect(boost::ref(signal1));
signal2(); //Вызывает signal2, который вызывает signal1
boost::signal<void(int, int)> SelectCell;
//Variant с зараннее определенными типами данных:
typedef boost::variant<int, float, std::string, vec2> TSignalParam;
//Хранитель различных сигналов:
struct TWidgetStruct
{
protected:
//Карта сигналов, ключ - имя сигнала
std::map<std::string, std::shared_ptr<boost::signal<void (TSignalParam)>>> SignalMap;
public:
//Чистим все
void ClearSignals()
{
SignalMap.clear();
}
//Добавляем слот к сигналу
void AddSlot(std::string signalName, std::function<void (TSignalParam)>> func)
{
//Если такого сигнала еще нет - создаем
if (SignalMap[signalName] == std::shared_ptr<boost::signal<void (TSignalParam)>>())
{
SignalMap[signalName] = std::shared_ptr<boost::signal<void (TSignalParam)>>(
new boost::signal<void (TSignalParam)>());
}
//Добавляем слот
SignalMap[signalName]->connect(func);
}
};
auto mouseDownFunc = [](TSignalParam param)
{
vec2 v = boost::get<vec2>(param);
std::cout<<"pressed at "<<v.x<<" "<<v.y<<std::endl;
}
auto changeTextFunc = [](TSignalParam param)
{
std::string text = boost::get<std::string>(param);
std::cout<<"text :"<<text<<std::endl;
}
TWidgetStruct WidgetStruct;
WidgetStruct.AddSlot("OnMouseDown", mouseDownFunc);
WidgetStruct.AddSlot("OnChangeText", changeTextFunc);
Тот же disconnect_all_slots чёрта с два нормально сделаешь
class MyClass
{
event EventHandler MyEvent;
void MyMethod()
{
this.MyEvent = null;
}
}
class MyClass
{
event EventHandler MyEvent;
void MyMethod()
{
this.Subscribe(ref this.MyEvent, this.MyHandler);
}
// код аналогичен add_MyEvent
// можно переписать в общем виде, используя касты в System.Delegate
void Subscribe(ref EventHandler e, EventHandler handler)
{
EventHandler fetched;
EventHandler current = e;
do
{
fetched = current;
EventHandler newE = (EventHandler)Delegate.Combine(fetched, handler);
current = Interlocked.CompareExchange(ref e, newE, fetched);
}
while (current != fetched);
}
void MyHandler(object o, EventArgs e)
{
}
}
add_MyEvent:Action<EventHandler> add_MyEvent =
(Action<EventHandler>)
typeof(MyClass)
.GetEvent("MyEvent", BindingFlags.NonPublic | BindingFlags.Instance)
.GetAddMethod(true)
.CreateDelegate(typeof(Action<EventHandler>), myClass);
// myClass – экземпляр MyClass
Вот так вы можете передать событие в функцию, а также подписаться на него:
Вот так вы, имея имя события, можете получить add_MyEvent
Возможно только внутри класса, который определяет событие.Ссылку за пределы класса можно вывести через callback-и. Несколько неудобно, да. С другой стороны, мне ещё никогда не приходилось передавать событие как аргумент. Предпочитаю IoC событийно-ориентированному подходу.
С другой стороны, мне ещё никогда не приходилось передавать событие как аргумент.
Boost Signals — сигналы и слоты для C++