2012-05-25 17 views
5

He tenido este código que se ejecuta durante bastante tiempo en una biblioteca:QFlags Enum Tipo de conversión falla de repente

MyClass::MyClass() 
    : QDialog() 
{ 
    // (...) 
    setWindowFlags(Qt::CustomizeWindowHint | Qt::WindowTitleHint); 
    // (...) 
} 

Entonces, después de cambiar varias partes de la biblioteca, me sale este mensaje a todos de repente:

error C2664: 'QWidget::setWindowFlags': cannot convert parameter 1 from 'int' to 'Qt::WindowFlags' 

Aparentemente no encuentra la | sobrecarga del operador proporcionada por la clase QFlags para que el resultado de | devuelve un int en lugar de un constructo QFlags.

Sé que podría lanzar manualmente el resultado a (Qt::WindowFlags) y hacerlo funcionar, pero QFlags normalmente haría innecesario este tipo de conversión.

¿Alguna idea de qué tipo de cambio podría provocar este comportamiento?

Estoy incluyendo <QtGui/QDialog> que generalmente sería suficiente. Incluir <QtCore/QFlags> no cambia el comportamiento.

Respuesta

5

Qt pone sus operadores de enumeración en el espacio de nombres global en lugar de en el espacio de nombre Qt. Si hay otro operador que coincida en el espacio de nombre actual, el compilador will not search the parent scopes. Tan pronto como agregue una sobrecarga para un operador en su espacio de nombres, las sobrecargas de Qt no estarán en el conjunto de coincidencias.

Fèlix's answer below también es válido, ya que requeriría dos conversiones implícitas: int ->QFlag ->QFlags. Visual C++ lo aceptará debido a una long-standing bug pero la mayoría de los compiladores lo rechazará:

error: no viable conversion from 'unsigned int' to 'Qt::WindowFlags' 
    (aka 'QFlags<Qt::WindowType>') 
Qt::WindowFlags f = Qt::CustomizeWindowHint | Qt::WindowTitleHint; 
       ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 

Esto funciona en todos los compiladores:

Qt::WindowFlags f(Qt::CustomizeWindowHint | Qt::WindowTitleHint); 

porque sólo se requiere una conversión: int ->QFlag.

La verdadera solución es que Qt coloque a los operadores en el mismo espacio de nombres que los tipos en los que operan. Mientras tanto, puede importar los operadores de sí mismo:

using ::operator|; 
setWindowFlags(Qt::CustomizeWindowHint | Qt::WindowTitleHint); 

Tenga en cuenta que esto puede tener consecuencias no deseadas, como se podría estar haciendo un montón de nombres disponibles en un contexto donde no deben.

El corchete de cierre en line 1733 es el final de namespace Qt que se abrió en line 58.

ADL se utiliza normalmente para resolver los operadores declarados en el mismo espacio de nombres como el tipo, pero esto no funciona si los operadores están en un espacio de nombres diferente.

+0

Tiene sentido, gracias por la explicación detallada. –

0

¿Has intentado separar el | expresión de la función de llamar? Algo así como:

// .. 
Qt::WindowFlags flags = Qt::CustomizeWindowHint | Qt::WindowTitleHint; 
setWindowFlags(flags); 
// ... 

sólo para ver dónde exactamente el problema es ...

Si se trata de un problema de incluye, simplemente #include <QtGui>

+0

Compila bien si lo divido en dos líneas como esa. ¿Alguna idea sobre la diferencia en mi código? ¿Es tal vez el operador =? –

+0

@ Fèlix paréntesis están desapareados en su ejemplo – dschulz

+0

@dschulz ¡Gracias! ¡Mi error! Ahora esta bien. –

1

Compruebe su código fuente para ver si usa Q_DECLARE_OPERATORS_FOR_FLAGS para declarar sus propios indicadores en algún lugar de un espacio de nombres antes de obtener el error de compilación.

Como @isanae dijo, If there is another operator that matches in the current namespace, .... Entonces no debes poner al otro operador que podría estar haciendo juego.

La solución es poner su propia declaración Q_DECLARE_OPERATORS_FOR_FLAGS en el espacio de nombres global, tal como lo hace Qt.

Espero que haya podido ser útil. Me tocó el mismo problema cuando puse todo en un entorno de compilación unitario, y cambié el orden de los códigos fuente y finalmente localicé el fragmento de código que causa este problema: uno Q_DECLARE_OPERATORS_FOR_FLAGS dentro de un espacio de nombres.