преобразование между std::string и QVariant (и наоборот) Qt5

Мне трудно преобразовать std::string в QVariant и QVariant обратно в std::string. В обоих случаях я получаю пустое значение (QVariant по умолчанию, точно так же, как он был инициализирован без параметров) и пустой std::string().

Это соответствующие части моего кода:

bool TestItemListModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
    // processing of other function arguments, checks, etc.
    (*myData)[row].setName(value.value<std::string>());
    // here I end up with ""
}

QVariant TestItemListModel::data(const QModelIndex &index, int role) const
{
    // again all the checks, etc.
    return QVariant::fromValue<std::string>((*myData)[row].getName());
}

Я нашел вопрос, похожий на этот, и именно так он должен был работать. Я также сделал дополнительную вещь, упомянутую в ответе, поэтому в моем main.cpp у меня есть это:

qRegisterMetaType<std::string>("std::string");

и в моем testitemlistmodel.h у меня есть это (до объявления класса):

Q_DECLARE_METATYPE(std::string)

Я использую Qt5.8.

РЕДАКТИРОВАТЬ

Я нашел источник для этого типа преобразования: http://www.qtcentre.org/threads/45922-best-way-to-extend-QVariant-to-support-std-string?p=208049#post208049. Теперь я только что понял, что он довольно старый и может больше не работать. Если это так, то как лучше всего это сделать?


person pzaj    schedule 25.06.2017    source источник
comment
Почему бы просто не преобразовать его в QString и позволить Qt позаботиться об этом за вас?   -  person MrEricSir    schedule 25.06.2017
comment
Нет ли значительных накладных расходов?   -  person pzaj    schedule 25.06.2017
comment
Это очень сложный вопрос, и только ваш профилировщик может сказать вам наверняка. Основные проблемы заключаются в том, сколько строк мы говорим, какова их длина и какую кодировку вы используете в своем std::string (что обычно зависит от платформы).   -  person MrEricSir    schedule 26.06.2017
comment
Я вижу, хорошо. У меня есть пользовательская модель ItemsModel, полученная из QAbstractListModel при поддержке std::vector<T>, где T содержит несколько членов std::string. преобразование делается в ItemsModel::data(...) [std::string -> QVariant], но что с ними происходит я не знаю. QVariant -> std::string выполняется в ItemsModel::setData(...), а QVariant здесь передается по константной ссылке. К сожалению, я не знаю, как это работает внутри, поэтому я не могу больше ничего сказать о том, как это используется экземпляром QListView, привязанным к этой модели.   -  person pzaj    schedule 26.06.2017
comment
Можете ли вы предоставить минимально воспроизводимый пример? Например, преобразовать стандартную строку в qvariant и обратно в простой тестовой функции и продемонстрировать отсутствие значения? В нынешнем виде у вас есть сложное приложение, в котором вы показали несколько строк кода, которые могут содержать или не содержать вашу проблему, используя указатели с неизвестными типами и множество неизвестных неизвестных.   -  person Yakk - Adam Nevraumont    schedule 26.06.2017
comment
@Yakk Я собирался сделать это, но как только я скомпилировал и запустил этот пример, он просто сработал (я взял тот, который я разместил по ссылке). Хотя я понимаю, что здесь могут быть проблемы с указателями и другими неизвестными, другие перечисленные решения (с использованием QSstring или QByteArray в качестве медианного типа) работают, как и ожидалось. Я предполагаю, что это как-то связано либо с макросом qRegisterMetaType, либо с макросом Q_DECLARE_METATYPE. Вместо этого я решил использовать QByteArray, который, похоже, отлично работает и обеспечивает надежность, которую я не могу воспроизвести с моим решением, опубликованным здесь.   -  person pzaj    schedule 26.06.2017


Ответы (1)


Как насчет использования QString в качестве медианного типа? Это немного накладно, но гораздо проще поддерживать код:

/* std::string to QVariant */ {
    std::string source { "Hello, World!" };
    QVariant destination;        

    destination = QString::fromStdString(source);
    qDebug() << destination;
}

/* QVariant to std::string */ {
    QVariant source { "Hello, World!" };
    std::string destination;

    destination = source.toString().toStdString();
    qDebug() << destination.c_str();
}

QVariant имеет конструктор для QString, который можно построить из std::string, а объект QVariant можно преобразовать в QString, который можно преобразовать в std::string.


Другой вариант — использовать QByteArray вместо QString, который просто копирует ваш std::string посимвольно и не преобразует его в Unicode, как это делает QString:

// std::string to QVariant
myQVariant.setValue<QByteArray>(myStdString.c_str());

// std::string to QVariant
myStdString = myQVariant.value<QByteArray>().constData();
person Akira    schedule 25.06.2017
comment
Я думал об этом, и вот как я это сделал, чтобы заставить его работать на данный момент, но я думаю, что использование QString приводит к некоторым накладным расходам, не так ли? Поэтому я ищу способ избежать этого, хотя, если я ничего не найду в ближайшее время, я просто буду использовать QString. - person pzaj; 25.06.2017
comment
Поскольку QString хранит строки в формате Unicode, у вас будет одно преобразование из std::string в QString и наоборот. - person Akira; 26.06.2017
comment
Я предполагаю, что использование QByteArray здесь будет быстрее (мой std::string содержит только английские буквы и цифры, если это имеет значение). Я предполагаю, что второй комментарий о преобразовании - просто опечатка :) Спасибо, я обязательно воспользуюсь одним из них (в зависимости от того, какой из них быстрее), если не найду прямого решения. - person pzaj; 26.06.2017
comment
Использование QByteArray быстрее, потому что оно обрабатывает const char* внутри вашего std::string как необработанные данные и не имеет дело с его содержимым. - person Akira; 26.06.2017
comment
Хорошо, я тоже не уверен, есть ли разница, но я только что узнал, что вы можете звонить myVariant.toByteArray().constData(). Мне это кажется более явным. - person pzaj; 26.06.2017
comment
myVariant.toByteArray() и myVariant.value<QByteArray>() в итоге делают то же самое. - person Akira; 26.06.2017