我的目标是更多的代码重用,同时保持冗长。
请考虑以下示例代码:
// 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复制整个条&lt; 1&gt; QMetaObject::ReadProperty
转换语句中的语句 - 但它以某种方式在&lt;&gt;上的barfs模板标签。
答案 0 :(得分:3)
moc
不喜欢Q_PROPERTY
声明中的模板括号。您可以执行以下操作:
class Foo : public QObject {
Q_OBJECT
Q_PROPERTY(int bar1 READ bar_1)
Q_PROPERTY(int bar2 READ bar_2)
private:
inline int bar_1() const { return bar<1>(); }
inline int bar_2() const { return bar<2>(); }
public:
template <int i> int bar() const;
};
moc
生成的代码应该能够访问类的私有方法,并且这种间接不应该导致任何运行时成本,因为编译器可以内联对bar_N
的调用。
您可能希望在宏中隐藏bar_N
的声明。
答案 1 :(得分:1)
行。我想我几乎把这个想出来了。它只是邪恶的。命名空间污染 - 在包含我的头文件之前moc_test.cpp
似乎没有DEFINE。
仅仅定义
#define ___BAR1 bar<1>
Q_PROPERTY(int bar1 READ ___BAR1)
完成了这项工作 - 但我更喜欢{M}仅在MOC运行期间(简单)和___BAR1
编译期间定义{。}}。
包围
moc_test.cpp
除了moc之外,隐藏了除了它之外的任何东西,但它不相关 - 当它编译moc_test.cpp时它也被gcc隐藏了
答案 2 :(得分:0)
只需将 () 放在 reader 函数周围:
Q_PROPERTY(int bar1 READ (bar<1>))