Tengo problemas para familiarizarme con la nueva sintaxis de señal / ranura (usando la función de puntero a miembro) en Qt 5, como se describe en Nueva sintaxis de ranura de señal . Traté de cambiar esto:
QObject::connect(spinBox, SIGNAL(valueChanged(int)),
slider, SLOT(setValue(int));
a esto:
QObject::connect(spinBox, &QSpinBox::valueChanged,
slider, &QSlider::setValue);
pero recibo un error cuando intento compilarlo:
error: no hay función coincidente para la llamada a
QObject::connect(QSpinBox*&, <unresolved overloaded function type>, QSlider*&, void (QAbstractSlider::*)(int))
He intentado con clang y gcc en Linux, ambos con -std=c++11
.
¿Qué estoy haciendo mal y cómo puedo solucionarlo?
Respuestas:
El problema aquí es que hay dos señales con ese nombre:
QSpinBox::valueChanged(int)
yQSpinBox::valueChanged(QString)
. Desde Qt 5.7, se proporcionan funciones auxiliares para seleccionar la sobrecarga deseada, para que pueda escribirPara Qt 5.6 y anteriores, debe decirle a Qt cuál desea elegir, lanzándolo al tipo correcto:
Lo sé, es feo . Pero no hay forma de evitar esto. La lección de hoy es: ¡no sobrecargue sus señales y ranuras!
Anexo : lo realmente molesto del elenco es que
void
(para señales).Así que a veces me encuentro usando este fragmento de C ++ 11:
Uso:
Personalmente, no me parece realmente útil. Espero que este problema desaparezca por sí solo cuando Creator (o su IDE) inserte automáticamente el yeso correcto al completar automáticamente la operación de tomar el PMF. Pero mientras tanto ...
Nota: ¡la sintaxis de conexión basada en PMF no requiere C ++ 11 !
Anexo 2 : en Qt 5.7, se agregaron funciones auxiliares para mitigar esto, siguiendo el modelo de mi solución anterior. El ayudante principal es
qOverload
(también tienesqConstOverload
yqNonConstOverload
).Ejemplo de uso (de los documentos):
Anexo 3 : si observa la documentación de cualquier señal sobrecargada, ahora la solución al problema de sobrecarga se indica claramente en los propios documentos. Por ejemplo, https://doc.qt.io/qt-5/qspinbox.html#valueChanged-1 dice
fuente
static_cast
fealdad sobre la sintaxis anterior, simplemente porque la nueva sintaxis permite una verificación en tiempo de compilación de la existencia de la señal / ranura donde la sintaxis anterior fallará en tiempo de ejecución.QSerialPort
)El mensaje de error es:
La parte importante de esto es la mención del " tipo de función sobrecargado no resuelto ". El compilador no sabe si quieres decir
QSpinBox::valueChanged(int)
o noQSpinBox::valueChanged(QString)
.Hay varias formas de resolver la sobrecarga:
Proporcione un parámetro de plantilla adecuado para
connect()
Esto obliga
connect()
a resolver&QSpinBox::valueChanged
la sobrecarga que requiere unint
.Si tiene sobrecargas no resueltas para el argumento de ranura, deberá proporcionar el segundo argumento de plantilla a
connect()
. Desafortunadamente, no hay sintaxis para pedir que se infiera el primero, por lo que deberá proporcionar ambos. Es entonces cuando el segundo enfoque puede ayudar:Use una variable temporal del tipo correcto
La asignación a
signal
seleccionará la sobrecarga deseada, y ahora se puede sustituir con éxito en la plantilla. Esto funciona igualmente bien con el argumento de 'ranura', y me parece menos engorroso en ese caso.Usa una conversión
Podemos evitarlo
static_cast
aquí, ya que es simplemente una coerción en lugar de eliminar las protecciones del lenguaje. Yo uso algo como:Esto nos permite escribir
fuente
En realidad, puedes envolver tu ranura con lambda y esto:
Se verá mejor. : \
fuente
Las soluciones anteriores funcionan, pero resolví esto de una manera ligeramente diferente, usando una macro, así que por si acaso aquí está:
Agregue esto en su código.
Entonces, tu ejemplo:
Se convierte en:
fuente
#define CONNECTCAST(class,fun,args) static_cast<void(class::*)args>(&class::fun)
, se usa comoCONNECTCAST(QSpinBox, valueChanged, (double))
en este caso.