Страницы

Поиск по вопросам

суббота, 15 июня 2019 г.

Как создать вспомогательный вложенный класс от QObject в шаблонном классе?

Захотел использовать сигналы/слоты на не-QObject'овом классе. Выкидываю такой фортель:
class Receiver : public QObject { Q_OBJECT public:
public slots: void onValueChanged(int newValue) { qDebug() << "the new value is:" << newValue; } };
class Itm { public: class Buddy;
Itm();
void setValue(int newValue);
Buddy *buddy() const { return _buddy; }
private: int _value; Buddy *_buddy; Receiver *_receiver; };
class Itm::Buddy : public QObject { Q_OBJECT public: void emitValueChanged(int newValue) { emit valueChanged(newValue); }
signals: void valueChanged(int newValue); };
В cpp:
Itm::Itm() : _value(0) { _buddy = new Buddy(); _receiver = new Receiver(); QObject::connect(_buddy, &Itm::Buddy::valueChanged, _receiver, &Receiver::onValueChanged); }
void Itm::setValue(int newValue) { if (_value != newValue) { _value = newValue; _buddy->valueChanged(newValue); } }
Все нормально срабатывает.
Теперь в основном вопрос такой - как сделать тоже самое на шаблоне класса
Попытка 1:
template class Itm { template class Buddy;
...
private: ValueType _value; Buddy *_buddy; };
template class Itm::Buddy : public QObject { Q_OBJECT public: void emitValueChanged(ValueType newValue) { emit valueChanged(newValue); }
signals: void valueChanged(ValueType newValue); };
получаю ошибку:
too few template-parameter-lists
Не понятно, почему ему мало? Ладно, не буду умничать, может избегу проблем если создам nested class. Попытка 2. Описываю Buddy внутри тела класса Itm :
template class Itm { class Buddy : public QObject { Q_OBJECT public: void emitValueChanged(ValueType newValue) { emit valueChanged(newValue); }
signals: void valueChanged(ValueType newValue); };
...
private: ValueType _value; Buddy *_buddy; };
Получаю:
Meta object features not supported for nested classes
Думаю, лучше возвратиться к первому варианту, но как избежать ошибок?
Или вообще избежать шаблона и использовать QVariant?


Ответ

К сожалению так сделать не получится, потому как утилита moc не поддерживает ни шаблонные, ни вложенные классы.
Да, вы можете использовать QVariant или сделать несколько перегрузок для нужных слотов и сигналов. Перегрузку moc поддерживает.
Кроме того, сейчас можно подключать лямбда-функции в которых можно "замкнуть" указатель на объект. То есть, если вам не требуется обрабывать стандартные сигналы QObject (например destroyed) от вашего Buddy, то это вам подойдет. При этом Buddy не обязательно должен быть QObject'ом. Как-то так примерно:
template<...> class Itm { template<...> class Buddy{ ... }; };
Item<...>::Buddy<...> * buddy = ...; connect(sender, &Sender::send, [buddy](){buddy->receive();});
Вот, на хабре было интересное обсуждение по теме (читайте коментарии).

Комментариев нет:

Отправить комментарий