Reputation: 505
I'm using a boost::signals2::signal inside a gui-class like this:
class GuiElement {
//...
typedef boost::signals2::signal<void(GuiElement &)> GuiElementSignal;
virtual GuiElementSignal &getSignal() { return signal_; };
}
All gui-classes inherit from this class so that callbacks can be registered. An example with a Toggle
class:
toggle.getSignal().connect([](lx::GuiElement &el) {
// cast to access toggle specific functions
state = static_cast<lx::Toggle &>(el).state();
cout << state << endl;
});
Inside the callback function everytime I have to cast GuiElement
to a SpecificClass
to access the specific class functions.
I'd like to avoid this cast and declare the callback signature as: toggle.getSignal().connect([](lx::Toggle &el) {...
Is there a way to realize this with templates with something like typedef boost::signals2::signal<void(T &)> GuiElementSignal
where T is replaced with the class?
Upvotes: 0
Views: 238
Reputation: 674
If you don't want to expose signal_
and don't want that all your gui-classes have to use the connect()
function, you could register all your callback functions as slots
. E.g. (using signals2) :
#include <iostream>
#include <boost/signals2/signal.hpp>
#include <boost/bind.hpp>
#include <boost/optional/optional_io.hpp>
#define registerEvent_(A) registerEvent(boost::bind(A, this, _1, _2))
struct A
{
typedef boost::signals2::signal<int (int &, int &)> EventSignal;
typedef EventSignal::slot_type SlotType;
void registerEvent(const SlotType & slot);
void triggerAll(int& a1, int& a2);
EventSignal signal_;
};
void A::registerEvent(const SlotType & slot) { signal_.connect(slot); }
void A::triggerAll(int& a1, int& a2) {std::cout << signal_(a1, a2) << "\n";}
struct B : public A
{
B();
int myFunc(int& a1, int& a2);
};
B::B() {
#ifdef WITHMACRO
registerEvent_(&B::myFunc);
#else
registerEvent(boost::bind(&B::myFunc, this, _1, _2));
#endif
}
int B::myFunc(int& a1, int& a2) { return a1 + a2 + 1; }
int main()
{
int a1 = 2;
int a2 = 3;
B b;
b.triggerAll(a1, a2);
}
Note: And you could use a macro (WITHMACRO
) if you even want to hide the bind
.
Upvotes: 0
Reputation: 23971
You can use the curiously recurring template pattern to solve this problem, for example:
template<typename T>
class GuiElement {
//...
typedef boost::signals2::signal<void(T&)> GuiElementSignal;
virtual GuiElementSignal &getSignal() { return signal_; };
};
class Button : public GuiElement<Button> {/* ... */};
Upvotes: 1