Как передать std :: function или указатель на функцию в qtconnect? - PullRequest
0 голосов
/ 28 января 2020

Это в основном для очистки кода от моего конструктора. У меня есть около 20+ строк connect(object, func1, this, func2) в одном конструкторе, и я пытаюсь очистить код с помощью std::vector<std::tuple<QObject*,std::function<void()>,std::function<void>>>> connections;

. Было бы неплохо, если бы я мог сделать что-то вроде:

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)),
  .
  .
  .
};

И затем вызвать его так:

for(auto &&e : connections)
  connect(std::get<0>(e),std::get<1>(e),this,std::get<2>(e));

Однако, когда я делаю это, я получаю сообщение об ошибке, что возникает ошибка замещения и std::function<void()> не может быть преобразован в функцию указатель. Поэтому решите изменить его и создать фактические указатели на функции, подобные следующему:

typename void(Foo::*fooFunc)();
typename void(QSlider::*sliderFunc)();

std::vector<std::tuple<QObject*,sliderFunc,fooFunc>> sliderConnections = {
  std::make_tuple(mySlider, &QSlider::sliderReleased, &Foo::onSliderChanged),
  .
  .
  .
};

И то же самое, я затем попытаюсь вызвать его:

for(auto &&e : sliderConnections)
  connect(std::get<0>(e),std::get<1>(e),this,std::get<2>(e));

Однако это также обеспечивает аналогичное ошибка, когда нет конверсий. Что не имеет никакого смысла, потому что теперь я на самом деле использую указатель на функцию. Который согласно документации по подключению должен иметь возможность взять указатель функции для их соединения. Так что либо я передаю это неправильно. Или то, что я пытаюсь достичь, невозможно.

Любая помощь будет оценена!

1 Ответ

0 голосов
/ 30 января 2020

Посмотрев на комментарий GM, я понял, что они были правы. A QObject* не является QSlider*, и поэтому при попытке вызвать функцию QSlider::sliderReleased он не может соединить два, потому что QObject не имеет ползунка. Поэтому, как только я изменил это в векторе кортежей, код скомпилировался просто отлично.

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)
};

Это будут частные члены любого класса, за который вы отвечаете. И затем в конструкторе вместо 6 строк connect(object,SIGNAL,object,SLOT) вы можете поместить их в функцию и вызывать их следующим образом:

for(auto && tup : sliderConnections)
  connect(std::get<0>(tup),std::get<1>(tup),this,std::get<2>(tup));

Это успешно соединяет все объекты с соответствующими функциями. Опять же, это личное предпочтение. Мне просто было интересно, есть ли способ, и GM указал мне правильное направление.

...