Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

QFlags Enum Type Conversion fails all of a sudden

Tags:

c++

qt

qt4

qt4.7

I've had this code running for quite a while in a library:

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

Then, after changing various parts of the library, I get this message all of a sudden:

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

Apparently it doesn't find the | operator overload provided by the QFlags class so that the result of | returns an int rather than a QFlags construct.

I know I could manually cast the result to (Qt::WindowFlags) and make it work, but QFlags would usually make this kind of cast unnecessary.

Any idea what kind of change could lead to this behaviour?

I am including <QtGui/QDialog> which would usually be sufficient. Including <QtCore/QFlags> doesn't change the behaviour.

like image 432
Tim Meyer Avatar asked May 25 '12 13:05

Tim Meyer


2 Answers

Since 5.12.0, this should be fixed by this commit: "Declare the operator| in the Qt namespace for QFlags in that namespaces". Before 5.12.0, Qt used to put its enum operators in the global namespace (see qnamespace.h) instead of in the Qt namespace.

The problem is that when there is another operator that matches in the current namespace, the compiler will not search the parent scopes. Therefore, as soon as you add an overload for an operator for any type in your namespace, Qt's overloads won't be in the set of matches. ADL is normally used to resolve operators declared in the same namespace as the type, but this doesn't work if the operators are in a different namespace.

The real solution was for Qt to put operators in the same namespace as the types they operate on, which they did in 5.12.0. If you're stuck with a previous version, you can import the operators yourself:

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

Note that this may have unintended consequences, as you might be making a lot of names available in a context where they shouldn't.

like image 61
isanae Avatar answered Oct 14 '22 18:10

isanae


Check your source code to see if you use Q_DECLARE_OPERATORS_FOR_FLAGS to declare your own flags somewhere in a namespace before where you got the compile error.

As @isanae said, If there is another operator that matches in the current namespace, .... So you should not put the other operator that might be matching.

The solution is to put all your own Q_DECLARE_OPERATORS_FOR_FLAGS declaration in global namespace, just as what Qt does.

Hope this could be helpful. I hit the same issue when I put everything into a unity build environment, and I switch the order of source codes and finally located the code snippet that causes this problem: one Q_DECLARE_OPERATORS_FOR_FLAGS inside a namespace.

like image 34
ZHANG Zikai Avatar answered Oct 14 '22 19:10

ZHANG Zikai