I am getting more and more into the Pimpl idiom (private opaque pointer to real class implementation). But I still have an issue which bothers me.
How does this idiom\design pattern deal with signals in the public class (like boost or qt signals)?
class my_class : public QObject
{
Q_OBJECT
public:
void monitorstuff();
signal:
void needupdate();
private:
class impl; unique_ptr<impl> pimpl; // opaque type here
};
class my_class::impl {
void reallymonitorstuff();
};
my_class::impl::reallymonitorstuff()
{
...
//update required here
...
}
void my_class::monitorstuff()
{
pimpl->reallymonitorstuff();
}
pimpl
, connect with signals of the outer class? A bit annoying to have twice as much signals as what is publicly available, also annoying when I need to swap instances.In general, I don't really see the problem. The public class should forward all calls to the impl including calls to connect a slot. The impl contains the signal, not the public class. E.g here using Boost.Signals2:
#include <memory>
#include <boost/signals2.hpp>
#include <iostream>
using signal_type = boost::signals2::signal<void()>;
using slot_type = signal_type::slot_type;
class my_class {
public:
my_class();
void monitorstuff();
void connect(const slot_type& slot);
private:
struct impl; std::unique_ptr<impl> pimpl;
};
struct my_class::impl {
signal_type signal;
void reallymonitorstuff();
void connect(const slot_type& slot){ signal.connect(slot); }
};
void
my_class::impl::reallymonitorstuff() {
//...
signal();
//...
}
void my_class::monitorstuff() {
pimpl->reallymonitorstuff();
}
void my_class::connect(const slot_type& slot) {
pimpl->connect(slot);
}
my_class::my_class() : pimpl(std::make_unique<my_class::impl>()){}
int main() {
my_class mc;
auto slot = []{ std::cout << "Notified!\n"; };
mc.connect(slot);
mc.monitorstuff();
}
I wonder if your problem is more specific to Qt.