0
votes

I'm trying to subclass QQueue in order to add some functionality. Actually, I wasn't able to subclass but because the code is very short I rewrote my own implementation:

#ifndef MYQUEUE_H
#define MYQUEUE_H

#include <QObject>
#include <QtCore/qlist.h>

QT_BEGIN_NAMESPACE

template <class T>
class MyQueue : public QList<T>
{
Q_OBJECT

public:
    // compiler-generated special member functions are fine!
    inline void swap(MyQueue<T> &other) Q_DECL_NOTHROW { QList<T>::swap(other); } // prevent QList<->QQueue swaps
#ifndef Q_QDOC
    // bring in QList::swap(int, int). We cannot say using QList<T>::swap,
    // because we don't want to make swap(QList&) available.
    inline void swap(int i, int j) { QList<T>::swap(i, j); }
#endif
    inline void enqueue(const T &t) { QList<T>::append(t); emit enqueued(); }
    inline T dequeue() { return QList<T>::takeFirst(); }
    inline T &head() { return QList<T>::first(); }
    inline const T &head() const { return QList<T>::first(); }

signals:
    void enqueued();
};

QT_END_NAMESPACE

#endif // MYQUEUE_H

Basically, it emits a signal whenever something is enqueued. I don't know the correct syntax to bind that signal to a slot:

MyQueue<QString> queue;
connect(&queue, &MyQueue::enqueued, this, &MainWindow::process_queue);

error: 'template class MyQueue' used without template parameters connect(&queue, &MyQueue::enqueued, this, &MainWindow::process_queue); ^

It says that I'm using MyQueue (that is a template class) without specifying the template parameters (QString).

I tried to add it but I did in a wrong way:

connect(&queue, &MyQueue<QString>::enqueued, this, &MainWindow::process_queue);

error: no matching function for call to 'MainWindow::connect(MyQueue, void (MyQueue::)(), MainWindow*, void (MainWindow::*)())'

What's the right syntax to connect such a signal?

2
I don't think your approach will work. Apart from template class, if you want to use signals/slots you have to use them with QObjects, or its subclasses.vahancho
Why can't MyQueue inherit from a non-template base class and put the required signal in the base class?G.M.
Do you mean a sort of wrapper that adds the required signals? It could be an acceptable workaround.Mark

2 Answers

2
votes

uses moc for their signal and slot connections; which does not support templates. If you're interested in rationale you can read more about this decision here: http://doc.qt.io/qt-5/why-moc.html

That said, all the functionality that you've shown in your example is availible in a QStringList so you may consider it as an option in this instance.

2
votes

As per my comment... you could probably have MyQueue inherit from a suitable base class that has the required signals.

class MyQueueBase: public QObject {
  Q_OBJECT;
public:
  virtual ~MyQueueBase ()
    {}
signals:
  void enqueued();
};

Then MyQueue becomes...

template<class T>
class MyQueue: public MyQueueBase,
               public QList<T>
{
public:

  /*
   * All as before but without the signal declaration.
   */
};

Code using the above can connect either to the base class or the derived class...

connect(&queue, &MyQueueBase::enqueued, this, &MainWindow::process_queue);
connect(&queue, &MyQueue<QString>::enqueued, this, &MainWindow::process_queue);