Давайте рассмотрим очень базовый класс адаптера диапазона, который охватывает диапазон и выполняет итерации по всем другим элементам исходного диапазона, если вы выполняете итерацию по адаптеру.
for (const auto & e : everyOtherElement(originalRange))
При написании такого класса адаптера диапазона необходимо написать соответствующий класс итератора для этого адаптера, чтобы сделать его итеративным и вести себя так, как нужно.
Такой класс итератора должен реализовывать все, что требуется для «концепции», которую вы хотите поддерживать, например InputIterator
. Среди прочего, мы должны реализовать operator*
вернуть ссылку на представленный элемент, а также operator->
такой, что it->member
доступ к членам этого элемента.
Я подумал, что было бы хорошей идеей просто «переслать» эти операторы в реализацию базового итератора, который оборачивает адаптер (давайте на минутку забудем о постоянстве):
struct everyOtherElement {
OriginalIterator b, e; // The begin and end we wrap around
// ...
struct iterator {
OriginalIterator it;
auto operator*() { return *it; } // <------
auto operator->() { return it.operator->(); } // <------
// ...
};
};
Тем не менее operator->
не скомпилируется, если OriginalIterator
имеет тип указателя, как для большинства std::vector
реализации и, конечно, сырые массивы. Поскольку такие итераторы не являются типами классов, запись не допускается. it.operator->()
,
Как я должен реализовать operator->
сделать итератор максимально прозрачным? Должен ли я реализовать operator->
с точки зрения operator*
то есть просто писать (*it).m
вместо it->m
, Я полагаю, что это не удастся, если какой-то итератор реализует их, чтобы означать разные вещи … (Хотя это было бы плохо, не так ли? Или это запрещено InputIterator
концепция?)
Это хорошая идея, чтобы реализовать его как просто возвращая оригинальный итератор, так как operator->
рекурсивно применяется автоматически до тех пор, пока возвращается не указатель?
auto operator->() { return it; }
Смотрите, например, стандартную спецификацию адаптеров итераторов. move_iterator:
pointer Iterator
они определяют pointer
введите как Iterator
и действительно верни это оператором ->
Других решений пока нет …