Я стремлюсь к немного большему количеству повторного использования кода, сохраняя при этом многословие.
Рассмотрим следующий пример кода:
// qdot@defixio /tmp/test4 $ cat test.h
#include <QObject>
class Foo : public QObject {
Q_OBJECT
// Q_PROPERTY(int bar1 READ bar<1>)
// Q_PROPERTY(int bar2 READ bar<2>)
public:
template <int i> int bar() const;
};
// qdot@defixio /tmp/test4 $ cat test.cpp
#include "test.h"
#include <QDebug>
template <int i>
int Foo::bar() const { qDebug() << "Template parameter" << i; }
int main() {
Foo foo;
foo.bar<1>();
foo.bar<2>();
return 0;
}
Этот компилируется и работает, как и ожидалось.
Если вам интересно, почему мне это нужно — представьте себе набор свойств, DESIGNABLE и т. д., но подпадающих под один и тот же «класс», — в этом случае я хотел бы иметь отдельные свойства, используя средства доступа с типом enum-templatetyped.
Раскомментирование определений свойств приводит к следующей ошибке moc:
/usr/bin/moc -DQT_NO_DEBUG -DQT_GUI_LIB -DQT_CORE_LIB -DQT_SHARED -I/usr/share/qt4/mkspecs/linux-g++ -I. -I/usr/include/qt4/QtCore -I/usr/include/qt4/QtGui -I/usr/include/qt4 -I. test.h -o moc_test.cpp
test.h:5: Parse error at "bar"
Любая идея о том, как правильно смешивать шаблоны и moc?
Чтобы ответить на комментарий cmannet85 и добавить больше информации - да, этот вызов moc
генерирует moc_test.cpp
из moc.h
.
Чтобы проверить и продемонстрировать это дальше, я добавил еще одно свойство
Q_PROPERTY(int baz1 READ baz1)
и разница между moc_test.cpp до и после такова:
--- moc_test.cpp 2012-10-02 13:23:39.442333849 +0200
+++ moc_test_baz1.cpp 2012-10-02 13:23:29.822328462 +0200
@@ -1,7 +1,7 @@
/****************************************************************************
** Meta object code from reading C++ file 'test.h'
**
-** Created: Tue Oct 2 13:23:39 2012
+** Created: Tue Oct 2 13:22:27 2012
** by: The Qt Meta Object Compiler version 63 (Qt 4.8.3)
**
** WARNING! All changes made in this file will be lost!
@@ -24,17 +24,20 @@
0, // classname
0, 0, // classinfo
0, 0, // methods
- 0, 0, // properties
+ 1, 14, // properties
0, 0, // enums/sets
0, 0, // constructors
0, // flags
0, // signalCount
+ // properties: name, type, flags
+ 8, 4, 0x02095001,
+
0 // eod
};
static const char qt_meta_stringdata_Foo[] = {
- "Foo\0"
+ "Foo\0int\0baz1\0"
};
void Foo::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
@@ -76,6 +79,30 @@
_id = QObject::qt_metacall(_c, _id, _a);
if (_id < 0)
return _id;
+
+#ifndef QT_NO_PROPERTIES
+ if (_c == QMetaObject::ReadProperty) {
+ void *_v = _a[0];
+ switch (_id) {
+ case 0: *reinterpret_cast< int*>(_v) = baz1(); break;
+ }
+ _id -= 1;
+ } else if (_c == QMetaObject::WriteProperty) {
+ _id -= 1;
+ } else if (_c == QMetaObject::ResetProperty) {
+ _id -= 1;
+ } else if (_c == QMetaObject::QueryPropertyDesignable) {
+ _id -= 1;
+ } else if (_c == QMetaObject::QueryPropertyScriptable) {
+ _id -= 1;
+ } else if (_c == QMetaObject::QueryPropertyStored) {
+ _id -= 1;
+ } else if (_c == QMetaObject::QueryPropertyEditable) {
+ _id -= 1;
+ } else if (_c == QMetaObject::QueryPropertyUser) {
+ _id -= 1;
+ }
+#endif // QT_NO_PROPERTIES
return _id;
}
QT_END_MOC_NAMESPACE
Нет абсолютно ничего, что могло бы помешать moc просто скопировать все операторы bar‹1> в операторы switch QMetaObject::ReadProperty
, но он каким-то образом ругается на теги шаблона ‹>.
moc
запускается перед препроцессором C++ (чтобы заменить все ключевые слова Qt «настоящим» C++), поэтому код шаблона не расширяется, аmoc
не может этого сделать сам. Это то, на что ссылается ошибка синтаксического анализа. - person cmannett85   schedule 02.10.2012moc
использует собственный синтаксический анализатор, который распознает только подмножество C++. - person Stefan Majewsky   schedule 02.10.2012