Название: Q_OBJECT-грабли в Qt4.3
Отправлено: bigirbis от Август 28, 2007, 10:26
В Qt4.3 стало обязательным объявления макроса Q_OBJECT в классе, для того, чтобы можно было использование приведение qobject_cast <>. Но при этом не разрешается использование данного макроса в шаблонных классах. А код уже написан и работает... :(.
Есть какие-нибудь красивые методы выхода из данной ситуации?
Название: Re: Q_OBJECT-грабли в Qt4.3
Отправлено: Dodge от Август 28, 2007, 15:29
Эти "Грабли" выросли из нового механизма генерации метаданных, и на мой это взгляд очень даже ничего система, ноги у нее растут скорей всего от QtScript, так что решайте задачу иным способом. Насчет шаблонов выхода нет, т.к. Q_OBJECT макрос для мок, а моку глубоко плевать на шаблоны, он их не понимает. И по подробнее про qobject_cast, в чем проблема?... лучше кусок кода.
Название: Re: Q_OBJECT-грабли в Qt4.3
Отправлено: bigirbis от Август 28, 2007, 15:38
Вот небольшой пример. Это достаточно неплохо сокращает код и делает его более понятным. template <class ObjT, class Parm1T, class RetT = void> class ThreadRun : public QThread { public: ThreadRun(ObjT *object, RetT (ObjT::*function)(Parm1T), Parm1T parm ,QObject *parent = NULL ) : QThread(parent), object_(object), function_(function), parm_(parm){} ~ThreadRun(){if(isRunning())this->wait();} void run(){retval_ = (object_->*function_)(parm_);} RetT & retval() {return retval_;} void msleep( unsigned long msecs ) {QThread::msleep( msecs ); } private: ObjT *object_; RetT (ObjT::*function_)(Parm1T); Parm1T parm_; RetT retval_; }; ThreadRun < MyWidget, QString, QString > * s_s_Thread = qobject_cast < ThreadRun < MyWidget, QString, QString > * > ( sender() );
Название: Re: Q_OBJECT-грабли в Qt4.3
Отправлено: Dodge от Август 28, 2007, 15:45
...
Интересное решение, я об этом не подумал... З.Ы. Еще можно попробовать сделать прототип, либо через макросы, получится "псевдо шаблон" :D
Название: Re: Q_OBJECT-грабли в Qt4.3
Отправлено: vaprele07 от Август 28, 2007, 16:03
а что мешает пользоваться static_cast? мне например qobject_cast не нравится из за strcmp: void *XButtonPrototype::qt_metacast(const char *_clname) { if (!_clname) return 0; if (!strcmp(_clname, qt_meta_stringdata_XButtonPrototype)) return static_cast<void*>(const_cast< XButtonPrototype*>(this)); if (!strcmp(_clname, "QScriptable")) return static_cast< QScriptable*>(const_cast< XButtonPrototype*>(this)); return QObject::qt_metacast(_clname); }
в итоге все равно приводится через стандартный каст хотя см QT_NO_MEMBER_TEMPLATES! template <class T> inline T qobject_cast(const QObject *object) { #if !defined(QT_NO_MEMBER_TEMPLATES) && !defined(QT_NO_QOBJECT_CHECK) reinterpret_cast<T>(0)->qt_check_for_QOBJECT_macro(*reinterpret_cast<T>(object)); #endif return static_cast<T>(const_cast<const QObject *>(reinterpret_cast<T>(0)->staticMetaObject.cast(const_cast<QObject *>(object)))); }
Название: Re: Q_OBJECT-грабли в Qt4.3
Отправлено: Tonal от Август 29, 2007, 07:24
Вполне можно разделить поток и замыкание. struct GenericClosure { void run() = 0 }; template <class ObjT, class Parm1T, class RetT = void> struct ConcretClosure : GenericClosure { ConcretFunc(ObjT *object, RetT (ObjT::*function)(Parm1T), Parm1T parm): object_(object), function_(function), parm_(parm){} void run() {object_->*function_)(parm_);} RetT & retval() {return retval_;} private: ObjT *object_; RetT (ObjT::*function_)(Parm1T); Parm1T parm_; RetT retval_; };
class ThreadRun : public QThread { public: ThreadRun(GenericClosure* closure, *parent = NULL ) : QThread(parent), closure_(closure) {} ~ThreadRun(){if(isRunning())this->wait();} void run() {closure_->run();} GenericClosure* closure() {return closure_;} void msleep( unsigned long msecs ) {QThread::msleep( msecs ); } private: GenericClosure* closure_; };
Ну и приводить или через dynamic_cast (стандартный rtti) или static_cast, если типы тебе известны. Например, в твоём примере ThreadRun < MyWidget, QString, QString > * s_s_Thread = qobject_cast < ThreadRun < MyWidget, QString, QString > * > ( sender() );
qobject_cast заменяется на static_cast и по смыслу и по действию. ;) А если ты хочешь оставить проверку, которую он предоставляет, можно так: assert(dynamic_cast<ThreadRun < MyWidget, QString, QString > *>(sender())); ThreadRun < MyWidget, QString, QString > * s_s_Thread = static_cast < ThreadRun < MyWidget, QString, QString > * > ( sender() );
|