QFlags Enum Type Conversion fails all of a sudden
Asked Answered
K

3

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.

Keratin answered 25/5, 2012 at 13:12 Comment(0)
R
7

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.

Reno answered 6/2, 2016 at 1:28 Comment(0)
A
3

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.

Alwitt answered 11/5, 2016 at 4:2 Comment(0)
S
0

Have you tried to separate the | expression from the function calling? Something like:

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

Just to see where exactly the problem is...

If it's a problem of includes, just do #include <QtGui>

Silkaline answered 25/5, 2012 at 13:58 Comment(6)
It compiles fine if I split it into two lines like that. Any idea about the difference to my code? Is it maybe the = operator?Keratin
@Fèlix parentheses are unpaired in your exampleGreeley
@Greeley Thanks! My mistake! Now it's ok.Silkaline
@TimMeyer Probably the compiler has a bad time trying to decipher if it must be considered as an int or as a Qt::WindowFlags. This method avoids the use of type cast.Silkaline
setWindowFlags( Qt::WindowFlags (Qt::CustomizeWindowHint | Qt::WindowTitleHint) ); should also work. I've seen this style in some Qt books.Greeley
Right, you are instantiating a Qt::WindowFlags with the copy constructor, just like mine. Same old friend, but different suit. And yours is a more compact solution, yes.Silkaline

© 2022 - 2024 — McMap. All rights reserved.