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"

テンプレートとモックを適切にミックスする方法について何かアイデアはありますか?


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が、どういうわけか<>テンプレートタグのbarfsです。

4

3 に答える 3

3

mocQ_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名前空間の汚染のためにそれはただの悪です-そして私のヘッダーファイルを含める前に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

リーダー関数の周りに()を付けるだけです。

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