qdo*_*dot 5 qt templates properties moc
我的目标是在保持冗长的同时,实现更多的代码重用。
考虑以下示例代码:
// 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;
}
Run Code Online (Sandbox Code Playgroud)
该程序按预期编译并运行。
如果您想知道为什么我会这样 - 想象一组属性,DESIGNABLE 等,但属于同一个“类” - 在这种情况下,我希望使用枚举模板类型访问器拥有单独的属性。
取消注释属性定义会导致以下 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"
Run Code Online (Sandbox Code Playgroud)
关于如何正确混合模板和 moc 有什么想法吗?
回答 cmannet85 的评论,并添加更多见解 - 是的,该moc调用moc_test.cpp从moc.h.
为了进一步测试和演示它,我添加了另一个属性
Q_PROPERTY(int baz1 READ baz1)
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
绝对没有什么可以阻止 moc 将整个 bar<1> 语句复制到QMetaObject::ReadPropertyswitch 语句中 - 但它会以某种方式在 <> 模板标记上出现 barfs。
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;
};
Run Code Online (Sandbox Code Playgroud)
生成的代码moc应该能够访问类的私有方法,并且这种间接访问不应引起任何运行时成本,因为编译器可以内联对bar_N.
bar_N您可能想隐藏宏中的声明。