Qt/Qml и перегрузки метода

Просто наткнулся на странное поведение Qt-структуры, вызывая перегруженные методы С++ из Qml и пытаясь понять причину этого. Скажем, у меня есть класс QList<QVariant> -like со следующими методами:

...
Q_SLOT void append(const QVariant &item);
Q_SLOT void append(const QVariantList &items);
Q_SLOT void insert(int index, const QVariant &item);
Q_SLOT void insert(int index, const QVariantList &items);
...

QML:

onclicked: {
  var itemCount = myListObject.size();
  myListObject.insert(itemCount, "Item " + (itemCount + 1));
}

Qt каким-то образом решает вызвать перегрузку void insert(int index, const QVariantList &items) с аргументом items, установленным в a null QVariant пустым QVariantList вместо перегрузки void insert(int index, const QVariant &item) с QString, завернутым в QVariant.

Теперь, если я изменю порядок объявлений следующим образом, он работает как ожидалось:

Q_SLOT void insert(int index, const QVariantList &items);
Q_SLOT void insert(int index, const QVariant &item);

Я не мог найти что-либо в документации по Qt-структуре относительно порядка объявлений и как это влияет на способ решения методов во время вызова.

Может кто-нибудь объяснить? Спасибо.

Ответ 1

Этот вопрос связан с перегрузкой в ​​JavaScript. Как только вы узнаете об этом, вы понимаете причину "странного поведения" вашего кода. Просто взгляните на Перегрузка функций в Javascript - лучшие практики.

В нескольких словах я рекомендую вам сделать следующее: поскольку вы можете использовать переменные QVariant с обеих сторон (QML и Qt/С++) - передать вариант как параметр и обработать его на стороне Qt/С++, поскольку вы желание.

Вы можете использовать что-то вроде этого:

Ваш класс С++ создан и передан в QML (например, как setContextProperty("TestObject", &tc)):

public slots:
    Q_SLOT void insert(const int index, const QVariant &something) {
        qDebug() << __FUNCTION__;
        if (something.canConvert<QString>()) {
            insertOne(index, something.toString());
        } else if (something.canConvert<QStringList>()) {
            insertMany(index, something.toStringList());
        }
    }

private slots:
    void insertOne(int index, const QString &item) {
        qDebug() << __FUNCTION__ << index << item;
    }

    void insertMany(int index, const QStringList &items) {
        qDebug() << __FUNCTION__ << index << items;
    }

Где-то в вашем QML:

Button {
    anchors.centerIn: parent
    text: "click me"
    onClicked: {
        // Next line will call insertOne
        TestObject.insert(1, "Only one string")
        // Next line will call insertMany
        TestObject.insert(2, ["Lots", "of", "strings"])
        // Next line will call insertOne
        TestObject.insert(3, "Item " + (3 + 1))
        // Next line will call insertOne with empty string
        TestObject.insert(4, "")
        // Next line will will warn about error on QML side:
        // Error: Insufficient arguments
        TestObject.insert(5)
    }
}