Qt6 и новый синтаксис сигналов и слотов

Хочу разобраться в том, как использовать новый синтаксис сигналов и слотов в Qt5 на основе указателей на методы. Из книги я взял такой код:

#include <QApplication>
#include <QHBoxLayout>
#include <QSlider>
#include <QSpinBox>

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    QWidget* window = new QWidget;
    window->setWindowTitle("Set your age");

    QSpinBox* spinBox = new QSpinBox;
    QSlider* slider = new QSlider(Qt::Horizontal);
    spinBox->setRange(0, 130);
    slider->setRange(0, 130);

    QObject::connect(spinBox, &QSpinBox::valueChanged, slider, &QSlider::setValue);
    QObject::connect(slider, SIGNAL(valueChanged(int)), spinBox, SLOT(setValue(int)));
    spinBox->setValue(35);

    QHBoxLayout* layout = new QHBoxLayout;
    layout->addWidget(spinBox);
    layout->addWidget(slider);
    window->setLayout(layout);

    window->show();

    return app.exec();
}

И немного поправил строку, чтобы вместо макросов использовались указатели на методы:

QObject::connect(spinBox, &QSpinBox::valueChanged, slider, &QSlider::setValue);

После этого код перестал компилироваться, выдается ошибка

error: no matching function for call to 'QObject::connect(QSpinBox*&, <unresolved overloaded function type>, QSlider*&, void (QAbstractSlider::*)(int))' 17 |
QObject::connect(spinBox, &QSpinBox::valueChanged, slider, &QSlider::setValue); | ~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Как правильно использовать сигналы и слоты с новым синтаксисом, чтобы такая ошибка не возникала?


Ответы (1 шт):

Автор решения: αλεχολυτ

Проблема возникает потому, что в вызове connect нет однозначности какую перегрузку valueChanged использовать. А в классе QSpinBox их две:

void valueChanged(int);
void valueChanged(const QString &);

В справке об этом сигнале, кстати, как раз указано про способ разрешения этой проблемы:

Note: Signal valueChanged is overloaded in this class. To connect to this signal by using the function pointer syntax, Qt provides a convenient helper for obtaining the function pointer as shown in this example:

connect(spinBox, QOverload<int>::of(&QSpinBox::valueChanged),
   [=](int i){ /* ... */ });

Чуть лаконичнее это делается с помощью хелпер шаблона qOverload:

connect(spinBox, qOverload<int>(&QSpinBox::valueChanged),
    [=](int i){ /* ... */ });

А вот в Qt6 (который упомянут в заголовке вопроса) подобной проблемы похоже бы не возникло, т.к. они убрали перегрузку со строкой и она теперь имеет самостоятельное название:

void QSpinBox::textChanged(const QString &text)
→ Ссылка