As can be seen in the code below (implemented as an illustration of the problem), I'm trying to send a signal from an inner class to a mid class, which will relay it to an outer class.
#include <boost/bind.hpp>
#include <boost/signals2.hpp>
#include <iostream>
class inner {
public:
template <class T>
void register_callback(boost::function<void(T *)> cb, T *obj)
{
sig_inner_.connect(boost::bind(cb, boost::ref(obj)));
}
void trigger()
{
std::cout << "inner" << std::endl;
sig_inner_();
}
private:
boost::signals2::signal<void()> sig_inner_;
};
class mid {
public:
mid() { inner_obj.register_callback<mid>(&mid::handle_sig_mid, this); }
template <class T>
void register_callback(boost::function<void(T *)> cb, T *obj)
{
sig_mid_.connect(boost::bind(cb, boost::ref(obj)));
}
void trigger() { sig_mid_(); }
void inner_trigger() { inner_obj.trigger(); }
void handle_sig_mid()
{
std::cout << "mid" << std::endl;
trigger();
}
private:
boost::signals2::signal<void()> sig_mid_;
inner inner_obj;
};
class outer {
public:
outer() { mid_obj.register_callback<outer>(&outer::handle_sig_outer, this); }
void inner_trigger() { mid_obj.inner_trigger(); }
private:
mid mid_obj;
void handle_sig_outer() { std::cout << "outer" << std::endl; }
};
int main()
{
outer outer_obj;
outer_obj.inner_trigger();
return 0;
}
Instead of the desired result of:
inner
mid
outer
When running the program, what actually happens is:
inner
mid
mid
Followed by a crash.
I already noticed that the address of 'this' is different in the handler than what I would expect in a regular method, but I don't know how work around that.
The only solution I found for this was connecting a signal in the outer class to its handler, and then storing the pointer(unique_ptr, in this case) in the inner class, thus avoiding the need to relay it, but it doesn't feel like a safe way to use signals.
I'm kind of new to c++, and to boost in particular, so I don't really know how trigger callbacks in the outer class from the inner class in a clean and safe way.