Must size() == end() - begin()? А как насчет трансляции? - программирование
Подтвердить что ты не робот

Must size() == end() - begin()? А как насчет трансляции?

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

В этом контексте, если у меня есть контейнер с итераторами с произвольным доступом, безопасно ли мне выполнять static_cast между его значениями difference_type и size_type по желанию, исходя из того, что end() - begin() должен всегда быть равным size(), когда он ливается?

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

Все, что я должен соблюдать перед литьем (например, потеря данных)?

4b9b3361

Ответ 1

Здесь, что С++ 11 должен сказать по-разному:

§ 23.2.1

Expression: difference_type
Return Type: signed integer type
Operational Semantics: -
Assertion/note, pre-/post-condition: is identical to the difference type of iterator and const_iterator
Complexity: compile-time

Expression: size_type
Return Type: unsigned integer type
Operational Semantics: -
Assertion/note, pre-/post-condition: size_type can represent any non-negative value of difference_type
Complexity: compile-time

Expression: size()
Return Type: size_type
Operational Semantics: distance(begin(),end()) 
Assertion/note, pre-/post-condition: -
Complexity: constant

Убедитесь, что size() эквивалентен end() - begin():

§ 24.4.4/4

distance():
Effects: If InputIterator meets the requirements of random access iterator, 
returns (last - first); otherwise, returns the number of increments needed 
to get from first to last

Так как ваш контейнер имеет итераторы с произвольным доступом, это верно. Это что. Как вы можете видеть в первом окне,

size_type can represent any non-negative value of difference_type

Из этого мы имеем, что приведение от difference_type до size_type должно быть справедливым для всех неотрицательных значений.

Ответ 2

Я не думаю, что это всегда безопасно. Эта историческая проблема существовала с момента первой спецификации языка C, где ptrdiff_t не гарантировало охват всего положительного диапазона size_t. По понятным причинам этот вопрос переносится на спецификацию std::vector.

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

Однако связь между size() и end() - begin() для стандартного контейнера может быть гарантирована другими способами. Реализация может налагать свои собственные ограничения на максимальный размер контейнера, который открывается через функцию container::max_size(). Он может искусственно ограничивать максимальный размер, чтобы убедиться, что вычитание никогда не переполняется.

P.S. Я бы сказал, что причиной существования difference_type является только знак и ничего больше. Чтобы быть полностью "безопасным" difference_type, должно быть на 1 бит больше, чем size_type. Это часто бывает трудно реализовать на практике, поэтому он не требуется по языковой спецификации.