Russian Qt Forum
Ноябрь 24, 2024, 12:31 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Q_OBJECT-грабли в Qt4.3  (Прочитано 3896 раз)
bigirbis
Гость
« : Август 28, 2007, 10:26 »

В Qt4.3 стало обязательным объявления макроса Q_OBJECT в классе, для того, чтобы можно было использование приведение qobject_cast <>. Но при этом не разрешается использование данного макроса в шаблонных классах. А код уже написан и работает... Грустный.

Есть какие-нибудь красивые методы выхода из данной ситуации?
Записан
Dodge
Гость
« Ответ #1 : Август 28, 2007, 15:29 »

Эти "Грабли" выросли из нового механизма генерации метаданных, и на мой это взгляд очень даже ничего система, ноги у нее растут скорей всего от QtScript, так что решайте задачу иным способом.
Насчет шаблонов выхода нет, т.к. Q_OBJECT макрос для мок, а моку глубоко плевать на шаблоны, он их не понимает.
И по подробнее про qobject_cast, в чем проблема?... лучше кусок кода.

Записан
bigirbis
Гость
« Ответ #2 : Август 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() );
Записан
Dodge
Гость
« Ответ #3 : Август 28, 2007, 15:45 »

...
Интересное решение, я об этом не подумал...

З.Ы. Еще можно попробовать сделать прототип, либо через макросы, получится "псевдо шаблон"  Веселый
Записан
vaprele07
Гость
« Ответ #4 : Август 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))));
}
Записан
Tonal
Гость
« Ответ #5 : Август 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() );
« Последнее редактирование: Август 29, 2007, 07:32 от Tonal » Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.049 секунд. Запросов: 21.