Russian Qt Forum
Апрель 23, 2024, 15:49 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: Указатель/ссылка на содержимое QVariant  (Прочитано 12326 раз)
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« : Февраль 11, 2019, 13:11 »

Добрый день

Пример: в QVariant хранится std::vector (ну конечно зарегистировался Q_DECLARE_METATYPE). Теперь я хочу добавлять/удалять/менять эл-ты этого вектора. Не нашел как получить указатель или ссылку на данные хранимые в QVariant. Выходит всякий раз нужно перезаливать весь вектор Плачущий

Это нормально или я плохо искал? Если нормально, то каковы мотивы такого ограничения?

Спасибо
Записан
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3258


Просмотр профиля
« Ответ #1 : Февраль 11, 2019, 13:53 »

Да, это нормально, в мире без исключений метод, возвращающий ссылку, не может вернуть ошибку, если запрошенный тип не совпадает с тем, что реально лежит в QVariant. Только покрашить приложение с std::terminate.
Ну и о5 же всегда можно положить шаред_птр на вектор=)
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #2 : Февраль 11, 2019, 15:38 »

Ну и о5 же всегда можно положить шаред_птр на вектор=)
Хорошо, пример: вот есть член какого-то класса который

а) шарится
б) может иметь содержимое разных типов

Как "давить эти 2 окурка одновременно" ?
Записан
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3258


Просмотр профиля
« Ответ #3 : Февраль 11, 2019, 15:54 »

шаред_птр на вариант? ссылка на вариант?
Записан
ssoft
Программист
*****
Offline Offline

Сообщений: 579


Просмотр профиля
« Ответ #4 : Февраль 11, 2019, 19:55 »

QVariant имеет implicit shared реализацию, как в прочем QByteArray, QString, QList и т.п. а это значит, что хранить ссылки и указатели на внутренние данные - это бомба с замедленным действием. В любой момент внутреннее значение может стать другим после неявной операции detach. Такими ссылками нужно пользоваться ооочень аккуратно.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #5 : Февраль 12, 2019, 10:53 »

QVariant имеет implicit shared реализацию, как в прочем QByteArray, QString, QList и т.п.
По-моему никакой имплисит шары сам QVariant не имеет, это 12 байт, 8 для хранения данных (напрямую или указатель) + тип по которому спрыгивает на базовый класс с виртуалами, Используется тот же паттерн что и в boost::any (и вероятно std::any), только базовый класс "один на тип", отсюда необходимость регистрировать.

а это значит, что хранить ссылки и указатели на внутренние данные - это бомба с замедленным действием. В любой момент внутреннее значение может стать другим после неявной операции detach. Такими ссылками нужно пользоваться ооочень аккуратно.
Ну если внутри сидит имплист контейнер и брать константный указатель на его данные - то да. Но для QVariant нет вообще никакого  "доступа к содержимому"

шаред_птр на вариант? ссылка на вариант?
По сути нужна очень простая вещь - шарить вариант. Хотел так
Код
C++ (Qt)
typedef QSharedPointer<QVariant> TSharedVar;
И заряжать вариант нужным контейнером. Но доступа к эл-там контейнера нет, поэтому не годится. Сделать наоборот почему-то не допер  Улыбающийся
Код
C++ (Qt)
typedef QSharedPointer<MyVector> TSharedVec;
QVariant v;
 
// заряжаем вариант
v.setValue(TSharedVec());
...
// получаем ссылку на вектор данных
TSharedVec sh= v.value<TSharedVec>();
if (sh.isNull()) throw;
MyVector & vec = *sh.data();
 
// оедактируем вектор
vec.resize(10);
 
Все вполне хорошо - и вариант есть и шарится. Не хватает одной вещи - сделать копию данных (в общем виде, не влезая в разборки с конкретными типами). Напр в первом случае это легко
Код
C++ (Qt)
typedef QSharedPointer<QVariant> TSharedVar;
TSharedVar sh;
...
sh.reset(new QVariant(*(sh->data()));
И каким бы ни было содержимое варианта - он скопируется корректно. А во втором случае получим еще один шаред ссылающийся на те же данные. Ну ладно, переживу сввитчами.
Записан
ssoft
Программист
*****
Offline Offline

Сообщений: 579


Просмотр профиля
« Ответ #6 : Февраль 12, 2019, 12:35 »

QVariant имеет implicit shared реализацию, как в прочем QByteArray, QString, QList и т.п.
По-моему никакой имплисит шары сам QVariant не имеет, это 12 байт, 8 для хранения данных (напрямую или указатель) + тип по которому спрыгивает на базовый класс с виртуалами, Используется тот же паттерн что и в boost::any (и вероятно std::any), только базовый класс "один на тип", отсюда необходимость регистрировать.
https://doc.qt.io/qt-5/implicit-sharing.html
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #7 : Февраль 12, 2019, 13:34 »

Ну вот, докатились до "тыц ссылкой" Улыбающийся  Возможно Вы имели ввиду что QVariant понимает что хранит тип с имплисит шарой, но об этом речь не идет (std::vector). Сам по себе QVariant НЕ шарится
Записан
ssoft
Программист
*****
Offline Offline

Сообщений: 579


Просмотр профиля
« Ответ #8 : Февраль 12, 2019, 16:12 »

Ну вот, докатились до "тыц ссылкой" Улыбающийся  Возможно Вы имели ввиду что QVariant понимает что хранит тип с имплисит шарой, но об этом речь не идет (std::vector). Сам по себе QVariant НЕ шарится
QVariant шарится))), и об этом явно написано в документации "тыц ссылкой", где приведена таблица классов Qt, использующих implicit shared.
QVariant может хранить практически любой copyable тип данных, и совершенно не догадывается о том какой он, с имплисит шарой или без.
Технических особенностей, почему бы не предоставить доступ к внутреннему содержимому, как, например, для QByteArray, никаких нет. Для std::any имеется std::any_cast< MyType & >.
Из-за отсутствия таких методов, QVariant постоянно использует копирование внутренних данных (fromValue/value), что приводит не редко к существенным потерям производительности.
Записан
ViTech
Гипер активный житель
*****
Offline Offline

Сообщений: 858



Просмотр профиля
« Ответ #9 : Февраль 12, 2019, 16:50 »

Ну вот, докатились до "тыц ссылкой" Улыбающийся  Возможно Вы имели ввиду что QVariant понимает что хранит тип с имплисит шарой, но об этом речь не идет (std::vector). Сам по себе QVariant НЕ шарится
QVariant шарится))), и об этом явно написано в документации "тыц ссылкой", где приведена таблица классов Qt, использующих implicit shared.

Можно такой ссылкой тыцнуть, и по коду выяснять, шарится там что-нибудь или нет Улыбающийся. Хотя может сегодня оно шарится, а завтра уже нет (реализация поменялась).

В исходниках можно ещё метод data() заметить, который для внутреннего пользования. Но если очень хочется, то можно и попользовать (на свой страх и риск).
Записан

Пока сам не сделаешь...
ssoft
Программист
*****
Offline Offline

Сообщений: 579


Просмотр профиля
« Ответ #10 : Февраль 12, 2019, 21:42 »

Можно такой ссылкой тыцнуть, и по коду выяснять ...
В исходниках можно ещё метод data() заметить, который для внутреннего пользования. Но если очень хочется, то можно и попользовать (на свой страх и риск).

Всегда поражала такая куча кода))). Более 5 тыс. строк  Шокированный Все можно сделать намного меньшими усилиями.
Записан
Old
Джедай : наставник для всех
*******
Online Online

Сообщений: 4349



Просмотр профиля
« Ответ #11 : Февраль 12, 2019, 21:46 »

Всегда поражала такая куча кода))). Более 5 тыс. строк  Шокированный Все можно сделать намного меньшими усилиями.
Легаси же. Улыбающийся
Сейчас можно, но когда закладывался QVariant шаблоны были в зачаточном состоянии. Улыбающийся
Записан
ssoft
Программист
*****
Offline Offline

Сообщений: 579


Просмотр профиля
« Ответ #12 : Февраль 13, 2019, 08:04 »

Всегда поражала такая куча кода))). Более 5 тыс. строк  Шокированный Все можно сделать намного меньшими усилиями.
Легаси же. Улыбающийся
Сейчас можно, но когда закладывался QVariant шаблоны были в зачаточном состоянии. Улыбающийся

Обычно да). Но в данном случае не так. Из-за ограничений QVariant, пришлось реализовать собственный аналог ещё в 2009.
Весь функционал Qt и даже больше (с сериализацией, имплисит шарой и преобразованием пользовательских типов друг в друга) уместился ~1000..1500 строк.
Сейчас как раз подумываю о рефакторинге на новый стандарт). Наверное еще меньше получится).
Записан
ViTech
Гипер активный житель
*****
Offline Offline

Сообщений: 858



Просмотр профиля
« Ответ #13 : Февраль 13, 2019, 11:16 »

Всегда поражала такая куча кода))). Более 5 тыс. строк  Шокированный Все можно сделать намного меньшими усилиями.

Там документации примерно половина, и многовато возни со встроенными и своими кутешными типами. Обилие нешаблонных методов toSomeType() тоже свой вклад вносит Улыбающийся.

Сейчас как раз подумываю о рефакторинге на новый стандарт). Наверное еще меньше получится).

Рефакторинга вида:
Код
C++ (Qt)
#include <variant>
// or
#include <any>
не будет достаточно? Улыбающийся
Записан

Пока сам не сделаешь...
ssoft
Программист
*****
Offline Offline

Сообщений: 579


Просмотр профиля
« Ответ #14 : Февраль 13, 2019, 12:09 »

Рефакторинга вида:
Код
C++ (Qt)
#include <variant>
// or
#include <any>
не будет достаточно? Улыбающийся

 Смеющийся Смеющийся Смеющийся

Сам тип, конечно , достаточно будет заменить на std::any) (но только с С++17).
Но там еще обвязка по динамической работе с типами и регистрации произвольной функциональности (кастование и преобразование типов, фабричные методы, сериализация и определенная пользователем любая другая).
Записан
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.138 секунд. Запросов: 22.