`iterator` и` const_iterator` не являются обязательными членами контейнеров STL? - PullRequest
2 голосов
/ 16 января 2020

Взято из Понимание реализации итератора / const_iterator :

", хотя iterator и const_iterator являются типами, объявленными в области действия vector, требования отсутствуют что vector (или любой контейнер STL) имеет член любого типа - iterator и const_iterator являются частью интерфейса std::vector, например, перегрузки члена begin() возвращают эти типы, но ничего не сказано о как эти функции получают итератор, который они возвращают "

Кроме того, контейнеры STL должны иметь:

" функцию начала и конца, которая возвращает итераторы "

Выше указано, что iterator и const_iterator не являются обязательными членами контейнера STL, например vector. Я предполагаю, что это означает, что тип, возвращаемый из .begin или .end, будет отличаться в зависимости от реализации.

Поэтому мне интересно, почему это не проблематично c, поскольку я вижу, как многие люди пишут std::vector<someType>::iterator или std::vector<someType>::const_iterator где iterator и const_iterator указаны вместо использования auto, например:

for (std::vector<int>::iterator i = s.begin(); i != s.end(); i++)
{

}

Ответы [ 2 ]

7 голосов
/ 16 января 2020

Вы читаете цитату неправильно. Человек говорит, что

имеет член любого типа

не

имеет любой тип

Когда они говорят, что имеют члена любого типа , они означают, что в классе нет члена данных типа iterator или const_iterator.

Они делают go, чтобы сказать

iterator и const_iterator являются частью интерфейса std::vector

Что является правильным, так как стандарт требует, чтобы std::vector отображал эти типы в этом интерфейсе.

2 голосов
/ 16 января 2020

std::vector обычно будет содержать typedef (или, что эквивалентно, using) для указания типа, к которому будет относиться имя iterator. В простейшем случае это может быть что-то вроде:

template <class T, class Allocator>
class vector {
    using iterator = T *;
    using const_iterator = T const *;
    // ...
};

Аналогично, его begin и end должны возвращать iterator с, а его cbegin и cend должны возвращать const_iterator s. Но векторный объект не обязательно должен содержать какие-либо объекты типа iterator или const_iterator.

Также обратите внимание, что хотя имена vector::iterator и vector::const_iterator должны быть определены, не обязательно, чтобы они определялись самим vector. Вы можете (например) иметь вектор, производный от базового класса, определяющий соответствующие имена:

template <class T>
class vector_base {
public:
    using iterator = T*;
    using const_iterator = T const *;
    // ...
};

template <class T, class Allocator>
class vector : public vector_base<T> {
};

Итак, даже если vector сам по себе не определяет iterator, имя vector::iterator определено правильно. Вероятно, я бы не стал упоминать об этом, за исключением одного момента: хотя это не относится к vector, существует стандартный класс с именем std::iterator, который был задуман в основном как базовый класс для итераторов, и большая часть того, что он делал, была в значительной степени описана выше - определял определения типов членов для value_type, difference_type, reference и т. д. Его использование в настоящее время считается устаревшим, но все еще имеется достаточное количество более старых классов итераторов, которые его использовали (а более старые версии стандарта по крайней мере подразумевали, что большинство стандартных типов итераторов также должны использовать его).

...