size_t
технически не является правильным выбором, так как он может быть недостаточно большим. Итераторам разрешено перебирать «что-то», что больше любого объекта в памяти — например, файл на диске. Когда они это сделают, итератор может определить тип больше size_t
как свой difference_type
, если он доступен.
difference_type
необходимо подписать, поскольку в контекстах, отличных от std::count
, он представляет смещения между итераторами в обоих направлениях. Для итераторов с произвольным доступом it + difference
является совершенно разумной операцией, даже если difference
отрицательно.
iterator_traits
не предлагает тип без знака. Возможно, так и должно быть, но, учитывая, что это не так, iterator_traits<InputIterator>::difference_type
это лучший доступный тип.
Вопрос о том, должны ли итераторы предлагать беззнаковый тип, вероятно, связан с массовым конфликтом стилей кодирования, следует ли вообще использовать беззнаковые типы для подсчета. Я не предлагаю воспроизводить этот аргумент здесь, вы можете посмотреть его. У ptrdiff_t
есть недостаток, заключающийся в том, что в некоторых системах он не может представить все допустимые различия указателей и, следовательно, не может представить все ожидаемые результаты std::count
.
Насколько я могу судить, даже в C++03 стандарт фактически запрещал это, может быть, случайно. 5.7/6 говорит о том, что вычитание может привести к переполнению ptrdiff_t
, как это делает C. Но в таблице 32 (требования к распределителю) сказано, что X::difference_type
может представлять разницу между любыми двумя указателями, а std::allocator
гарантированно использует ptrdiff_t
в качестве своего difference_type
(20.1.5/4). С++ 11 аналогичен. Таким образом, одна часть стандарта считает, что вычитание указателя может переполнить ptrdiff_t
, а другая часть стандарта говорит, что не может.
std::count
предположительно был разработан в соответствии с тем же (возможно, ошибочным) предположением, что и требования распределителя, что ptrdiff_t
достаточно велико, чтобы выразить размер любого объекта, и (в общем) difference_type
итератора может выражать количество итерандов между любыми двумя итераторами.
person
Steve Jessop
schedule
11.02.2013
iterator_traits<InputIterator>::difference_type
. - person Flexo   schedule 21.09.2011iterator_traits<InputIterator>::difference_type
- это typedef дляptrdiff_t
- person Samaursa   schedule 21.09.2011InputIterator
— это параметр шаблона. - person Fred Larson   schedule 21.09.2011Allocator::max_size()
для распределителя, используемого с вашим контейнером? Я подозреваю, что это не проблема для всего, кроме возможноchar
, у которого может быть другая специализация. - person Flexo   schedule 21.09.2011int
для итерации через контейнерvector
... до тех пор, пока у вас не будет контейнера, достаточно большого, чтобы выйти за пределы диапазонаint
. - person Samaursa   schedule 21.09.2011char
. Могу поспорить, чтоiterator_traits::difference_type
уже существовал, когда это было добавлено (оно было добавлено после другого более старого вариантаcount
), и они не хотели принудительно обновлять каждую специализациюiterator_traits
. Я не могу найти точную точку, в которой это было добавлено (хотя я ищу), но если сделать это без добавления еще одногоtypedef
, область изменения будет очень локальной. - person Flexo   schedule 21.09.2011iterator_traits
дает вам свободу иметь типы, которые не простоstd::size_type
. - person Flexo   schedule 21.09.2011ptrdiff_t
не имеет преимущества передsize_t
, только недостаток. - person Samaursa   schedule 21.09.2011std::size_t
имеет серьезный недостаток: целочисленный тип не может меняться в зависимости от типа итератора. - person André Caron   schedule 21.09.2011difference_type
является определением типаptrdiff_t
, не имеет смысла. Конечно, я могу изменить это для своих собственных итераторов, но зачем выбиратьptrdiff_t
для стандартных итераторов? - person Samaursa   schedule 21.09.2011difference_type
мог указать разницу между любыми двумя итераторами, даже если разница была отрицательной. - person Mark Ransom   schedule 21.09.2011