What You'll Learn
- Build STL-compatible iterators
- Iterator categories and type aliases
- Container iterators for custom data
- C++20 Ranges and composable pipelines
Building Custom Iterators & Using Ranges
Iterators are the glue between containers and algorithms in C++. By implementing the iterator protocol (begin(), end(), operator++, operator*), your custom types work with range-based for, STL algorithms, and C++20 Ranges — the most powerful composition feature in modern C++.
Building a Range Iterator
A custom Range class generates numbers lazily — no vector allocation, no storage. It just needs begin() and end() that return iterator objects supporting operator*, operator++, and operator!=.
Pro Tip: Always define the five type aliases (iterator_category, value_type, etc.) — std::iterator_traits needs them for STL algorithm compatibility.
Range Iterator
Lazy number generation with custom iterators
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
// A custom range that generates numbers on-the-fly
class Range {
int start_, end_, step_;
public:
Range(int start, int end, int step = 1)
: start_(start), end_(end), step_(step) {}
// Iterator class nested inside Range
class Iterator {
int current, step;
public:
// Required type aliases for STL compatibility
using iterator_category = input_iterator_tag;
u
...Container Iterators
Custom containers need iterators to work with range-based for. A linked list iterator traverses nodes by following next pointers. The key is making end() return an iterator pointing to nullptr — the sentinel value.
Linked List Iterator
Build a linked list with STL-compatible iteration
#include <iostream>
#include <string>
using namespace std;
// Custom linked list with STL-compatible iterator
template<typename T>
class LinkedList {
struct Node {
T data;
Node* next;
Node(const T& d) : data(d), next(nullptr) {}
};
Node* head = nullptr;
int sz = 0;
public:
~LinkedList() {
while (head) { auto* tmp = head; head = head->next; delete tmp; }
}
void pushFront(const T& val) {
auto* node = new Node(val);
node
...C++20 Ranges — Composable Pipelines
Ranges transform data processing from imperative loops into declarative pipelines: filter → transform → take. Views are lazy — they don't allocate memory or process elements until iterated. This is the future of C++ data processing.
Common Mistake: Storing a view that references a temporary container. Views are non-owning — if the source is destroyed, the view is dangling. Always ensure the source outlives the view.
Ranges Pipelines
Filter, transform, and take with composable operations
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <numeric>
using namespace std;
// C++20 Ranges preview — composable, lazy data pipelines
// Real ranges use: #include <ranges> with views::filter, views::transform
// Simulated range adaptors
template<typename Container, typename Pred>
vector<typename Container::value_type> filter(const Container& c, Pred pred) {
vector<typename Container::value_type> result;
for (const auto& x : c) if (pred(x)) resul
...Quick Reference
| Category | Operations | Example |
|---|---|---|
| Input | Read, advance (single pass) | istream_iterator |
| Forward | Read, advance (multi pass) | forward_list::iterator |
| Bidirectional | Forward + backward | list::iterator |
| Random Access | Jump to any position | vector::iterator |
Lesson Complete!
You can now build custom iterators, create iterable containers, and use range-style pipelines.
Sign up for free to track which lessons you've completed and get learning reminders.