3

我的目标是更多的代码重用,同时保持冗长。

考虑以下示例代码:

// 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 等,但属于同一个“类” - 在这种情况下,我希望使用枚举模板类型的访问器拥有单独的属性。

取消注释属性定义,会导致以下 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.cppmoc.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> 语句复制到QMetaObject::ReadPropertyswitch 语句中 - 但它以某种方式在 <> 模板标签上出现了错误。

4

3 回答 3

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宏中的声明。

于 2012-10-02T11:46:21.790 回答
1

好的。我想我几乎想通了这一点。moc_test.cpp这只是 evil.due 命名空间污染 -在包含我的头文件之前似乎没有 DEFINE 。

仅仅定义

#define ___BAR1 bar<1> 
Q_PROPERTY(int bar1 READ ___BAR1) 

完成了这项工作 - 但是,如果仅在 MOC 运行(简单)和编译___BAR1期间定义,我会更喜欢。moc_test.cpp

包围

#ifdef Q_MOC_RUN
#define ___BAR1 bar<1> 
#endif Q_MOC_RUN

隐藏除了 moc 之外的任何东西的定义,但它是不相关的 - 当它编译 moc_test.cpp 时它也对 gcc 隐藏

于 2012-10-02T12:10:35.137 回答
0

只需将 () 放在 reader 函数周围:

Q_PROPERTY(int bar1 READ (bar<1>))
于 2021-02-16T08:55:00.993 回答