Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

How to make a template?



  • Hi, I want to create a template that can be used to emit different types of data but with same signal name. For example, dataReady(T data); is my signal and I wish this signal can emit data that is of type int, bytearray and some user-defined type. I am wondering how can I achieve this?


  • Qt Champions 2017

    @Christina123 said in How to make a template?:

    The problem that I encounter is that when I try to overload the a signal function, an error occurs saying error: no matching member function for call to 'connect'.

    Yes, that's expected. How should the compiler know which of the two overloads it's supposed to pick? You have to guide it:

    QObject::connect(rthread, QOverload<TypesOfTheArguments>::of(&ReceiverThread::sendData), this, &Receiver::readData);
    

    I will very much want to use QVariant for my code, but unfortunately, I have a user-defined type which is vector<QPainterPath> and this is not supported by QVariant. So, QVariant may not be a feasible way.

    Custom types can be put in a variant, but it's involved (somewhat). They need to be copyable and constructible, and also they need to be declared as metatypes.



  • @Christina123
    While you wait for a better C++-er than I to answer about the template approach....

    ...Have you considered whether one signal with a QVariant argument would suit your situation?

    Nothing wrong with dedicated-type-templates approach, just which would you prefer?



  • Moc doesn't understand templates.

    Verdigris does, and might work for this use case. The macros is uses are different.
    Moc-ng does as well, and I think is supposed to be source-compatible with moc.

    I haven't used either one.


  • Qt Champions 2017

    @Christina123 said in How to make a template?:

    I am wondering how can I achieve this?

    If the class is a template, then it's a different class for each one instantiation (i.e. QVector<int> is different class from QVector<double>). If the function is a template, then it's a different function for each instantiation. So basically what you're asking (asuming template classes) is how can I connect a signal no matter from what QObject derived class it comes ... well, you can't, typically.

    You can have different overloads, however, or you can use QVariant. Mixing QObject and templates is rather dubious (due to the way the QObject is supposed to work) so that's why it's not had support in moc for so long ...



  • Hi, thank you for replying to my answers. The problem that I encounter is that when I try to overload the a signal function, an error occurs saying error: no matching member function for call to 'connect'. My code is below:

    signals:
        void sendData(MyPath data); \\ user-defined data type
        void sendData(QSize data);
    
    connect(rthread, &ReceiverThread::sendData, this, &Receiver::readData);
    

    I will very much want to use QVariant for my code, but unfortunately, I have a user-defined type which is vector<QPainterPath> and this is not supported by QVariant. So, QVariant may not be a feasible way.


  • Qt Champions 2017

    @Christina123 said in How to make a template?:

    The problem that I encounter is that when I try to overload the a signal function, an error occurs saying error: no matching member function for call to 'connect'.

    Yes, that's expected. How should the compiler know which of the two overloads it's supposed to pick? You have to guide it:

    QObject::connect(rthread, QOverload<TypesOfTheArguments>::of(&ReceiverThread::sendData), this, &Receiver::readData);
    

    I will very much want to use QVariant for my code, but unfortunately, I have a user-defined type which is vector<QPainterPath> and this is not supported by QVariant. So, QVariant may not be a feasible way.

    Custom types can be put in a variant, but it's involved (somewhat). They need to be copyable and constructible, and also they need to be declared as metatypes.



  • Hi, yes I understand my problem. So I change my code according to the code you provide connect(rthread, QOverload<MyPath,QSize>::of(&ReceiverThread::sendData), this, &Receiver::readData);, but somehow it gives me another error no matching function for call to 'of'.


  • Qt Champions 2017

    @Christina123 said in How to make a template?:

    QOverload<MyPath,QSize>

    Choose one of the two. You select a single overload to connect, you can't have them both at the same time.



  • Hi, just want to clarify a little bit more. So, if I want to overload either signals or slots, I will have to use QOverload<>::of(...) to ensure that the moc knows which function to use. Is that correct?


  • Qt Champions 2017

    Yes, but if we are talking specifically for Qt6 then you should use the qOverload<ArgumentTypes> function, as Qt6 already requires c++17 support. For Qt5 you may need to revert to QOverload<>::of depending on your compiler.

    https://doc-snapshots.qt.io/qt6-dev/qtglobal.html#qOverload



  • Thank you! This has been very helpful to me :)


Log in to reply