简体   繁体   中英

specific class in inheritance hierachy as type in boost::signal2 callback

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?

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> {/* ... */};

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 . Eg (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 .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM