7

Can I use a template type in any way as a slot or signal argument? As an example, I'm trying to define the following:

void exampleSignal(std::map<non_template_type_1,non_template_type_2> arg);
void exampleSlot(std::map<non_template_type_1,non_template_type_2> arg);

This results in the following during runtime:

QObject::connect: Cannot queue arguments of type 
    'std::map<non_template_type_1,non_template_type_2>'
(Make sure 'std::map<non_template_type_1,non_template_type_2>' 
    is registered using qRegisterMetaType().)

Trying to register std::map<non_template_type_1,non_template_type_2> with Q_DECLARE_METATYPE() results in compilation failure and apparently is not supported.

As a workaround, I'm using QVariantMap instead of std::map. But I really would like to know the correct way to solve this problem; one where it is not possible to modify the template classes.

Edit: I forgot to mention that the signal and slot are emitted and received in different threads. Apparently the runtime error doesn't occur in single-thread scenarios.

BartoszKP
  • 34,786
  • 15
  • 102
  • 130
Ayberk Özgür
  • 4,986
  • 4
  • 38
  • 58

3 Answers3

4

This works for me:

qRegisterMetaType< std::vector<float> >( "std::vector<float>" );
qRegisterMetaType< std::vector<int>   >( "std::vector<int>"   );
qRegisterMetaType< std::map<std::string,int64_t> >( "std::map<std::string,int64_t>" );
Diego Sánchez
  • 539
  • 2
  • 12
  • This is what worked for me. I had a `QVector`, and Qt refused to understand my `qRegisterMetaType>();`. It instead insisted on a name without scope of the template type. I.e. I had to say `qRegisterMetaType>("QVector");`, which finally persuaded it to work. – Ruslan May 21 '19 at 17:23
2

As explained in this thread you can try using a typedef, including the QMetaType header and then using both Q_DECLARE_METATYPE macro and the qRegisterMetaType function (as implied by this thread on a similar issue).

Community
  • 1
  • 1
BartoszKP
  • 34,786
  • 15
  • 102
  • 130
  • Actually, I confirmed it to work without `Q_DECLARE_METATYPE` so `qRegisterMetaType` seems enough along with a `typedef`. I don't know how safe it is to omit `Q_DECLARE_METATYPE` though. – Ayberk Özgür Oct 14 '14 at 15:47
1

There is no problem if you created the class like this and used the Qt moc compiler to create those QMetaObject's automatically:

class MyClass : public QObject
{
    Q_OBJECT
public:
    explicit MyClass(QObject *parent = 0)
        : QObject(parent)
    {
    }
public slots:
    void exampleSlot(std::map<non_template_type_1,non_template_type_2> arg);
signals:
    void exampleSignal(std::map<non_template_type_1,non_template_type_2> arg);
};

Of course you need to include QObject and wherever std::map is located at.

msrd0
  • 7,816
  • 9
  • 47
  • 82
  • Thank you, indeed this seems possible in a single-thread setting, but I forgot to mention that it is not the case with me. – Ayberk Özgür Oct 14 '14 at 15:08
  • @AyberkÖzgür So whats the problem? The signal will always be received in Qt's Event Handler Thread – msrd0 Oct 14 '14 at 15:09
  • It's not. See QueuedConnection in http://qt-project.org/doc/qt-4.8/threads-qobject.html#signals-and-slots-across-threads. – Ayberk Özgür Oct 14 '14 at 15:17