Qt C ++: несколько Q_NAMESPACE для одного и того же пространства имен в разных файлах - PullRequest
1 голос
/ 01 февраля 2020
  • У меня есть два enum с. Они находятся в одном и том же пространстве имен, но в разных заголовочных файлах.
  • Чтобы сделать их доступными для системы мета-типов Qt, я пытаюсь это сделать:
//C1.h
#include <QObject>
namespace SW
{
Q_NAMESPACE
enum class Enum1 {A, B};
Q_ENUM_NS(Enum1)
}
//C2.h
#include <QObject>
namespace SW
{
Q_NAMESPACE
enum class Enum2 {A, B};
Q_ENUM_NS(Enum2)
}
//main.c
#include <QDebug>
#include <QMetaEnum>

#include "C1.h"
#include "C2.h"

int main(int argc, char *argv[]) {
    auto me1 = QMetaEnum::fromType<SW::Enum1>();
    qDebug() << "me1 valid:" << me1.isValid();

    auto me2 = QMetaEnum::fromType<SW::Enum2>();
    qDebug() << "me2 valid:" << me2.isValid();
}
  • С учетом вышесказанного я получаю ошибку компоновщика дубликатов символов. Поскольку и moc_C1.o, и moc_C2.o определили staticMetaObject, полученный в результате Q_NAMESPACE
  • , я обнаружил, что пространство имен в обоих заголовках должно содержать Q_NAMESPACE. В противном случае mo c жалуется: «Ошибка: в объявлении пространства имен отсутствует макрос Q_NAMESPACE».
  • Если у меня только один из C1.h или C2.h, он собирается и работает нормально.
  • Если я переместить содержимое C2.h в C1.h, оно также работает и выдает:
me1 valid: true
me2 valid: true
  • Если переместить содержимое C2.h в main. cpp (с или без Q_NAMESPACE), он компилируется, но сбои во время выполнения:
me1 valid: true
me2 valid: false

Вопрос : нет ли способа использовать Q_NAMESPACE для пространства имен, распределенного по нескольким файлы?

Способы, которые работают вокруг Эта проблема, о которой я могу подумать:

  • Заключить мое перечисление в класс Q_OBJECT или Q_GADGET
  • Есть все мое перечисление в том же файле

Ответы [ 2 ]

0 голосов
/ 30 апреля 2020

К моему великому разочарованию, это невозможно.

В качестве альтернативы Verdigris библиотека. Он полностью совместим с Qt и позволяет использовать средства Qt без необходимости вызывать MO C, поэтому вы не получите ошибку при отсутствии Q_NAMESPACE.

Но вам нужно будет перечислить все ваши значения перечисления в макросе W_ENUM_NS и W_NAMESPACE_IMPL в некотором исходном файле

//foo.h
#pragma once

#include "wobjectdefs.h"

namespace lib
{
W_NAMESPACE(lib)

enum class Foo {
    A,
    B,
};
W_ENUM_NS(Foo, Foo::A, Foo::B)

} // namespace lib

-

// bar.h
#pragma once
#include "foo.h"
#include "wobjectdefs.h"

namespace lib
{
enum class Bar {
    A,
    B,
};
W_ENUM_NS(Bar, Bar::A, Bar::B)
} // namespace lib

-

#include <QCoreApplication>
#include <QDebug>

#include "bar.h"
#include "foo.h"

#include "wobjectimpl.h"

namespace lib
{
W_NAMESPACE_IMPL(lib)
}

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    qDebug() << lib::Bar::A;
    qDebug() << lib::Foo::A;
    return a.exec();
}
0 голосов
/ 01 февраля 2020

Кажется, это известная ошибка в соответствии с их системой отслеживания проблем QTBUG-68611

Нам придется жить с этим ограничением, пока оно не будет устранено.

В качестве альтернативы , вы могли бы (хотя я не советую) иметь промежуточное звено с файловой структурой, например:

// internal/C1.h
#include <QObject>
enum class Enum1 {A, B};
Q_ENUM_NS(Enum1)
//internal/C2.h
#include <QObject>
enum class Enum2 {A, B};
Q_ENUM_NS(Enum1)
// C.h
#include <QObject>
namespace SW
{
Q_NAMESPACE
#include internal/C1.h
#include internal/C2.h
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...