LINUX.ORG.RU

Вы тут сидите и ничего не знаете!

 


0

2

Совершенно случайно наткнулся, в стд появилась мега фича ssize()! После долгий метаний относительно signed/unsigned геморроя, сегодня решил - ну буду к каждому проекту присобачивать костылики - sigsize() и idx(), оказалось, что один костыль не нужен. Ещё бы такую перегрузку для контейнеров воткнуть:

operator[]( ptrdiff_t pos );

Жаль проблемы с неоднозначностью будут. Ладно, может чего придумают на этот счёт, ну а пока такое:

template <typename T>
auto &idx(T &container, std::ptrdiff_t i) {
    return container[static_cast<std::size_t>(i)];
}

Короче - наверняка есть много людей с тонной static_cast’ов в коде - берите ssize() на вооружение.

PS: да, конечно же знаю про *(ctr.begin() + i).

★★
Ответ на: комментарий от ZenitharChampion

У меня такое компилится:

#include <vector>
using namespace std;

int main() {
	vector v{1, 2};
	int sz = ssize(v);
}
$ g++ -std=c++20 1.cc
kvpfs ★★
() автор топика

Вы тут сидите и ничего не знаете!

2019/02/22

Открыл календарь: 2021/07/04.

Кто хотел, тот узнал…

После долгий метаний относительно signed/unsigned геморроя

Можно пример кода? А то возможно ты ещё многого не знаешь 😺

fsb4000 ★★★★★
()
Последнее исправление: fsb4000 (всего исправлений: 1)
Ответ на: комментарий от fsb4000

Можно пример кода? А то возможно ты ещё многого не знаешь 😺

Кто мучился, тот поймёт, ещё Страуструп предлагал забить на беззнаковые индексы в CppCoreGuidelines. Некоторых ждет сюрприз после включения -Wsign-conversion и осознания проблемы, у кого-то портянки изуродованы бесконечными static_casta’ми. Да сам факт отсутствия -Wsign-conversion в -Wall о многом говорит, разнознаковая арифметика слишком массова.

kvpfs ★★
() автор топика
Ответ на: комментарий от kvpfs

Некоторых ждет сюрприз после включения -Wsign-conversion

У меня включено, и нет никаких проблем 😺. Я подозреваю ты не до конца прочитал cppreference. Удачного чтения тогда 😉

fsb4000 ★★★★★
()
Ответ на: комментарий от fsb4000

Я не сильно хочу спорить, но мой опыт такой - основные типы знаковые, unsigned в виде исключения (маски всякие, просто огромный массив, торчащая из пользовательского интерфейса беззнаковая по своей природе сущность).

Сейчас у меня на руках небольой проект, около 2К строк, взаимодействует с нижележащей сишной либой с которой обменивается знаковыми типами, а с другой стороны - STL, которой подавай беззнаковые. Вот и начинается эта череда кастов signed<->unsigned, *(ctr.begin() + i), и прочая ерунда, которая уродует код. Сяду и перепишу всё на знаковых типах.

kvpfs ★★
() автор топика
Ответ на: комментарий от ZenitharChampion

ещё вчера мы сидели и смеялись над теми и показывали пальцем, кто пишет на крестах
а сегодня сами сидим и с наслаждением обмазываемся JS и котлином

darkenshvein ★★★★★
()

Ну я как минимум год знаю об этой «фиче», при том что я C++ пользуюсь крайне редко.

peregrine ★★★★★
()
Ответ на: комментарий от darkenshvein

смеялись над теми и показывали пальцем, кто пишет на крестах

обмазываемся JS

За мной сегодня тоже бежал сумашедший бомж, что-то крича и тыкая пальцем.

rupert ★★★★★
()

C++ как всегда ужасны

AUX ★★★★
()

Короче - наверняка есть много людей с тонной static_cast’ов в коде - берите ssize() на вооружение.

Я один из них. Спасибо за наводку.

Beewek ★★★
()

То, что стандартные контейнеры работают на size_t индексах и длинах, — это, конечно, дебилизм первоначальной реализации. Теперь уже ноша обратной совместимости.

Лично я всегда включаю -Wextra -pedantic, но проблем с знаковыми/беззнаковыми не имею. Потому что использую итераторы почти всегда.

filosofia
()
Ответ на: комментарий от fsb4000

Меня каждый раз сильно удивляет, как у тебя после работы ещё хватает желания следить за всеми мелочами в стандартах С++, как принятых, так и только обсуждаемых.

i-rinat ★★★★★
()
Ответ на: комментарий от EugeneBas

Точно, народ ведь аж с года так 2011 начал на с++20 писать. Оно и заметно, на всём гитхабе прогугливается в лучшем случае тысячи 2 файлов с std::ssize() из которых процентов 80-90 код из libc++ у многочисленных форков llvm.

kvpfs ★★
() автор топика
Ответ на: комментарий от filosofia

Но индексы всё же более универсальны для храниния, например, нет никакой заморочки с константностью, типом, меньше шаблонов. Да ещё пол беды, если одни лишь итераторы, но СТЛ постоянно толкает тебя на unsigned

int cnt = ...;

string.insert(string.begin(), cnt, ' ');
  1. Втыкать на ровном месте static_cast? Да, красиво.
  2. Забить и оставить как есть? Значит загадить выхлоп от -Wsign-conversion и пропустить однажды действительно нужное предупреждение.
  3. Впускать в код unsigned? Тогда этот cnt пройдет по всему коду где я это как-то высчитывал и создаст еще с десяток мест с проблемами, где я вернусть к п1.

Да, за unsigned STL очень хочется кому-нибдь спасибо сказать.

kvpfs ★★
() автор топика
Ответ на: комментарий от kvpfs

Может в твоём случае это и правильно…

Просто, например в cppcheck

https://github.com/danmar/cppcheck/blob/6cb8f877981a491465aba2f9ffb00d6142f6f852/Makefile#L102 -Wno-sign-compare отключены эти проверки только из-за подобных циклов: https://github.com/danmar/cppcheck/blob/e6e0cb773fb54d8deae79efccf6eab70f00235e6/tools/generate_cfg_tests.cpp#L24

А с этим вполне могут справиться вот эти функции, вместо кастов: https://en.cppreference.com/w/cpp/utility/intcmp

Кстати:

Cppcheck-2.5

@danmar released this 18 hours ago ·

Надо тему в новости ЛОР написать, раз уж вовремя зашёл на страницу этого проекта.

fsb4000 ★★★★★
()
Ответ на: комментарий от kvpfs

Почему сразу не сделать size_t cnt, а cast делать там, где нужно будет сложить, если понадобится вообще, cnt с чем-то ещё, что скорее всего будет присходить реже. По крайней мере в примере со строкой не видно, почему взят int.

grem ★★★★★
()

А зачем нужны знаковые целые для работы с размером контейнеров?

LamerOk ★★★★★
()
Ответ на: комментарий от kvpfs

а разве гитхаб - это единственный источник информации по нововведениям в плюсы? я для этих целей cppreference использую

EugeneBas ★★
()
Ответ на: комментарий от grem

Да, всё логично на первый взгляд, до того момента, когда хочешь высчитать размер добивки строки взяв интовую ширину экрана из ncurses или ещё где заюзать эту переменную в каком-нибудь арифметическом выражении. Я не должен ломать мозг на этапе объявления переменной - «int или unsigned? Как я буду это использовать», да я и сам пока ещё не знаю.

Беззнаковые - подмножество целых, которые подмножество вещественных. В смешанных операциях логично кастовать тип подмножества в тип множества (3+3.0 = double(6)), но беззнковые этой простой модели не следуют, а значит это ручные касты в смешанных ариф операциях. И полнейшая глупость - пригодный лишь для спец кейсов unsigned делать основой универсальной СТЛ.

Надо признать ошибку и сделать фундаментальные правки. Например, почему вот это неоднозначность?

void f(unsigned long);
void f(long);

int l;
unsigned int ul;
f(l);
f(ul);

почему бы не пересмотреть назначение «очков» у кандидатов из overload set’а и не сделать валидным это? А после продублировать все size_t методы аналогичными с ssize_t.

kvpfs ★★
() автор топика
Ответ на: комментарий от kvpfs

Беззнаковые - подмножество целых, которые подмножество вещественных

Натуральные, а не беззнаковые. К машинным типам все это отношения не имеет.

Остальное полная чушь.

Siborgium ★★★★★
()
Ответ на: комментарий от kvpfs

В смешанных операциях логично кастовать тип подмножества в тип множества (3+3.0 = double(6)),

5.0/3 = int(1)?
Никому нельзя доверять!

беззнковые этой простой модели не следуют

ну а что поделать, приходится кастовать, иначе на переполнение можно нарваться и получить совершенно не то в результате.

grem ★★★★★
()
Ответ на: комментарий от grem

Может ты неправильно понял, я имею в виду автокаст

static_assert(is_same_v<decltype(5.0/3), double>);
kvpfs ★★
() автор топика
Ответ на: комментарий от Siborgium

Остальное полная чушь.

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

kvpfs ★★
() автор топика
Ответ на: комментарий от kvpfs

Я не должен ломать мозг на этапе объявления переменной - «int или unsigned? Как я буду это использовать», да я и сам пока ещё не знаю.

Войтишник?

eao197 ★★★★★
()
Ответ на: комментарий от eao197

Просто уже наелся этого дерьма. Я то уже приспособился, и тот кейс со стрингом буду решать так:

template <typename T>
struct sig {
    static_assert(std::integral<T>);
    T m_t;
    sig(T t) : m_t{t} {}
    template <typename U>
        operator U() {
            static_assert(std::integral<U>);
            return static_cast<U>(m_t);
        }
};
...
string.insert(string.begin(), sig(cnt), ' ');

Плюс ещё один раннее упомянутый костыль idx() + ssize() и вроде норм, но желающих страдать на удивление очень много.

kvpfs ★★
() автор топика
Ответ на: комментарий от kvpfs

Просто уже наелся этого дерьма.

Простите, какого дерьма? Может вы под дерьмом понимаете необходимость ломать мозг при выборе типа переменной?

Ну так это ж программирование. Когда-то это подразумевало, что программист должен ломать мозг.

Теперь, видимо, окончательно наступили времена «фигак-фигак-и-в-продакшен-потому-что-думать-лень»

Можно еще вопрос: а как вы убеждаетесь, что при работе со знаковыми индексами и размерностями в C++ у вас нет UB?

eao197 ★★★★★
()
Ответ на: комментарий от eao197

Когда-то

когда-то джентельмену не к лицу было появляться без шляпы на публике. так што ваш высер, сударь, выглядит не очень. разработка ПО уже давно вышла за рамки инженерной профессии с соответствующей ей инженерной культуры.

anonymous
()
Ответ на: комментарий от eao197

Простите, какого дерьма? Может вы под дерьмом понимаете необходимость ломать мозг при выборе типа переменной?

Какое-то лютое недопонимание, я уже писал почему в случае с uint всё иначе. Дальше собирайте на здровье грабли вида: -1 + 1U + 1LL, но без меня.

kvpfs ★★
() автор топика
Ответ на: комментарий от kvpfs

Какое-то лютое недопонимание

Так ответе на вопросы, может этого недопонимания станет меньше. Что мешает ответить?

я уже писал почему в случае с uint всё иначе

Рискну предположить, что вагон и маленькая тележка копий на тему int/unit для индексов/размерностей были сломаны задолго до того, как вы занялись программированием. И то, что вы озвучиваете всего лишь одну точку зрения, ничего в этих раскладах не меняет.

Суть в другом: программист раньше должен был думать прежде чем писать код (ну или хотя бы во время написания). А теперь вы (будучи программистом, полагаю) заявляете, что вы не хотите думать.

Очень печально становится от факта того, что программистам думать лень.

eao197 ★★★★★
()
Ответ на: комментарий от eao197

Суть в другом: программист раньше должен был думать прежде чем писать код (ну или хотя бы во время написания). А теперь вы (будучи программистом, полагаю) заявляете, что вы не хотите думать. Очень печально становится от факта того, что программистам думать лень.

Суть совершенно в другом, эти матёрые программисты всю жизнь писали на моделе ILP32, а integer promotion в плюсах завязан на int, и вроде было ничего т.к. смешанная (без и знаковая) арифметика не давала сюрпризов. А теперь всё иначе, LP64 и LLP64 вокруг, а в плюсах до сих пор integer promotion на int’е, но эти матерые волки всё живут в старой парадигме и принимать реальность не хотят.

kvpfs ★★
() автор топика

Но вообще тебе в жабку или что-то подобное. Там ламерок выше задавал основной вопрос по теме, ты так и не ответил, что символизирует.

anonymous
()
Ответ на: комментарий от kvpfs

Сколько боли и ни одного вменяемого ответа.

eao197 ★★★★★
()
Ответ на: комментарий от anonymous

В данном случае важно то, что все аргументы всех арифметических операций кастуются в int/unsigned если они меньше. На ILP32 это было максимальным типом и не было никакой разницы в выражении (x+y+z), сейчас же z может оказаться размером жирнее int’a, тогда лови сюрприз.

kvpfs ★★
() автор топика
Ответ на: комментарий от kvpfs

кастуются в int/unsigned если они меньше. На ILP32 это было максимальным типом и не было никакой разницы в выражении (x+y+z), сейчас же z может оказаться размером жирнее int’a, тогда лови сюрприз.

Одно откровение лучше другого. Нет, int никогда не был самым широким типом.

anonymous
()

Вы тут сидите и ничего не знаете!

Исходя из разных ваших ответов, честнее было бы тред назвать

Вы тут сидите и ничего не знаете матерые волчары!
anonymous
()
Ответ на: комментарий от anonymous

Не нужно так эмоционально вести диалоги …

anonymous
()
Ответ на: комментарий от kvpfs

Я то уже приспособился, и тот кейс со стрингом буду решать так

Оказалось много удобней так:

template <std::integral T>
auto sig(T t)
{
        using type_t = std::conditional_t<std::is_signed_v<T>,
                  std::uintmax_t, std::intmax_t>;
        return static_cast<type_t>(t);
};

А idx() - вообще ненужный костыль.

kvpfs ★★
() автор топика
Ответ на: комментарий от reprimand

Это тебя так static_cast напугал? Начинаешь понимать насколько он изящен, когда делаешь по проекту grep ‘static_cast’ или ‘reinterpret_cast’ и осознаёшь, что в Ц к сожалению его нет.

Кстати лично для меня это основная причина не применять static_cast в ариф операциях и выделить это в отдельную категорию, чтобы он был там, где его место.

kvpfs ★★
() автор топика

Странно, вот никогда не приходилось такой бред писать. Может потому что в нормальном коде неоткуда взяться знаковым смещениям в контейнерах?

slovazap ★★★★★
()
Ответ на: комментарий от slovazap

Я вот ради интереса взял первый попавшийся проект (на самом деле второй, для первого какой-то либы не нашлось) с строкой поиска ncurses и ЦПП https://github.com/mtytel/cursynth, и скомпилил его с -Wsign-conversion. Куча бесполезных, мусорных ворингов среди реально важных:

RtAudio.cpp:8011:53: warning: conversion to ‘unsigned int’ from ‘int’ may change the sign of the result [-Wsign-conversion]
 8011 |     memset( outBuffer, 0, stream_.bufferSize * info.outJump * formatBytes( info.outFormat ) );

тут info.outJump кастуется в unsigned. Типичный потенциальный косяк, поведение которого зависит от размера formatBytes(). Конкретно здесь он вряд ли вляпается, но однажды обязательно наступит т.к. свободно смешивает разнознаковую арифметику и с большим трудом будет разбираться из-за мусорных предупреждений (когда откроет для себя -Wsign-conversion).

К счастью большинству такое здесь не грозит, они так говорят.

kvpfs ★★
() автор топика
Ответ на: комментарий от kvpfs

Каждый второй проект не умеет типы использовать, что уж там. Хранит индексы в int, например, или почему-то вообще в ptrdiff_t. Варнинги на эту тему совершенно обоснованы, и исправляются использованием правильных типов, а не костылями типа ssize, которые просто скрывают ошибку.

Signed size - это вообще оксюморон, никакой контейнер не может иметь отрицательный размер, и никакой из стандартных отрицательные индексы. Если ты передаёшь ему ssize_t, значит ты профнепригоден. Бывают, конечно, случаи когда ты не виноват и тебе приехал ssize_t из какой-нибудь ублюдочной сявой библиотеки - так скастуй его явно, а желательно ещё и на знак проверь.

slovazap ★★★★★
()
Ответ на: комментарий от slovazap

Ну ты ведь не сомневашься в профпригодности Страуструпа, а он топит за знаковые индексы. Он даже вообще как-то сказал на пару с Саттером:

Don’t try to avoid negative values by using unsigned

может секрет какой-то есть?

Signed size - это вообще оксюморон, никакой контейнер не может иметь отрицательный размер, и никакой из стандартных отрицательные индексы.

Не в этом дело, я уже писал про ILP32 и LP64, нужно либо стд допиливать, либо правила integer promotion менять. Со вторым могут быть проблемы из-за совместимости, наверное.

kvpfs ★★
() автор топика
Ответ на: комментарий от kvpfs

Не в этом дело, я уже писал про ILP32 и LP64

Скорее всего дело в тараканах в вашей голове, а не в ILP32 и LP64.

eao197 ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.