具有模板访问器的Qt Q_属性

具有模板访问器的Qt Q_属性,qt,templates,properties,moc,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

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

考虑以下示例代码:

// 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;
}
有没有关于如何正确混合模板和moc的想法


回答cmannet85的评论,并添加更多见解-是的,
moc
调用从
moc.h
生成
moc\u test.cpp

为了进一步测试和演示它,我添加了另一个属性

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_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 @@
/****************************************************************************
**从C++文件'Test.h’读取元对象代码
**
-**创建时间:2012年10月2日星期二13:23:39
+**创建时间:2012年10月2日星期二13:22:27
**作者:Qt元对象编译器版本63(Qt 4.8.3)
**
**警告!在此文件中所做的所有更改都将丢失!
@@ -24,17 +24,20 @@
0,//类名
0,0,//classinfo
0,0,//方法
-0,0,//属性
+1,14,//属性
0,0,//枚举/集合
0,0,//构造函数
0,//标志
0,//信号计数
+//属性:名称、类型、标志
+8,4,0x02095001,
+
0//eod
};
静态常量字符qt_meta_stringdata_Foo[]={
-“Foo\0”
+“Foo\0int\0baz1\0”
};
void Foo::qt\u static\u metacall(QObject*\u o,QMetaObject::Call _c,int _id,void**\u a)
@@ -76,6 +79,30 @@
_id=QObject::qt_元调用(_c,_id,_a);
如果(_id<0)
返回_id;
+    
+#ifndef QT_无属性
+if(_c==QMetaObject::ReadProperty){
+void*_v=_a[0];
+开关(_id){
+案例0:*重新解释铸造(\u v)=baz1();断裂;
+        }
+_id-=1;
+}else if(_c==QMetaObject::WriteProperty){
+_id-=1;
+}else if(_c==QMetaObject::ResetProperty){
+_id-=1;
+}else if(_c==QMetaObject::QueryPropertyDesignable){
+_id-=1;
+}如果(_c==QMetaObject::QueryPropertyScript可写){
+_id-=1;
+}else如果(_c==QMetaObject::QueryPropertyStored){
+_id-=1;
+}else if(_c==QMetaObject::QueryPropertyEditable){
+_id-=1;
+}else if(_c==QMetaObject::QueryPropertyUser){
+_id-=1;
+    }
+#endif//QT\u NO\u属性
返回_id;
}
QT_END_MOC_名称空间

没有任何东西可以阻止moc将整个bar语句复制到
QMetaObject::ReadProperty
switch语句中,但它会在模板标记上出现bar

moc
不喜欢
Q_属性中的模板括号
声明。您可以执行以下操作:

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;
};
class Foo:public QObject{
Q_对象
Q_属性(int bar1读取bar_1)
Q_属性(int bar2读取bar_2)
私人:
内联int bar_1()常量{return bar();}
内联int bar_2()常量{return bar();}
公众:
模板int bar()常量;
};
moc
生成的代码应该能够访问类的私有方法,并且这种间接方式不应该导致任何运行时开销,因为编译器可以内联调用
bar\N


您可能希望在宏中隐藏
条的声明。

确定。我想我差点就猜出来了。由于名称空间污染,在包含我的头文件之前,
moc_test.cpp
中似乎没有定义

仅仅定义

#define ___BAR1 bar<1> 
Q_PROPERTY(int bar1 READ ___BAR1) 
对除moc之外的任何内容隐藏定义,但它是IRRLEENT-当gcc编译moc_test.cpp时,它也对gcc隐藏。只需在读取器函数周围放置()即可:

Q_PROPERTY(int bar1 READ (bar<1>))
Q_属性(int bar1读取(bar))

<代码> >代码> MOC < /C> >在C++预处理器之前运行(用“Real' C++替换所有QT关键字”,因此模板代码不被扩展,而 MOC < /Cord>本身不能这样做。这就是解析错误所指的。主要问题是“代码> MOC 使用自己的解析器,它只识别C++的一个子集。是的,但是我不知道如何使它与模板代码相同。如果在McCestTest.CPP中用‘BAZ'替换‘BAZ1’,我不认为它需要在这个步骤中扩展。它工作得很好。我该如何隐藏该声明?我会做一些类似于
#define BAR(N)inline int BAR###N()const{return BAR()}
,但是你只宏化
BAR
的解决方案更干净。好吧,我会说你的更干净-我的污染了全局命名空间,因为绝对没有定义来区分moc生成代码的编译和“真实”代码的编译。
#ifdef Q_MOC_RUN
#define ___BAR1 bar<1> 
#endif Q_MOC_RUN
Q_PROPERTY(int bar1 READ (bar<1>))