QFlags枚举类型转换突然失败

问题描述 投票:5回答:3

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

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

c++ qt qt4 qt4.7
3个回答
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
投票

检查源代码,看看是否使用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


0
投票

你试图分开|来自函数调用的表达式?就像是:

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

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

如果这是包含的问题,那就做#include <QtGui>

© www.soinside.com 2019 - 2024. All rights reserved.