QFlags枚举类型转换突然失败

时间:2012-05-25 13:12:54

标签: c++ qt qt4 qt4.7

我已经将这段代码在库中运行了很长时间:

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>不会改变行为。

3 个答案:

答案 0 :(得分:5)

5.12.0开始,这应该由this commit修复:“在Qt命名空间中为该命名空间中的QFlags声明运算符”。在5.12.0之前,Qt过去常常将其枚举运算符放在全局命名空间中(参见qnamespace.h)而不是Qt命名空间。

问题是当在当前名称空间中有另一个匹配的运算符时,编译器will not search the parent scopes。因此,只要为命名空间中的任何类型的运算符添加重载,Qt的重载就不会出现在匹配集中。 ADL通常用于解析在与该类型相同的命名空间中声明的运算符,但如果运算符位于不同的命名空间中,则不起作用。

真正的解决方案是让Qt将运营商放在与他们运营的类型相同的名称空间中,这是他们在5.12.0中所做的。如果您遇到以前的版本,可以自行导入运算符:

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

请注意,这可能会产生意想不到的后果,因为您可能会在不应该使用的情况下提供大量名称。

答案 1 :(得分:1)

检查源代码,看看是否使用If there is another operator that matches in the current namespace, ...在编译错误之前在命名空间的某处声明自己的标志。

正如@isanae所说,Q_DECLARE_OPERATORS_FOR_FLAGS。所以你不应该放置可能匹配的其他运算符。

解决方案是将所有自己的Q_DECLARE_OPERATORS_FOR_FLAGS声明放在全局命名空间中,就像Qt所做的那样。

希望这可能有所帮助。当我将所有内容放入统一构建环境时,我遇到了同样的问题,我切换了源代码的顺序,最后找到导致此问题的代码片段:命名空间内有一个{{1}}。

答案 2 :(得分:0)

您是否尝试将|分开?来自函数调用的表达式?类似的东西:

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

只是为了看看问题究竟在哪里......

如果是包含问题,请执行#include <QtGui>