This is mainly to clean up a bunch of code from my constructor. I have around 20+ lines of connect(object, func1, this, func2)
in the constructor alone and I am trying to clean up the code by having a std::vector<std::tuple<QObject*,std::function<void()>,std::function<void>>>> connections;
It would work out quite nicely if I could do something like:
std::vector<std::tuple<QObject*,std::function<void()>,std::function<void>>>> connections = {
std::make_tuple(mySlider, std::bind(&QSlider::sliderReleased,mySlider, std::bind(&Foo::onSliderChanged,this)),
.
.
.
};
And then call it like this:
for(auto &&e : connections)
connect(std::get<0>(e),std::get<1>(e),this,std::get<2>(e));
However, when I do this I get an error that there is a substitution failure and a std::function<void()>
cannot be converted into a function pointer. So decide to change it up and create actual function pointers like the following:
typename void(Foo::*fooFunc)();
typename void(QSlider::*sliderFunc)();
std::vector<std::tuple<QObject*,sliderFunc,fooFunc>> sliderConnections = {
std::make_tuple(mySlider, &QSlider::sliderReleased, &Foo::onSliderChanged),
.
.
.
};
And same thing, I then try to call it:
for(auto &&e : sliderConnections)
connect(std::get<0>(e),std::get<1>(e),this,std::get<2>(e));
However this also provides a similar error where there are no conversions. Which doesn't make any sense because now I am actually using a function pointer. Which according to the connection documentation it should be able to take a function pointer to connect them. So either I am passing it in incorrectly. Or what I am trying to achieve is not possible.
Any help would be appreciated!
After looking at G.M's comment I realized they were correct. A QObject*
is not a QSlider*
and therefore when trying to call the function QSlider::sliderReleased
it couldn't connect the two because QObject
does not have a slider. So once I changed that in the vector of tuples the code compiled just fine.
ex:
typedef void(Foo::*fooFunc)();
typedef void(QSlider::*sliderFunc)();
typedef void(QSpinBox::*spinFunc)();
const std::vector<std::tuple<QSlider*, sliderFunc, fooFunc>> sliderConnections = {
std::make_tuple(slider1, &QSlider::sliderReleased, &Foo::onSlider1Changed),
std::make_tuple(slider2, &QSlider::sliderReleased, &Foo::onSlider2Changed),
std::make_tuple(slider3, &QSlider::sliderReleased, &Foo::onSlider3Changed)
};
const std::vector<std::tuple<QSpinBox*, spinFunc, fooFunc>> spinConnections = {
std::make_tuple(spin1, &QSpinBox::editingFinished, &Foo::onSpin1Changed),
std::make_tuple(spin2, &QSpinBox::editingFinished, &Foo::onSpin2Changed),
std::make_tuple(spin3, &QSpinBox::editingFinished, &Foo::onSpin3Changed)
};
These will be private members in whatever class you are in charge of. And then in the constructor, instead of having 6 lines of connect(object,SIGNAL,object,SLOT)
, you can then put them into a function and call them like:
for(auto && tup : sliderConnections)
connect(std::get<0>(tup),std::get<1>(tup),this,std::get<2>(tup));
This successfully connects all the objects to their appropriate functions. Again, it's personal preference. I was just wondering if there was a way and G.M pointed me in the correct direction.