tgoop.com/cxx95/54
Create:
Last Update:
Last Update:
#madskillz
Итераторы с неопределенным концом 🏁
Итераторы это одна из главных концепций C++. У каждого класса контейнера (set/vector/list/...) в C++ есть свой соответствующий класс итератора (для доступа к своим данным).
Класс, для которого определен итератор, должен иметь методы begin()
и end()
, по вызову которых отдаются объекты итератора.
Класс итератора должен иметь методы operator++()
и operator*()
.
Наличия этих методов достаточно для использования итератора в разных стандартных методах и в range-based for loop.
Обычно итераторы итерируются по всем объектам от begin()
до end()
:
const std::vector<int> vec{1, 3, 5, 7, 9};Однако бывают случаи, когда
// внизу аналог выражения `for (int value : vec) { /* ... */ }`
auto __begin = vec.begin();
auto __end = vec.end();
for ( ; __begin != __end; ++__begin) {
int value = *__begin;
/* do something with `value`... */
}
end()
нельзя вычислить заранее и нужно делать на каждом шагу проверку, не пора ли выходить из цикла. В стандарте C++20 встречается такой костыль:1️⃣ Завести пустой мусорный класс std::default_sentinel_t
2️⃣ Метод
end()
класса-"контейнера" должен отдавать объект мусорного классаstd::default_sentinel_t end() {(а метод
return {};
}
begin()
продолжает отдавать объект итератора)3️⃣ Класс итератора должен определить оператор сравнения с объектом мусорного класса:
bool operator==(std::default_sentinel_t) const {В итоге старый код с итераторами работает как прежде, но завершается только когда оператор сравнения вернет
return /* какое-то условие */;
}
true
.Какие есть реально используемые use cases:
🎯 std::counted_iterator - обертка над каким-нибудь другим итератором, итерируется по не более чем
N
элементам🎯 Поддержка range-based for для корутин - чтобы можно было в цикле забирать новые значения от корутины, пока она активна (класс итератора -
class Iter
)BY C++95
Share with your friend now:
tgoop.com/cxx95/54