Препроцессор C++ и QT MOC
Я пытаюсь что-то (возможно, глупо).
Использовали несколько макросов для создания "количества" функций в домене C++;
#define THR_CONFIG_VALUE(path, value, type, name, defaultvalue) \
type name() { return m_##name; } \
void set##name(type data) { m_##name = data; }
#include <backend/config.i>
#undef THR_CONFIG_VALUE
Основано на следующем файле config.i:
THR_CONFIG_VALUE("", "type", int, ThisType, 0)
THR_CONFIG_VALUE("", "auto", bool, AutoVar1, false)
THR_CONFIG_VALUE("", "auto", bool, AutoVar2, false)
Это прекрасно работает, я получаю ряд функций-установщиков, также генерирую переменные-члены таким же образом (для записи).
Теперь я начинаю смешиваться с вещами QT, пытаясь использовать MOC для генерации Q_PROPERTIES:
#define THR_CONFIG_VALUE(path, value, type, name, defaultvalue) \
Q_PROPERTY(type name READ name WRITE set##name NOTIFY indexChanged)
#include <backend/vessel/thruster/thruster_config.i>
#undef THR_CONFIG_VALUE
МОК пофиг на такие попытки. Это спасло бы меня, набрав 170 строк Q_PROPERTY и в будущем еще несколько сотен.
Вопрос 1: почему, препроцессор и последовательность MOC? Вопрос 2: есть ли "путь QT"?
Спасибо,
3 ответа
Теперь у меня есть реализация, которая работает. Использовал вклад Вердигриса.
Немного сложно, пришлось включить C++14 и добавить это определение в файл PRO:
DEFINES += __cpp_constexpr=201304 __cpp_variable_templates=201304
Также, как я использовал пространства имен; пришлось сделать включения внутри пространства имен:
FRONTEND_BEGIN_NAMESPACE
#include <frontend/gui/helper/wobjectdefs.h>
Тогда это работает:
#define THR_CONFIG_VALUE(path, value, type, name, defaultvalue) \
W_PROPERTY(type, name MEMBER m_##name)
#include <backend/config.i>
#undef THR_CONFIG_VALUE
Qt имеет свой собственный способ генерирования методов получения и установки, основываясь на имени переменной, как вы это сделали.
Посмотрите на систему собственности
Я реализовал макрос для Qt, который делает то, что вы хотите, но он должен использоваться в контексте QObject
или же Q_GADGET
, (Q_PROPERTY
нельзя использовать вне их.)
Когда я впервые написал макрос, я не понимал, что Q_PROPERTY не генерирует установщик, метод получения, метод уведомления или даже хранилище для значения. Они должны быть сгенерированы отдельно (что легко в макросе).
NOTIFY
часть Q_PROPERTY
требует signal
быть определенным. Поскольку сигналы кодируются в C++ с помощью MOC перед вызовом препроцессора, используя #define
не будет работать. (Я не использую NOTIFY
в моем коде.)
Неполный пример:
#define THR_CONFIG_VALUE(type, name) \
Q_PROPERTY(type name READ name WRITE set##name) \
type m_##name; \
void set##name(const type &a_value) { m_##name = a_value; } \
...