QVariant, удерживающий сравнение QSet <QString>, не работает должным образом, в то время как голый QSet <QString>работает нормально - PullRequest
0 голосов
/ 06 апреля 2020

У меня есть QSet<QString>, который я храню в QVariant, а затем пытаюсь сравнить его с идентичным объектом. Хотя QSet<QString> сравнение работает, это уже не тот случай, когда они заключены в QVariant. Есть идеи или обходные пути? Мне нужно сравнить QVariant в модульных тестах с QCOMPARE():

    QSet<QString> s1({"str"});
    QSet<QString> s2({"str"});

    QVariant v1;
    QVariant v2;

    v1.setValue(s1);
    v2.setValue(s2);

    qDebug() << QString::number(v1 == v2); // 0
    qDebug() << QString::number(s1 == s2); // 1
    qDebug() << QString::number(s1.value<QSet<QString>>() == s2.value<QSet<QString>>()); // 1

1 Ответ

3 голосов
/ 06 апреля 2020

Это можно заставить работать, но оказывается, что есть немного ручного труда. Из документации QVariant::operator== ...

Предупреждение : чтобы эта функция работала с пользовательским типом, зарегистрированным в qRegisterMetaType (), ее операторе сравнения должен быть зарегистрирован с помощью QMetaType :: registerComparators ()

Даже если qRegisterMetaType() не использовался в этом случае, похоже, что QMetaType::registerComparators() все еще нужно вызывать. documentation для этого дополнительно указывает, что для типа T успешный вызов QMetaType::registerComparators<T>() "...requires T to have both an operator== and an operator<". В этом случае QSet уже имеет оператор равенства, но не operator<, поэтому его необходимо реализовать. Соединение битов дает ...

#include <iostream>
#include <QSet>
#include <QString>
#include <QVariant>

template<typename T>
bool operator< (const QSet<T> &a, const QSet<T> &b)
{
  auto ia = a.begin();
  auto ib = b.begin();
  while (true) {
    if (ia == a.end() || ib == b.end())
      return a.size() < b.size();
    if (*ia < *ib)
      return true;
    ++ia;
    ++ib;
  }
  return false;
}

int main ()
{
  QMetaType::registerComparators<QSet<QString>>();
  QSet<QString> s1({"str"});
  QSet<QString> s2({"str"});

  QVariant v1;
  QVariant v2;

  v1.setValue(s1);
  v2.setValue(s2);

  std::cout << (v1 == v2) << "\n";
  std::cout << (s1 == s2) << "\n";
  std::cout << (v1.value<QSet<QString>>() == v2.value<QSet<QString>>()) << "\n";
}

Основы c, тестирование дает результат ...

1
1
1
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...