I am trying to develop a generic function which determines whether two QObjects are equal. In order for this to be possible, the functions being compared must have an 'equals' method that compares various function values in each and returns true if they are all equal. Slso, this 'equal' method must be declared with Q_INVOKABLE.
However, when I attempt to call invokeMethod for the 'equals' method, it fails an an error "QMetaObject::invokeMethod: No such method F1::equals(QObject*)(QObject*)" is displayed.
Here is my test project and files:
Project file:
CONFIG += c++11 console
CONFIG -= app_bundle
# The following define makes your compiler emit warnings if you use
# any feature of Qt which as been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
main.cpp
HEADERS += \
f1.h \
assert1.h
assert1.h
#ifndef ASSERT1_H
#define ASSERT1_H
#include <QObject>
#include <QDebug>
class Assert1 : public QObject
{
Q_OBJECT
public:
explicit Assert1(QObject *parent = nullptr) {}
static bool isEqual(QString msg, QObject* o1, QObject* o2)
{
if(o1 != nullptr && o2 != nullptr)
{
if(o1->metaObject()->className() != o2->metaObject()->className())
{
qDebug() << msg << " not same class type!";
return false;
}
const QMetaObject* metaObject =o1->metaObject();
int ix = metaObject->indexOfMethod(QMetaObject::normalizedSignature("equals(QObject *)"));
qDebug() << QMetaObject::normalizedSignature("equals(QObject *)");
if(ix == -1)
{
qDebug() << msg << tr("indexOfMethod(\"equals\") returns %1").arg(ix);
return false;
}
else
{
bool rslt = false;
if(!QMetaObject::invokeMethod(o1, QMetaObject::normalizedSignature("equals(QObject *)"),
Qt::DirectConnection,
Q_RETURN_ARG(bool, rslt),
Q_ARG(QObject*, o2)))
qDebug() << msg << tr("invoke method 'equals' failed for %1").arg(o1->metaObject()->className());
if(!rslt)
qDebug() << msg << tr(" objects not equal");
return false;
}
}
qDebug() << msg << "not equal";
}
signals:
public slots:
};
#endif // ASSERT1_H
f1.h
#ifndef F1_H
#define F1_H
#include <QObject>
#include <QDebug>
class F1 : public QObject
{
Q_OBJECT
public:
explicit F1(int p1, QString p2, QObject *parent = nullptr) : QObject(parent)
{
this->p1 = p1;
this->p2 = p2;
}
void setP1(int p) {this->p1 = p;}
void setP2(QString p) {this->p2 = p;}
Q_INVOKABLE bool equals(QObject* other)
{
if(qobject_cast<F1*>(other) != nullptr)
{
if(this->p1 != ((F1*)other)->p1)
return false;
if(this->p2 != ((F1*)other)->p2)
return false;
}
return true;
}
Q_INVOKABLE QString toString()
{
qDebug() << "p1 '" << p1 << " p2 = '" << p2 << "'";
}
signals:
public slots:
private:
int p1;
QString p2;
};
#endif // F1_H
main.cpp
#include <QCoreApplication>
#include "f1.h"
#include "assert1.h"
#include <QDebug>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
F1* tf1 = new F1(1, "1");
F1* tf2 = new F1(1, "a");
F1* tf3 = new F1(1, "a");
F1* tf4 = new F1(4, "abc");
qDebug() << "tf1->equals(tf4) returns: " << (tf1->equals(tf4)?"true":"false");
qDebug() << "tf2->equals(tf3) returns: " << (tf2->equals(tf3)?"true":"false");
Assert1::isEqual("should be equal", (QObject*)tf2, (QObject*)tf3);
//return a.exec();
}
running the test produces this output:
Debugging starts
tf1->equals(tf4) returns: false
tf2->equals(tf3) returns: false
"equals(QObject*)"
QMetaObject::invokeMethod: No such method F1::equals(QObject*)(QObject*)
"should be equal" "invoke method 'equals' failed for F1"
How do I get invokeMethod to work?