Захотел использовать сигналы/слоты на не-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
...
private:
ValueType _value;
Buddy
template
signals:
void valueChanged(ValueType newValue);
};
получаю ошибку:
too few template-parameter-lists
Не понятно, почему ему мало? Ладно, не буду умничать, может избегу проблем если создам nested class.
Попытка 2. Описываю Buddy внутри тела класса Itm :
template
signals:
void valueChanged(ValueType newValue);
};
...
private:
ValueType _value;
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();});
Вот, на хабре было интересное обсуждение по теме (читайте коментарии).
Комментариев нет:
Отправить комментарий