Начитался тут тем про MSVC /Wall /WX, и решил тоже попробовать.
Повылезала куча всего, но в основном signed/unsigned mismatch, и вот это вот всё. Индексы в массивах и векторах — хочет size_t, а у меня часто int. Или исторически так сложилось, или требования какого-то API, или просто было пофигу, потому что я знаю, что у меня массив вообще никогда не вырастет до такого размера, чтобы знаковый бит стал проблемой (например, вектор из созданных HPEN/HBRUSH — система ляжет раньше, чем я только начну приближаться к проблемному размеру), и, часто, при этом, этот индекс если меньше нуля, то это инвалидный индекс, и я всегда проверяю инвалидность. Или битовые операторы и операторы сдвига — они, как оказалось, возвращают int/int64, а не тот тип, который изначально участвует в выражении. Полечил сишными кастами. Если бы лечить static_cast'ами, это каждое выражение становится пипец каким ужасным и нечитаемыми.
В целом, плюсовыми кастами пользуюсь иногда, когда надо явно сделать какое-то нетривиальное преобразование в критичном месте, и поиск таких мест по маске "_cast<" и выдаёт немного.
Почему сишным кастом пользоваться плохо?
Например, я убираю возможную знаковость у char переменной и конвертирую её в unsigned как-то так:
auto u = (unsigned)(std::uint8_t)ch;
Но можно и так:
auto u = static_cast<unsigned>(static_cast<std::uint8_t>(ch));
Во втором случае выражение гораздо менее наглядно, приходится скрипеть мозгами, чтобы понять, что там происходит.
Припоминаю аргументы:
1) Удобно искать cast'ы — но если на каждый чих их использовать, то любой поиск выдаст тонно-километры этих кастов. А если мы знаем точно, к какому типу ищем каст, то не всё ли равно, что искать — либо "_cast<TYPE>(", либо "(TYPE)"?
2) Сишный каст универсален, и беспринципно беспощаден — ну это есть, да, надо думать иногда, стоит ли использовать сишный каст или в узком месте использовать специализированный плюсовый каст. Может, просто стоит в код стайлах писать, в каких случаях надо использовать плюсовые касты, подразумевая, что в остальных случаях можно обойтись сишным кастом?
Да, для удобства поиска использую именно сишный каст, а не constructor style cast вида int(...)
Здравствуйте, reversecode, Вы писали:
R>вот они последователи шмыги, которые ни разу не бывали на собеседованиях
Я в яндекс дзене немного посидел, там скукота, перекладывание из одной шляпы в другую. В НИИ я примерно тем же занимался, но там было веселее — там раз в несколько месяцев мой робот начинал летать/ползать, это драйвило.
Да, даже в НИИ в код стайле было прописано использование строго только плюсовых кастов. И нигде я не видел внятных обоснований для этого.
ЗЫ А ты зачем Шмыгу обижаешь, твой же побратим, не?
Здравствуйте, reversecode, Вы писали:
R>вот они последователи шмыги, которые ни разу не бывали на собеседованиях
Кстати, ты бы мог, как сознательный украинец, взять шмыгу под свой патронаж, помочь побратиму, а заодно вы бы схлопнулись и аннигилировали, как частица и античастица, очистив профильные форумы от своего присутствия
Здравствуйте, Marty, Вы писали:
M> Индексы в массивах и векторах — хочет size_t, а у меня часто int. Или исторически так сложилось, или требования какого-то API, или просто было пофигу, потому что я знаю, что у меня массив вообще никогда не вырастет до такого размера, чтобы знаковый бит стал проблемой (например, вектор из созданных HPEN/HBRUSH — система ляжет раньше, чем я только начну приближаться к проблемному размеру), и, часто, при этом, этот индекс если меньше нуля, то это инвалидный индекс, и я всегда проверяю инвалидность.
Здравствуйте, Marty, Вы писали:
M>Например, я убираю возможную знаковость у char переменной
Для чего? Любой практически полезный сценарий надо прописывать в явном виде, с if'ами, а не неявно через типопреобразование.
Если я правильно понял, тебе лень нормально написать bound checking, и ты заменил его кастами.
M>ОбсудиПохоливарим?
Я следую прямо противоположному правилу: кроме сишных кастов ничего не использовать, чтобы было меньше говнокода. Логика очень простая и железобетонная: ЛЮБОЙ КАСТ ЭТО СИТУАЦИЯ, КОГДА *ТЫ* ЗНАЕШЬ О НАСТОЯЩЕМ ТИПЕ, А КОМПИЛЯТОР — ПОЧЕМУ-ТО НЕТ. Таких ситуаций надо избегать, потому, что они говорят о неправильной архитектуре и/или неверно написанном коде. Есть, конечно, ситуации, когда имеешь дело с историческими артефактами типа WinAPI, но там и Си-каста хватает.
Здравствуйте, Alekzander, Вы писали:
A>Здравствуйте, Marty, Вы писали:
M>>Например, я убираю возможную знаковость у char переменной
A>Для чего? Любой практически полезный сценарий надо прописывать в явном виде, с if'ами, а не неявно через типопреобразование.
A>Если я правильно понял, тебе лень нормально написать bound checking, и ты заменил его кастами.
Бывают случаи, когда бинарные данные приходят тупо в виде const char* или std::string, а собрать их нужно, скажем, в std::vector<std::uint8_t>. Повлиять на источник данных нельзя, это может быть сторонняя библиотека или кусок кода, написанный 100500 лет назад.
Здравствуйте, Marty, Вы писали:
M>Например, я убираю возможную знаковость у char переменной и конвертирую её в unsigned как-то так: M>
M>auto u = (unsigned)(std::uint8_t)ch;
M>
Achtung! unsigned это unsigned int, а не unsigned char. Тут один байт в четыре превращается.
M>Но можно и так: M>
M>auto u = static_cast<unsigned>(static_cast<std::uint8_t>(ch));
M>
static_cast, dynamic_cast, reinterpret_cast это в первую очередь инструменты для преобразования указателей базовых классов в унаследованные с контролем или в случае reinterpret_cast явное указание, что не в наследуемый.
Хотя в рекомендациях пишут, что static_cast можно и нужно использовать даже для встроенных типов.
Здравствуйте, so5team, Вы писали:
S>За использование сишного каста в C++ном коде нужно отрывать руки, а затем выгонять на мороз (ну или в обратной последовательности).
Евангелизм как он есть.
Здравствуйте, so5team, Вы писали:
M>>>Например, я убираю возможную знаковость у char переменной
A>>Для чего? Любой практически полезный сценарий надо прописывать в явном виде, с if'ами, а не неявно через типопреобразование.
A>>Если я правильно понял, тебе лень нормально написать bound checking, и ты заменил его кастами.
S>Бывают случаи, когда бинарные данные приходят тупо в виде const char* или std::string, а собрать их нужно, скажем, в std::vector<std::uint8_t>. Повлиять на источник данных нельзя, это может быть сторонняя библиотека или кусок кода, написанный 100500 лет назад.
Я же написал, что иногда приходится иметь дело с историческими артефактами, но там и Си-каста хватает. Речь идёт о том, что всё, что сложнее, лично для меня детектор.
Здравствуйте, Kernan, Вы писали:
S>>За использование сишного каста в C++ном коде нужно отрывать руки, а затем выгонять на мороз (ну или в обратной последовательности). K>Евангелизм как он есть.
Или слишком много набитых в C++ шишек, которых можно было бы избежать, если бы программисты думали о том, как написать нормальный код, а не о том, чтобы сэкономить несколько символов.
Далеко не глупые люди посмотрели к тему приводит C-шный каст, внедрили в C++ специальные конструкции, которые если не делают код безопаснее, то уж точно явно отмечают подозрительные места... Но нет, всегда есть кто-то шибко умный, который скажет, что у него-то уж точно все нормально.
Здравствуйте, Alekzander, Вы писали:
A>Я же написал, что иногда приходится иметь дело с историческими артефактами, но там и Си-каста хватает.
Си-каст? Прострелить ноги, оторвать руки и на мороз шагом марш!
Но вообще, конечно, забавно. Сперва рассуждения о "Любой практически полезный сценарий надо прописывать в явном виде, с if'ами, а не неявно через типопреобразование", а потом бах, и Си-каст, который на все типопреобразования кладет с прибором. Вот что в головах у людей?
Здравствуйте, so5team, Вы писали:
S>Далеко не глупые люди посмотрели к тему приводит C-шный каст, внедрили в C++ специальные конструкции, которые если не делают код безопаснее, то уж точно явно отмечают подозрительные места...
тут вопрос как раз о конструкциях, которые приводят к простреленным конечностям с C и C++ кастом. Я вот как-то придумать такие конструкции с ходу не могу.
Просто "пометить подозрительные места" — мне кажется слишком слабый аргумент для ввода 4 новых слов в язык.