Q_ENUMS和using声明不能一起工作



考虑以下类定义:

// exported.hpp
#include <QObject>
class Exported: public QObject {
    Q_OBJECT
public:
    using QObject::QObject;
    enum class FOO { BAR };
    Q_ENUM(FOO)
};

和以下main文件:

// main.cpp
#include <QApplication>
#include <QQmlApplicationEngine>
#include "exported.hpp"
int main(int argc, char *argv[]) {
    QApplication app(argc, argv);
    QQmlApplicationEngine engine;
    qmlRegisterType<Exported>("Package", 1, 0, "Exported");
    engine.load(QUrl(QLatin1String("qrc:/main.qml")));
    return app.exec();
}

通过这样做,我可以很容易地在QML中访问枚举的命名常量。例如:

// main.qml
import QtQuick 2.7
import QtQuick.Controls 2.0
import Package 1.0
ApplicationWindow {
    Rectangle {
        Component.onCompleted: {
            console.log(Exported.BAR)
        }
    }
}

只要枚举的声明包含在类中就可以。
例如,如果我像下面所示的那样更改类定义,它就不再工作了:

// exported.hpp
#include <QObject>
enum class FOO { BAR };
class Exported: public QObject {
    Q_OBJECT
public:
    using QObject::QObject;
    using FOO = ::FOO;
    Q_ENUM(FOO)
};

现在,QML文件中的Exported.BARundefined


最基本的问题是:为什么使用声明的不能工作?
请注意,它适用于转发声明,例如:
// exported.hpp
#include <QObject>
enum class FOO { BAR };
class Exported: public QObject {
    Q_OBJECT
public:
    using QObject::QObject;
    enum class FOO;
    Q_ENUM(FOO)
    enum class FOO { BAR };
};

这对Q_ENUM的文档实际上是真实的(强调我的):

这个宏向元对象系统注册一个枚举类型。必须放在具有Q_OBJECT或Q_GADGET宏的类的枚举声明之后。

整节没有提到定义。
另一边,我们有这个来自标准:

using声明将一组声明引入using声明所在的声明区域。

所以,我希望它也能工作。无论如何,这可能是我的一个错误的期望。

话虽如此,对于如何处理这种不方便有什么建议吗?
枚举在类外定义的情况下,我能看到的解决它的唯一方法是在类内定义另一个枚举,并在它们之间具有一对一的映射。

这与标准c++没有任何关系,至少没有直接关系。Qt的moc在理解c++语法规则方面相当有限(这是有充分理由的1)。显然,这种将枚举导入类作用域的方式超出了它的能力范围。

在我的代码中,当我想让moc为我生成enum <->字符串转换时,我使用别名,但方向相反:

class Exported: public QObject {
    Q_OBJECT
public:
    using QObject::QObject;
    enum class FOO { BAR };
    Q_ENUM(FOO)
};
using FOO = Exported::Foo;

这让moc高兴,并且是有效的c++。缺点是,您将Exported的定义拉到使用FOO定义的每个作用域中,并且您不能前声明FOO

1它是在libclang出现之前创建的,对于一些极端情况,一个完整的c++解析器的实现成本是非常不经济的。

相关内容

  • 没有找到相关文章

最新更新