Чому в C ++ 20 вводиться std :: ssize ()?


99

C ++ 20 представив std::ssize()безкоштовну функцію, як показано нижче:

template <class C>
    constexpr auto ssize(const C& c)
        -> std::common_type_t<std::ptrdiff_t,
                              std::make_signed_t<decltype(c.size())>>;

Можлива реалізація, схоже, використовує static_castдля перетворення повернутого значення size()функції члена cl ass C в його підписаний аналог.

Оскільки size()функція члена C завжди повертає негативні значення, чому б хто-небудь хотів зберігати їх у підписаних змінних? У випадку, якщо хтось дійсно хоче, це справа просто static_cast.

Чому std::ssize()вводиться в C ++ 20?


4
@ Jarod42 Чи не визначено це реалізацію замість невизначеної? (переповнення підпису не визначено. Але конверсія підписана визначена реалізацією)
phön

8
Якщо тільки вони додають ssizeofоператора.
Геза

3
Це може бути кілька пов'язаних: stackoverflow.com/questions/30395205 / ...
Marco13

10
@ JohnZ.Li Загрожуючи звучати занадто неконструктивно: я думаю, що вся система типів C ++ стосовно цілих типів порушена. Звичайно, можна стверджувати, що деякі примхи (як-от невідомо, скільки бітів charмає) успадковуються від C і принаймні дещо полегшуються (u)intX_t, але це все-таки нескінченне джерело однаково тонких і критичних помилок. Такі речі ssizeє лише виправленнями, і це займе певний час (можливо, "назавжди"), поки це не зануриться в загальні "посібники з найкращих практик", яких люди (можуть) суворо дотримуватися.
Marco13

6
@ Marco13: З іншого боку, C / C ++ типу система (на відміну від системи фіксованих типів , наприклад , в Java), в стороні від вирішення C / C ++ коду для роботи на архітектурі , де більшість інших мов квакати, це дозволить компетентним викладачам , щоб отримати якісь - то важливі уроки в голову учня. Мовляв, не весь світ 64-бітний. І ні, не весь світ використовує 8-бітні символи. З цими речами легко впоратися, і це робить тебе кращим розробником, якби тільки інструктори навчали б це з самого початку . (І, просто щоб переконатися, ви дійсно знаєте , що (u)intX_tтипи необов'язково , що не так чи що?)
DevSolar

Відповіді:


69

Обґрунтування описано в цій роботі . Цитата:

Коли проміжок було прийнято в C ++ 17, воно використовувало підписане ціле число і як індекс, і як розмір. Частково це полягало в тому, щоб дозволити використовувати "-1" в якості дозорного значення для позначення типу, розмір якого не був відомий під час компіляції. Але мати контейнер STL, функція якого розмір () повертає підписане значення, було проблематичним, тому P1089 було введено для "виправлення" проблеми. Він отримав підтримку більшості, але не граничну величину 2 на 1, необхідну для досягнення консенсусу.

У цьому документі P1227 було запропоновано додати функції non-member std :: ssize та member ssize (). Включення цих даних зробило б певний код набагато простішим і дозволило б уникнути небажаних непідписаних підрахунків розмірів. Ідея полягала в тому, що стійкість до P1089 зменшиться, якщо ssize () буде доступний для всіх контейнерів, як через std :: ssize (), так і як член-функції.


30
for(int i = 0; i < container.ssize() - 1; ++i)Приклад також досить переконливий
Caleth

7
@John мені здається, що вони могли зробити те ж саме, що і string :: npos і просто використовувати size_t (-1) як спеціальне значення.
rubenvb

15
@ JohnZ.Li Вже довго вважається помилкою, що типи розмірів STL не підписані. Зараз, на жаль, уже пізно реформувати це. Надання безкоштовної функції - це найкраще, що ми можемо зробити зараз.
LF

16
@LF: Це була Герб Саттер на конференції (можливо, Бжарн це також сказав). Але, він трохи помиляється. Тепер із 32-бітними / 64-бітними комп'ютерами розмір підписаних даних буде краще (значить, він правий). Але в старі часи (16-розрядні розміри) розмір підписаних даних був би поганим (наприклад, ми могли виділити лише 32k байтові масиви).
Геза

11
@LF: Я знайшов згадування Герба про це: youtube.com/watch?v=Puio5dly9N8&t=2667 . Коли він каже, що "не дуже добре на практиці", це актуально в наш час. Але це було неправдою> 20 років тому (16-бітні системи) взагалі. Отже, не було великою помилкою використання без підпису, коли проект було розроблено.
Геза

50

Безкоштовно вкрадено у Еріка Ніблера:

'Unsigned types signal that a negative index/size is not sane'була переважаюча мудрість, коли STL вперше був розроблений. Але логічно, що кількість речей не повинна бути позитивною. Я можу захотіти зберегти кількість підписаних цілих чисел, щоб позначити кількість елементів, доданих до колекції або вилучених з них. Тоді я хотів би поєднати це з розміром колекції. Якщо розмір колекції не підписаний, тепер я змушений змішувати арифметику з підписами та без підпису, що є фермою помилок. Укладачі попереджають про це, але оскільки дизайн STL в значній мірі змушує програмістів в цій ситуації, попередження настільки поширене, що більшість людей його вимикають. Це прикро, бо в цьому ховаються справжні помилки.

Використання неподписаних вкладишів в інтерфейсах не є вигодою, що багато хто думає, що це так. Якщо випадково користувач передає в API трохи негативне число, воно раптом стає величезним додатним числом. Якби API прийняв число як підписане, то він може виявити ситуацію, стверджуючи, що число більше або дорівнює нулю.

Якщо ми обмежимо використання безпідписаних вхідних даних до подвійного подвійного використання (наприклад, масок) і використовуємо підписані вставки скрізь в інших місцях, помилки рідше трапляються і їх легше виявити, коли вони виникають.


6
Свіфт застосовує такий підхід, хоча він не турбується про те, щоб негативні підписані номери переосмислювались як масивні безпідписані номери (оскільки немає неявних кастингу, саме з чого насправді ви потрапите в цей божевільний будинок веселощів). Вони просто застосовують підхід (розмір машинного слова) Intмає бути загальним типом валюти цілих чисел, навіть коли сенс мають лише позитивні числа (наприклад, індексація масиву). Будь-яке відхилення від нього повинно бути обґрунтованим. Приємно не потрібно всюди турбуватися про касти.
Олександр -

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.