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

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

Страниц: 1 [2] 3 4 ... 6   Вниз
  Печать  
Автор Тема: Итераторы  (Прочитано 32089 раз)
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3260


Просмотр профиля
« Ответ #15 : Февраль 01, 2021, 17:14 »

можно просто перегрузить функцию для ссылки и указателя без шаблонов=)

Код:
void foo(Type &t) {...}
void foo(Type *t) {foo(*t); }
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #16 : Февраль 03, 2021, 07:47 »

 
можно просто перегрузить функцию для ссылки и указателя без шаблонов=)

Код:
void foo(Type &t) {...}
void foo(Type *t) {foo(*t); }
Непонимающий Не уловил идею
Записан
Fregloin
Супер
******
Offline Offline

Сообщений: 1025


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

Вам уже указали решение вашей пробелмы - std::advance
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


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

Вам уже указали решение вашей пробелмы - std::advance
"А можно пример?" Улыбающийся Потому что не вижу каким боком здесь поможет advance

И что там за "плохо скрываемое раздражение"? Улыбающийся Нет удобного решения - ну у меня его тоже нет.
Записан
Racheengel
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2679


Я работал с дискетам 5.25 :(


Просмотр профиля
« Ответ #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 Offline

Сообщений: 81


Просмотр профиля
« Ответ #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 Offline

Сообщений: 11445


Просмотр профиля
« Ответ #21 : Апрель 20, 2021, 11:00 »

Да, интересный приемчик с reference_wrapper, не знал, спасибо
Записан
AkonResumed
Чайник
*
Offline Offline

Сообщений: 81


Просмотр профиля
« Ответ #22 : Апрель 20, 2021, 11:08 »

Не вопрос. Да и это делеко не последний писк моды - это c C++11.
Записан
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3260


Просмотр профиля
« Ответ #23 : Апрель 20, 2021, 12:41 »


Код:
return reinterpret_cast<QSet<std::reference_wrapper<CData>>&>(mSelection);

Это UB
Записан
AkonResumed
Чайник
*
Offline Offline

Сообщений: 81


Просмотр профиля
« Ответ #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 Offline

Сообщений: 4350



Просмотр профиля
« Ответ #25 : Апрель 20, 2021, 14:45 »

Ну это все таки грязный хак. Улыбающийся
А что если у QSet для указателей и нет разные специализации?
Записан
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3260


Просмотр профиля
« Ответ #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 Offline

Сообщений: 3260


Просмотр профиля
« Ответ #27 : Апрель 20, 2021, 15:09 »

Ну или более сложный пример, вы знаете что на вашей платформе sizeof(bool) == sizeof(int8_t) (ну или char).
Значит вы можете сделать
Код:
vector<bool> bools;
auto &chars = reinterpret_cast<vector<char>&>(bools);
?
Записан
AkonResumed
Чайник
*
Offline Offline

Сообщений: 81


Просмотр профиля
« Ответ #28 : Апрель 20, 2021, 15:53 »

А что если у QSet для указателей и нет разные специализации?
Ах, таки вы меня подсекли! Про возможную специализацию внешнего типа я упустил. В данном случае специализации QSet нет, работать будет. Но в общем случае - да, это нужно учитывать.

Авварон,
Код:
vector<bool> bools;
auto &chars = reinterpret_cast<vector<char>&>(bools);
Как метко подметил Old, причина этого UB в специализации vector<bool>. Она хранит биты, а не байты.

По поводу strict alias rule и оптимизации (привет restrict poiners): А как вы соотнесете это с placement new(), например?
Записан
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3260


Просмотр профиля
« Ответ #29 : Апрель 20, 2021, 16:03 »

Ах, таки вы меня подсекли! Про возможную специализацию внешнего типа я упустил. В данном случае специализации QSet нет, работать будет. Но в общем случае - да, это нужно учитывать.

Там внутри могут быть всякие traits которые для разных типов разные.
Но в любом случае, даже если битовое представление одинаковое, это UB.

По поводу strict alias rule и оптимизации (привет restrict poiners): А как вы соотнесете это с placement new(), например?

В чем проблема-то? Единственный валидный юзкейз reinterpret_cast между разными типами это каст к массиву байт (или void*) и обратно.
Компилятор знает что вон тот char buffer[] потенциально может алиаситься с вот этим указателем и сгенерит менее производительный код.
placement new как раз подпадает под это - буфер чаров может алиаситься (и делает это) с указателем на произвольный T.
А вот любые другие типы (например int* в double*) алиаситься не могут.
Записан
Страниц: 1 [2] 3 4 ... 6   Вверх
  Печать  
 
Перейти в:  


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