Russian Qt Forum
Апрель 19, 2024, 05:31
Добро пожаловать,
Гость
. Пожалуйста,
войдите
или
зарегистрируйтесь
.
Вам не пришло
письмо с кодом активации?
1 час
1 день
1 неделя
1 месяц
Навсегда
Войти
Начало
Форум
WIKI (Вики)
FAQ
Помощь
Поиск
Войти
Регистрация
Russian Qt Forum
>
Forum
>
Программирование
>
С/C++
>
Итераторы
Страниц:
1
[
2
]
3
4
...
6
Вниз
« предыдущая тема
следующая тема »
Печать
Автор
Тема: Итераторы (Прочитано 26395 раз)
Авварон
Джедай : наставник для всех
Offline
Сообщений: 3258
Re: Итераторы
«
Ответ #15 :
Февраль 01, 2021, 17:14 »
можно просто перегрузить функцию для ссылки и указателя без шаблонов=)
Код:
void foo(Type &t) {...}
void foo(Type *t) {foo(*t); }
Записан
Igors
Джедай : наставник для всех
Offline
Сообщений: 11445
Re: Итераторы
«
Ответ #16 :
Февраль 03, 2021, 07:47 »
Цитата: Авварон от Февраль 01, 2021, 17:14
можно просто перегрузить функцию для ссылки и указателя без шаблонов=)
Код:
void foo(Type &t) {...}
void foo(Type *t) {foo(*t); }
Не уловил идею
Записан
Fregloin
Супер
Offline
Сообщений: 1025
Re: Итераторы
«
Ответ #17 :
Февраль 15, 2021, 13:08 »
Вам уже указали решение вашей пробелмы - std::advance
Записан
Igors
Джедай : наставник для всех
Offline
Сообщений: 11445
Re: Итераторы
«
Ответ #18 :
Февраль 15, 2021, 14:13 »
Цитата: Fregloin от Февраль 15, 2021, 13:08
Вам уже указали решение вашей пробелмы - std::advance
"А можно пример?"
Потому что не вижу каким боком здесь поможет advance
И что там за "плохо скрываемое раздражение"?
Нет удобного решения - ну у меня его тоже нет.
Записан
Racheengel
Джедай : наставник для всех
Offline
Сообщений: 2679
Я работал с дискетам 5.25 :(
Re: Итераторы
«
Ответ #19 :
Апрель 15, 2021, 12:02 »
Навеяло:
Джун: так, сейчас по быстрому наговнокодим, так, ну скомпилилось, ну вроде не падает... иногда... фух, в продакшен.
Мидл: так, что эти джуны там наваяли, ой блин, говнокод, лапша, нет структуры и ПолётаМысли... Ну ща тут абстрактную шаблонную фабрику прикрутим, там визитор, тут обсервер... 95 из 100 тестов прошло, значит уже хорошо, эй, менеджер, готово!
Синьйор: так, блин, что за GOFнокод... Фабрики в лес, визиторы в лес, оставим пару классов, чтобы KISS и иже с ним... Ага, раз в 50 быстрее работает... готово
Тимлид: народ, давайте-ка код ревью по быстрому проведём, а то отдавать скоро.
Начальник разработки: так, что там в задаче сказано? А, найти площадь прямоугольника. Где там мой калькулятор...
Записан
What is the 11 in the C++11? It’s the number of feet they glued to C++ trying to obtain a better octopus.
COVID не волк, в лес не уйдёт
AkonResumed
Чайник
Offline
Сообщений: 81
Re: Итераторы
«
Ответ #20 :
Апрель 19, 2021, 22:51 »
Цитировать
struct CBigClass {
...
QList<CData> mData;
QSet<CData *> mSelection;
...
};
Я бы сделал так:
Код:
struct CBigClass {
...
QList<CData> mData;
QSet<std::reference_wrapper<CData>> mSelection;
...
};
Теперь тип элемента в контейнерах, можно сказать, одинаковый.
Если QSet<CData *> mSelection; нужно оставить, то сделайте zero-cost адаптер, чтобы оперировать ссылками, а не указателями:
Код:
struct CBigClass {
...
QSet<std::reference_wrapper<CData>>& mSelectionAsRefs()
{
static_assert(sizeof(CData*) == sizeof(std::reference_wrapper<CData>));
return reinterpret_cast<QSet<std::reference_wrapper<CData>>&>(mSelection);
}
};
Итак, std::reference_wrapper внутренне реализован как указатель, но имеет семантику ссылки. Собственно, она часто и используется с контейнерами.
Теперь адаптер: он не имеет накладных расходов (ссовсем), поскольку размер std::reference_wrapper == размеру указателя, и мы жестко реинтерпретируем. Но равенство размеров не гарантируется (не уверен), поэтому мы это проверяем в compile-time static_assert-ом.
И еще. В вашем QSet<CData *> mSelection; могут быть нулевые указатели? Предполагаю - нет. Если указатель не может быть нулевым - используйте ссылку (во всех таких случаях). Читаемость и строгость кода же повышаются. Хотя, в плане читаемости - спорно (std::reference_wrapper<> - много букв
).
«
Последнее редактирование: Апрель 19, 2021, 22:55 от AkonResumed
»
Записан
Igors
Джедай : наставник для всех
Offline
Сообщений: 11445
Re: Итераторы
«
Ответ #21 :
Апрель 20, 2021, 11:00 »
Да, интересный приемчик с reference_wrapper, не знал, спасибо
Записан
AkonResumed
Чайник
Offline
Сообщений: 81
Re: Итераторы
«
Ответ #22 :
Апрель 20, 2021, 11:08 »
Не вопрос. Да и это делеко не последний писк моды - это c C++11.
Записан
Авварон
Джедай : наставник для всех
Offline
Сообщений: 3258
Re: Итераторы
«
Ответ #23 :
Апрель 20, 2021, 12:41 »
Цитата: AkonResumed от Апрель 19, 2021, 22:51
Код:
return reinterpret_cast<QSet<std::reference_wrapper<CData>>&>(mSelection);
Это UB
Записан
AkonResumed
Чайник
Offline
Сообщений: 81
Re: Итераторы
«
Ответ #24 :
Апрель 20, 2021, 14:24 »
Это не UB. В худшем (маловероятном) случае, это compile-time error. Потому что так перед грязным хаком (reinterpret_cast) идет
Код:
static_assert(sizeof(CData*) == sizeof(std::reference_wrapper<CData>));
что делает хак чистым. Прпосто вдумайтесь в смысл условия ассерта.
Если уж подходить совсем параноидально, то в теории UB возможен, но такая реализация std::reference_wrapper лишена практического смысла. Например, std::reference_wrapper хранит не исходный указатель, а смещенный на 5, например, или в форме инверсных битов.
«
Последнее редактирование: Апрель 20, 2021, 14:32 от AkonResumed
»
Записан
Old
Джедай : наставник для всех
Offline
Сообщений: 4349
Re: Итераторы
«
Ответ #25 :
Апрель 20, 2021, 14:45 »
Ну это все таки грязный хак.
А что если у QSet для указателей и нет разные специализации?
Записан
Авварон
Джедай : наставник для всех
Offline
Сообщений: 3258
Re: Итераторы
«
Ответ #26 :
Апрель 20, 2021, 15:04 »
Это UB, в общем случае нельзя делать reinterpret_cast между unrelated типами.
https://en.cppreference.com/w/cpp/language/reinterpret_cast
Цитировать
std::pair<int, int> and std::pair<const int, int> are
not
similar.
Компилятор предполагает что 2 ссылки/указателя на различные типы не могут ссылаться не одну область памяти (strict alias rule) и строит на этом оптимизации.
reinterpret_cast ломает это предположение - если компилятор тупенький и не оптимизирует, то это будет работать, если умный, то сломается. UB.
Записан
Авварон
Джедай : наставник для всех
Offline
Сообщений: 3258
Re: Итераторы
«
Ответ #27 :
Апрель 20, 2021, 15:09 »
Ну или более сложный пример, вы знаете что на вашей платформе sizeof(bool) == sizeof(int8_t) (ну или char).
Значит вы можете сделать
Код:
vector<bool> bools;
auto &chars = reinterpret_cast<vector<char>&>(bools);
?
Записан
AkonResumed
Чайник
Offline
Сообщений: 81
Re: Итераторы
«
Ответ #28 :
Апрель 20, 2021, 15:53 »
Цитата: Old от Апрель 20, 2021, 14:45
А что если у QSet для указателей и нет разные специализации?
Ах, таки вы меня подсекли! Про возможную специализацию внешнего типа я упустил. В данном случае специализации QSet нет, работать будет. Но в общем случае - да, это нужно учитывать.
Авварон,
Код:
vector<bool> bools;
auto &chars = reinterpret_cast<vector<char>&>(bools);
Как метко подметил Old, причина этого UB в специализации vector<bool>. Она хранит биты, а не байты.
По поводу strict alias rule и оптимизации (привет restrict poiners): А как вы соотнесете это с placement new(), например?
Записан
Авварон
Джедай : наставник для всех
Offline
Сообщений: 3258
Re: Итераторы
«
Ответ #29 :
Апрель 20, 2021, 16:03 »
Цитата: AkonResumed от Апрель 20, 2021, 15:53
Ах, таки вы меня подсекли! Про возможную специализацию внешнего типа я упустил. В данном случае специализации QSet нет, работать будет. Но в общем случае - да, это нужно учитывать.
Там внутри могут быть всякие traits которые для разных типов разные.
Но в любом случае, даже если битовое представление одинаковое, это UB.
Цитата: AkonResumed от Апрель 20, 2021, 15:53
По поводу strict alias rule и оптимизации (привет restrict poiners): А как вы соотнесете это с placement new(), например?
В чем проблема-то? Единственный валидный юзкейз reinterpret_cast между разными типами это каст к массиву байт (или void*) и обратно.
Компилятор знает что вон тот char buffer[] потенциально может алиаситься с вот этим указателем и сгенерит менее производительный код.
placement new как раз подпадает под это - буфер чаров может алиаситься (и делает это) с указателем на произвольный T.
А вот любые другие типы (например int* в double*) алиаситься не могут.
Записан
Страниц:
1
[
2
]
3
4
...
6
Вверх
Печать
« предыдущая тема
следующая тема »
Перейти в:
Пожалуйста, выберите назначение:
-----------------------------
Qt
-----------------------------
=> Вопросы новичков
=> Уроки и статьи
=> Установка, сборка, отладка, тестирование
=> Общие вопросы
=> Пользовательский интерфейс (GUI)
=> Qt Quick
=> Model-View (MV)
=> Базы данных
=> Работа с сетью
=> Многопоточное программирование, процессы
=> Мультимедиа
=> 2D и 3D графика
=> OpenGL
=> Печать
=> Интернационализация, локализация
=> QSS
=> XML
=> Qt Script, QtWebKit
=> ActiveX
=> Qt Embedded
=> Дополнительные компоненты
=> Кладовая готовых решений
=> Вклад сообщества в Qt
=> Qt-инструментарий
-----------------------------
Программирование
-----------------------------
=> Общий
=> С/C++
=> Python
=> Алгоритмы
=> Базы данных
=> Разработка игр
-----------------------------
Компиляторы и платформы
-----------------------------
=> Linux
=> Windows
=> Mac OS X
=> Компиляторы
===> Visual C++
-----------------------------
Разное
-----------------------------
=> Новости
===> Новости Qt сообщества
===> Новости IT сферы
=> Говорилка
=> Юмор
=> Объявления
Загружается...