2012-05-25 17 views
5

Ho avuto questo codice in esecuzione per un po 'in una libreria:QFlags Enum Tipo conversione fallisce tutto ad un tratto

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

Poi, dopo aver cambiato varie parti della biblioteca, ottengo questo messaggio tutti un improvviso:

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

Apparentemente non trova il | sovraccarico dell'operatore fornito dalla classe QFlags in modo che il risultato di | restituisce un int invece che un costrutto QFlags.

So che potrei trasmettere manualmente il risultato a (Qt::WindowFlags) e farlo funzionare, ma QFlags di solito rende questo tipo di cast non necessario.

Qualche idea sul tipo di modifica che potrebbe portare a questo comportamento?

Sono incluso <QtGui/QDialog> che di solito sarebbe sufficiente. Includere <QtCore/QFlags> non modifica il comportamento.

risposta

5

Qt mette i suoi gestori enum nel namespace globale anziché nello spazio dei nomi Qt. Se c'è un altro operatore che corrisponde nello spazio dei nomi corrente, il compilatore will not search the parent scopes. Non appena aggiungi un sovraccarico per un operatore nel tuo spazio dei nomi, i sovraccarichi di Qt non saranno nel set di corrispondenze.

Fèlix's answer below è anche valido perché richiederebbe due conversioni implicite: int ->QFlag ->QFlags. Visual C++ accetterà a causa di una long-standing bug ma la maggior parte dei compilatori lo rifiuterà:

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

Questo funziona su tutti i compilatori:

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

perché è necessaria una sola conversione: int ->QFlag.

La vera soluzione è che Qt metta gli operatori nello stesso spazio dei nomi sui tipi su cui operano. Nel frattempo, è possibile importare gli operatori da soli:

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

Si noti che questo può avere conseguenze impreviste, come si potrebbe essere fare un sacco di nomi disponibili in un contesto dove non dovrebbero.

La staffa di chiusura line 1733 è la fine del namespace Qt che è stato aperto il line 58.

ADL viene normalmente utilizzato per risolvere operatori dichiarati nello stesso namespace come tipo, ma questo non funziona se gli operatori sono in uno spazio diverso.

+0

Ha senso, grazie per la spiegazione dettagliata. –

0

Hai provato a separare il | espressione dalla funzione chiamata? Qualcosa di simile:

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

solo per vedere esattamente dove il problema è ...

Se si tratta di un problema di include, basta fare #include <QtGui>

+0

Si compila bene se l'ho diviso in due righe del genere. Qualche idea sulla differenza con il mio codice? È forse l'operatore =? –

+0

@ Le parentesi di Fèlix sono binarie nel tuo esempio – dschulz

+0

@dschulz Grazie! Errore mio! Adesso va bene. –

1

Controllare il codice sorgente per vedere se si utilizza Q_DECLARE_OPERATORS_FOR_FLAGS per dichiarare le proprie bandiere da qualche parte in un namespace prima di dove si è verificato l'errore di compilazione.

Come ha detto @isanae, If there is another operator that matches in the current namespace, .... Quindi non dovresti mettere l'altro operatore che potrebbe corrispondere.

La soluzione è inserire la propria dichiarazione Q_DECLARE_OPERATORS_FOR_FLAGS nello spazio dei nomi globale, proprio come fa Qt.

Spero che questo possa essere utile. Ho riscontrato lo stesso problema quando ho inserito tutto in un ambiente di compilazione di unità e ho cambiato l'ordine dei codici sorgente e infine individuato lo snippet di codice che causa questo problema: uno Q_DECLARE_OPERATORS_FOR_FLAGS all'interno di uno spazio dei nomi.