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).

★★

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

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

Я не признаю авторитетов, поэтому конечно же сомневаюсь. Страуструп там или очередной Васян рот раскрыл мне без разницы, важно какие были приведены обоснования.

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

Может и есть, если ты не гнушаешься цитировать страуструпа наверное тебе не лень будет копнуть глубже.

Мне лично очевиден профит от кода в котором некорректные состояния невыразимы.

slovazap ★★★★★
()

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

НеЗнаете:

… не знаете, не знаете, не знаете

goto НеЗнаете;

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

Я не признаю авторитетов, поэтому конечно же сомневаюсь. Страуструп там или очередной Васян рот раскрыл мне без разницы, важно какие были приведены обоснования.

Вот цитата Бьярне:

Using an unsigned instead of an int to gain one more bit to represent positive integers is almost never a good idea. Attempts to ensure that some values are positive by declaring variables unsigned will typically be defeated by implicit conversion rules

Ещё есть такой путь в coreguideline: https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#es102-use-signed-types-for-arithmetic

P.S. мне size_t тоже больше нравится для индексов, чем int

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

важно какие были приведены обоснования.

А нарушение ассоциативности привычных операций - не аргумент?

cout << (-2 + 1u + 1ll) << endl;  // 4294967296
cout << (1u + 1ll -2) << endl;    // 0

Беззнаковые не подчиняются правильным правилам каста в родительское множество. Такие конструкции по-хорошему вообще должны давать компайл тайм ошибку, только через явный каст. В итоге uint - это «кривой костыль», годный лишь для ограниченного числа локальных задач. По-моему, этого вполне достаточно.

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

По-моему, этого вполне достаточно.

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

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

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

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

Ограничения будут хоть со знаковым, хоть с беззнаковым, если они той же ширины.

Чтобы без ограничений использовать знаковые числа на 64-битных указателях, тебе потребуется 128-битный int.

/thread

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

Мне лично очевиден профит от кода в котором некорректные состояния невыразимы.

При переходе к модульной арифметике от обычной некорректные состояния никуда не деваются. -1, например, превратившись в некоторое положительное число, по прежнему остаётся некорректной. Энфорсить инварианты нужно всё равно в рантайме за счёт своих проверок. Разве что теперь нет шанса половить знаковый overflow автоматически через ASAN.

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

Я для тугих специально написал что, коли так оказалось что тебе пришёл знаковый тип, при касте в беззнаковый должна быть проверка. Но поинт был в другом - не может быть такой корректной арифметики которая породит отрицательный размер, поэтому в корректном коде не будет нужно ни знаковых типов, ни дополнительных проверок.

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

Мне не нужны отрицательные индексы и размерности, мне нужна возможность использовать их в обычных арифметических операциях и получать предсказуемый результат

Если у вас нет надобности в отрицательных индексах/размерностях, то зачем вам арифметические операции, где такие значения могут появится?

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

А почему бы нет? Металлобаза скупает и продаёт металлолом, за месяц куплено 3 тонны (unsigned buy = 3), продано 4 тонны (unsigned sell = 4). Подсчитать общий результат за месяц:

long res = buy - sell;

предвосхищая вопрос «зачем тебе здесь long, в валидных программах используется int», подсчитаем результат по всем предприятиям региона:

res += buy_2 - sell_2;
res += buy_3 - sell_3;
...
kvpfs ★★
() автор топика
Ответ на: комментарий от slovazap

Каждый второй проект не умеет типы использовать

Да и ты тоже. Если не отличаешь беззнаковых целых от чисел с арифметикой по модулю. Подсказка: в C++ нет фундаментальных беззнаковых целых чисел.

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

А почему бы нет?

Нет хотя бы потому, что по вашим же словам «Мне не нужны отрицательные индексы и размерности».

Для того, чтобы ваш пример с разницей между покупкой и продажей имел отношение к теме разговора, вам нужно показать как и зачем эта самая разница начинает использоваться в качестве размерности контейнера или индекса в контейнере (не ассоциативном контейнере).

предвосхищая вопрос «зачем тебе здесь long, в валидных программах используется int»

Простите за офтопик, но:

во-первых, вам не следует пытаться думать за других, у вас, судя по вашей способности выражать мысли, есть проблемы даже с думанием за самого себя;

во-вторых, откуда у вас уверенность в том, что long-а хватит? Вы пишите код, намертво прибитый к конкретной аппаратной платформе?

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

Ну ты ведь не сомневашься в профпригодности Страуструпа

Как из профпригодности Страуструпа следует необходимость подражать ему во всем?

а он топит за знаковые индексы. Он даже вообще как-то сказал на пару с Саттером:

Don’t try to avoid negative values by using unsigned

Не понимаю, как из этого следует необходимость использовать знаковые индексы.

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

Беззнаковые не подчиняются правильным правилам каста в родительское множество.

Нет никакого «родительского» множества, бегом в школу.

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

Не должны. Кроме того,

main.cxx:6:14: warning: implicit conversion changes signedness: 'int' to 'unsigned int' [-Wsign-conversion]
    cout << (-2 + 1u + 1ll) << endl;  // 4294967296
Siborgium ★★★★★
()

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

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

Нет хотя бы потому, что по вашим же словам «Мне не нужны отрицательные индексы и размерности». Для того, чтобы ваш пример с разницей между покупкой и продажей имел отношение к теме разговора, вам нужно показать как и зачем эта самая разница начинает использоваться в качестве размерности контейнера или индекса в контейнере (не ассоциативном контейнере).

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

Во-вторых, а для чего мне такие индексы? А для того чтобы исключить по максимуму из кода беззнковые, включить -Wsign-conversion и не получать тонну ворингов в местах вида: vector[int_idx], а получать в действительно нужных местах вида: а+b+c, в которое может случайно залететь uint. Именно для подавления такого «шума», а не для vector[-1].

В-третьих, а что фундаментально не так в языке с integer promotion? Общим результирующим типом для знакосмешанных операций должен быть максимально широкий на данной системе, например специальный и отдельный тип (а не typedef) unsigned_max/signed_max. Не знаю точно, можно ли было это предвидеть на заре учитывая то, что совсем недавно определились с представлением целых.

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

Нет никакого «родительского» множества, бегом в школу.

Натуральные числа не являются подмножеством целых чисел? Любые операции, в которых операнды разных классов, должных кастоваться в родительское подмножество (целые числа в данном кейсе).

Не должны. Кроме того,

А теперь вопрос - насколько комфортно будет искать данные воринги, когда есть ещё 100500 ворингов мусорных на vec[int_idx]? Не вынудит ли это вовсе забить на -Wsign-conversion т.к. «заипало выдавать эту портянку»?

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

Я буд-то с растаманами говорю, один в один фанатики.

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

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

Вот ваши слова:

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

Здесь вы

a) говорите, что отрицательные индексы и размерности вам не нужны;

b) не говорите, что вам нужны знаковые индексы. Вам нужна возможность использовать индексы/размерности в арифметических операциях. Из чего вовсе не следует потребность в знаковых индексах.

а для чего мне такие индексы?

Да, ответ очень хотелось бы услышать. Но его опять нет. Ибо в словесном поносе вида:

А для того чтобы исключить по максимуму из кода беззнковые, включить -Wsign-conversion и не получать тонну ворингов в местах вида: vector[int_idx], а получать в действительно нужных местах вида: а+b+c, в которое может случайно залететь uint. Именно для подавления такого «шума», а не для vector[-1]

ответа на этот вопрос нет. Есть подозрение, что вы хотите в своем коде складывать помидоры с апельсинами и не получать за это по рукам от компилятора. Но к проблеме (без)знаковости индексов/размерностей это имеет лишь косвенное отношение.

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

Так уж и быть, вас я не убедил. Приводить доп аргументы я устал.

PS: на самом деле не думаю, что вот допилить integer promotion сейчас прям совсем невозможно, ну много ли существует мест, где:

void any_fn(int);
void any_fn(long); //or long long

вкрутить новый «всегда широчайший тип», сделать преходной воринг который будет срабатывать, когда overload set находятся оба подобных варианта и выбирается второй, и исправить эти 0.5% случаев во всей кодовой базе. Но если адепты в языке проблемы не замечают, то вряд ли это когда-то случится, тут и слова Страуструпа под сомнения ставят.

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

даже новый воринг не нужен, тип ведь будет новым (unsigned_max/signed_max) и в данном случае будет просто ошибка компиляции из-за неоднозначности.

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

и в данном случае будет просто ошибка компиляции из-за неоднозначности.

Удачи с внесением изменения в стандарт, которое ломает рабочий код.😉

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

насколько комфортно будет искать данные воринги, когда есть ещё 100500 ворингов мусорных на vec[int_idx]?

Не мои проблемы. Если ты используешь беззнаковые числа для индексов, никаких «100500 ворингов мусорных на vec[int_idx]» у тебя не будет.

Натуральные числа не являются подмножеством целых чисел?

Так и быть, краткий экскурс в математику для дошколят.

Предполагая 4-байтные int и unsigned int (что не всегда так),

{int} = 0, ±1, ±2, ..., ±2147483647, -2147483648
{unsigned int} = 0, 1, 2, ..., 4294967295

Осталось только понять, какое отношение имеют машинные типы к математическим

N = 0, 1, 2, ...
Z = 0, ±1, ±2, ...

И выучить известное утверждение A ⊆ B ⇔ A ∩ B = A,

{int} ∩ {unsigned int} = 0, 1, 2, ..., 2147483647
{int} ∩ {unsigned int} ≠ {int}
{int} ∩ {unsigned int} ≠ {unsigned int}

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

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

В-третьих, а что фундаментально не так в языке с integer promotion?

То, что он существует. Никому не нужны никакие promotion, машинные типы нужны для осуществления над ними машинных операций. Касты между типами не бесплатны.

должен быть максимально широкий

Складываю THE_WIDEST_INT_TYPE_EVER_MAX и THE_WIDEST_INT_TYPE_EVER_MAX. В какой тип результат записывать?

Занавес.

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

Так и быть, краткий экскурс в математику для дошколят.

Правда думаешь, что не догадываюсь о том, что int не включает весь диапазон unsigned? Навивно, зря старался. И значения это никакого не имеет, важно лишь как каст будет происходить - с sign extension или без.

То, что он существует. Никому не нужны никакие promotion

Без него твои поделки начали бы падать еще в далекие времена x32. Подумай на досуге - почему -Wsign-conversion отсутствует в -Wall наборе.

Складываю THE_WIDEST_INT_TYPE_EVER_MAX и THE_WIDEST_INT_TYPE_EVER_MAX. В какой тип результат записывать?

signed_max

На остальные вопросы отвечал уже 20 раз.

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

Приводить доп аргументы я устал.

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

Могли бы вы привести реальный пример, в котором вы смешиваете в одном арифметическом выражении индексы в массиве с чем-то еще (например, количеством проданного металлолома), а на выходе у вас опять получаются индексы в массиве?

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

Правда думаешь, что не догадываюсь о том, что int не включает весь диапазон unsigned?

Блеяние про «родительское» множество ты уже забыл?

Без него твои поделки начали бы падать еще в далекие времена x32.

Мои поделки я собираю с -Wall -Wextra -Werror.

Складываю THE_WIDEST_INT_TYPE_EVER_MAX и THE_WIDEST_INT_TYPE_EVER_MAX. В какой тип результат записывать?

signed_max

Ты из себя дурачка строишь? Складываю SIGNED_MAX и SIGNED_MAX, в какой тип мне результат записывать? Почему тебя overflow не волнует, а касты волнуют?

Ты занимаешься полной ерундой, за которую яростно цепляешься. На это попросту смешно смотреть. Пойми наконец, что тебе нужен bigint, и пользуйся им.

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

Блеяние про «родительское» множество ты уже забыл?

Ты меня как-то по диагонали читал? Цитирую себя:

Беззнаковые не подчиняются правильным правилам каста в родительское множество.

Правильно - каст в знаковый тип достаточного размера, я и пишу - не подчиняются. Это как 3+3.0 кастуется в double. Хз чего ты придираешься.

Мои поделки я собираю с -Wall -Wextra -Werror.

Значит тебя ждет сюрприз - туда не входит -Wsign-conversion

Почему тебя overflow не волнует, а касты волнуют?

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

Ты занимаешься полной ерундой, за которую яростно цепляешься. На это попросту смешно смотреть. Пойми наконец, что тебе нужен bigint, и пользуйся им.

Нет, я вполне доволен собственными костылем + ssize(). Но понимаю, что в языке здесь проблема, которую хорошо бы поправить.

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

Могли бы вы привести реальный пример, в котором вы смешиваете в одном арифметическом выражении индексы в массиве с чем-то еще (например, количеством проданного металлолома), а на выходе у вас опять получаются индексы в массиве?

А почему вы меня вгоняете именно в такие рамки? Я себя так не ограничивал. Приведу другой пример - хочу взять int’овую ширину экрана, вычесть uint длину некоторой строки, которую буду печатать и на выходе получить длину добивки и передать в string::insert, которая ожидает uint. Как вы и хотели: string.insert(unsigned(int - usigned)). Не говорите больше, что я не привел примеров.

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

взять int’овую ширину экрана

У тебя какие-то проблемы, проверься. Ширина экрана также выражается беззнаковым.

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

О мой бог, я думал, что это только растонутые такие … man COLS

#include <curses.h>
       int COLOR_PAIRS;
       int COLORS;
       int COLS;

Можно получить проблемы в любом математическом выражении a-b+c*q+m …, ты уверен, что среди членов нет uint? Ок, хочешь страдать, проверяй каждый член на соответствие нужному диапазону и делай 100500 проверок, я же просто всё в интах буду делать, а в случае чего - воринг получу от Wsign-conversion.

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

А почему вы меня вгоняете именно в такие рамки?

Потому что только в этих рамках разговор об знаковых или беззнаковых индексах/размерностях имеет смысл.

Я себя так не ограничивал.

Возможно, в этом и есть корень проблемы. В смысле вам лень напрягаться и хочется, чтобы все автоматически и правильно. Но вы в C++, здесь такие фокусы не прокатывают (отчасти из-за темного наследия чистой ламповой сишечки).

Приведу другой пример - хочу взять int’овую ширину экрана, вычесть uint длину некоторой строки, которую буду печатать и на выходе получить длину добивки и передать в string::insert, которая ожидает uint.

Тут, как минимум, два вопроса вам хочется задать:

  1. Почему вы уверены, что в int-овой ширине экрана у вас будет строго положительное значение? Может там -1?

  2. Почему для вас проблема сразу привести все значения к одному типу (или к одному семейству типов, скажем, все к знаковым целым или все к беззнаковым целым)?

Впрочем, обо всем этом slovazap уже писал, но вы, такое ощущение, вообще не восприняли то, о чем он вам говорил.

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

Почему для вас проблема сразу привести все значения к одному типу (или к одному семейству типов, скажем, все к знаковым целым или все к беззнаковым целым)?

Т.е. так:

f(auto a, b, c, d, e) {
    return static_cast<int>(a) +
           static_cast<int>(b) +
           static_cast<int>(c) +
           static_cast<int>(d) +
           static_cast<int>(e);
}

действительно, нужно подумать над этим )

Почему вы уверены, что в int-овой ширине экрана у вас будет строго положительное значение? Может там -1?

Да не в том вообще дело какой там индекс юзать или какого типа размер предать, а в том, что когда начинаешь пускать в код unsigned на равных с signed (не где-то для масок, сдвигов, под чутким надздором как за неблагонадёжным), то рано или поздно получишь такое:

auto call = [](auto t, auto k) {
    cout << (-2 + t + k) << endl;
};
call(1u, 1); // 0
call(2u, 1); // 1

call(1u, 1L); // 4294967296
call(2u, 1L); // 1

когда через t пролез какой-нибудь размер массива или подобное, причем тип результирующего (-2 + t + k) == long, и он полное право имеет быть любым и даже отрицательным.

Всему виной - правила, которые стоило бы переписать. Заканчиваю.

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

Т.е. так:

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

что когда начинаешь пускать в код unsigned на равных с signed (не где-то для масок, сдвигов, под чутким надздором как за неблагонадёжным), то

Пожалуйста, придерживайтесь в разговоре всего лишь одной узкой темы, а именно обоснованность применения знаковых чисел для индексов и размерностей. Не смешения unsigned с signed вообще, а именно знаковые индексы/размерности. Именно же к этому относится ssize из вашего стартового пука в лужу.

когда через t пролез какой-нибудь размер массива или подобное, причем тип результирующего (-2 + t + k)

Блин, в n+1 раз вынужден указать на то, что суть именно в том, почему у вас индексы/размерности вдруг утекают в арифметические выражения, где есть еще какая-то неведомая хрень.

Т.е. вы тупо не можете различить в своем коде, где у вас помидоры, а где апельсины. И складываете хз что с хз с чем. Просто потому, что так вышло.

Не удивительно, что результаты вас обескураживают.

PS. Возможно, со временем вы обнаружите, что ни int, ни long не дают никаких гарантий на то, что в них может поместиться. И вы создадите тему «Вот вы сидите и не знаете, что есть int_least64_t».

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

Всему виной - правила, которые стоило бы переписать.

Компилятор вам доверяет и уважает ваш код

auto call = [](auto t, auto k) {
    cout << (-2 + t + k) << endl;
};

Что написали, то и получили.

anonymous
()

Из цопепе-коре-гуайдланс (под редакцией неких Страуструпа и Саттера):

ES.106: Don’t try to avoid negative values by using unsigned

ES.107: Don’t use unsigned for subscripts, prefer gsl::index

(https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#es106-dont-try-to-avoid-negative-values-by-using-unsigned)

Для самых одаренных в этом классе: я вашей мамой клянусь, вы в жизни не создадите вектор длиннее максимальной размерности size_t. Альтернативно одаренная часть аудитории, я с удовольствием послушаю ваш спич о платформозависимости его размера, а также «а вдруг где-нибудь не хватит».

Отдельный привет той части аудитории, которая считает, что спецификатор unsigned есть экспрессия логической позитивности некоего значения. Ходьба по минному полю: on.

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

Дошколёнок спалился на «вектор длиннее максимальной размерности size_t» - это просто перепаста без смысла, эникей ничего не знает. Нормальный пацан сообщил бы сразу о PTRDIFF_MAX + 1UL.

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

Признаю, обосрався в порыве наброса. Должно было быть так: «вектор длиннее максимального значения signed size_t».

PTRDIFF_MAX + 1UL

В плюсах индексы и длина вектора обычно через size_t определяются.

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