В C++20 для получения подписанный размер контейнера для универсального кода. (И причина его добавления объясняется здесь.)
Несколько странно, что приведенное здесь определение (в сочетании с common_type
и ptrdiff_t
) заставляет возвращаемое значение быть либо ptrdiff_t
, либо подписанной формой возвращаемого значения size()
контейнера, в зависимости от того, что больше.
P1227R1 косвенно предлагает обоснование это (для std::ssize() было бы катастрофой преобразовать размер 60 000 в размер -5 536).
Однако мне кажется, что это странный способ попытаться это исправить.
- Containers which intentionally define a
uint16_t
size and are known to never exceed 32,767 elements will still be forced to use a larger type than required.- The same thing would occur for containers using a
uint8_t
size and 127 elements, respectively. - В среде рабочего стола вам, вероятно, все равно; но это может быть важно для встроенных или других сред с ограниченными ресурсами, особенно если результирующий тип используется для чего-то более постоянного, чем переменная стека.
- The same thing would occur for containers using a
- Контейнеры, которые используют размер по умолчанию
size_t
на 32-разрядных платформах, но которые, тем не менее, содержат элементы размером от 2 до 4 миллиардов, столкнутся с той же проблемой, что и выше. - Если все еще существуют платформы, для которых
ptrdiff_t
меньше 32 бит, они также столкнутся с той же проблемой.
Не лучше ли было бы просто использовать подписанный тип как есть (без увеличения его размера) и assert
, чтобы не произошла ошибка преобразования (например, чтобы результат не был отрицательным)?
Я что-то упускаю?
Чтобы немного расширить это последнее предложение (вдохновленное ответом Никола Боласа): если бы оно было реализовано так, как я предложил , то этот код будет Just Work™:
void DoSomething(int16_t i, T const& item);
for (int16_t i = 0, len = std::ssize(rng); i < len; ++i)
{
DoSomething(i, rng[i]);
}
Однако в текущей реализации это приводит к предупреждениям и/или ошибкам, если только static_cast
s не добавляются явно, чтобы сузить результат ssize
, или использовать вместо этого int i
, а затем сузить его в вызове функции (и индексации диапазона), ни одно из которых не кажется как улучшение.
size()
что-либо, кроме (любого псевдонима)std::size_t
- person Caleth   schedule 22.05.2019