Почему std :: ssize () введен в C ++ 20? - PullRequest
87 голосов
/ 20 мая 2019

C ++ 20 представил функцию std::ssize() free, как показано ниже:

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?

Ответы [ 2 ]

62 голосов
/ 20 мая 2019

Обоснование описано в этой статье . Цитата:

Когда span был принят в C ++ 17, он использовал целое число со знаком как индекс и размер. Частично это должно было позволить использовать «-1» в качестве значения часового, чтобы указать тип, размер которого не был известен во время компиляции. Но наличие контейнера STL, функция size () которого возвращала значение со знаком, было проблематичным, поэтому для устранения проблемы был введен протокол P1089. Он получил поддержку большинства, но не 2: 1, необходимый для достижения консенсуса.

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

40 голосов
/ 20 мая 2019

безвозмездно украденный от Эрика Ниблера:

'Unsigned types signal that a negative index/size is not sane' был преобладающей мудростью, когда был впервые разработан STL.Но логически, количество вещей не должно быть положительным.Я могу захотеть сохранить счет в целом числе со знаком, чтобы обозначить количество элементов, добавленных в коллекцию или удаленных из нее.Тогда я хотел бы объединить это с размером коллекции.Если размер коллекции не подписан, теперь я вынужден смешивать арифметику со знаком и без знака, которая является ошибочной фермой.Об этом предупреждают компиляторы, но поскольку дизайн STL в значительной степени заставляет программистов попадать в эту ситуацию, предупреждение настолько распространено, что большинство людей его отключают.Это позор, потому что это скрывает реальные ошибки.

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

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

...