2012-05-25 1 views
5

я имел этот код работает довольно долгое время в библиотеке:QFlags Enum Тип преобразование не может внезапно

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

Затем, после замены различных частей библиотеки, я получаю это сообщение все из внезапно:

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

По-видимому, он не находит | перегрузка оператора, предоставляемая классом QFlags, так что результат | возвращает int, а не конструкцию QFlags.

Я знаю, что могу вручную направить результат на (Qt::WindowFlags) и заставить его работать, но QFlags обычно делают этот вид ненужного.

Любая идея, какие изменения могут привести к такому поведению?

Я включаю в себя <QtGui/QDialog>, который обычно будет достаточным. В том числе <QtCore/QFlags> не изменяет поведение.

ответ

5

Qt помещают свои перечисления операторов в глобальном пространстве имен -, а не в пространстве имен Qt. Если есть другой оператор, который соответствует текущему пространству имен, компилятор will not search the parent scopes. Как только вы добавите перегрузку для оператора в вашем пространстве имен, перегрузки Qt не будут в наборе совпадений.

Fèlix's answer below также недопустимо, так как это потребовало бы два неявных преобразований: int ->QFlag ->QFlags. Visual C++ будет принимать его из-за long-standing bug но большинство компиляторов будет отвергать его:

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

Это работает на всех компиляторов:

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

, так как требуется только одна конверсия: int ->QFlag.

Реальное решение для Qt заключается в том, чтобы операторы находились в том же пространстве имен, что и типы, над которыми они работают. В то же время, вы можете импортировать операторам самостоятельно:

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

Обратите внимание, что это может привести к нежелательным последствиям, как вы могли бы сделать много имен, доступных в контексте, где они не должны.

Закрывающий кронштейн line 1733 конец namespace Qt, который был открыт на line 58.

ADL обычно используется для разрешения операторов, объявленных в том же пространстве имен типа, но это не работает, если операторы находятся в другом пространстве имен.

+0

Имеет смысл, спасибо за подробное объяснение. –

0

Вы пытались отделить | выражение от вызова функции? Что-то вроде:

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

Просто, чтобы увидеть, где именно проблема ...

Если это проблема включает в себя, просто сделать #include <QtGui>

+0

Он компилируется отлично, если я разбил его на две строки. Любая идея о различии с моим кодом? Возможно, это оператор =? –

+0

@ Скобки Fèlix в вашем примере непарные – dschulz

+0

@dschulz Спасибо! Виноват! Сейчас все в порядке. –

1

Проверьте исходный код, чтобы узнать, используете ли вы Q_DECLARE_OPERATORS_FOR_FLAGS, чтобы объявить свои собственные флаги где-то в пространстве имен до того, где вы получили ошибку компиляции.

Как @isanae сказал, If there is another operator that matches in the current namespace, .... Поэтому вы не должны ставить другого оператора, который может быть сопоставлен.

Решение состоит в том, чтобы разместить всю свою собственную декларацию Q_DECLARE_OPERATORS_FOR_FLAGS в глобальном пространстве имен, точно так же, как это делает Qt.

Надеюсь, это может быть полезно. Я столкнулся с той же проблемой, когда я помещал все в среду сборки с единством, и я переключил порядок исходных кодов и, наконец, нашел фрагмент кода, который вызывает эту проблему: один Q_DECLARE_OPERATORS_FOR_FLAGS внутри пространства имен.