template<class It>void advance_impl(It& it, int n, std::random_access_iterator_tag) { it += n; // O(1) — only legal here}template<class It>void advance_impl(It& it, int n, std::bidirectional_iterator_tag) { if (n >= 0) while (n--) ++it; // O(n) else while (n++) --it;}template<class It>void advance_impl(It& it, int n, std::input_iterator_tag) { while (n--) ++it; // O(n), forward only}template<class It>void advance(It& it, int n) { advance_impl(it, n, typename std::iterator_traits<It>::iterator_category{});}
Why this step? The empty tag object's type selects the overload at compile time — zero runtime cost, yet each container gets its optimal algorithm. This is the whole point of the hierarchy.
sort needs random-access iterators; list's are bidirectional — use list::sort() instead.
What category does forward add over input?
Multi-pass: you can copy an iterator and re-traverse.
Recall Feynman: explain to a 12-year-old
Imagine different toy boxes. A scroll of paper you can only read once as it unrolls — that's an input iterator. A stamp that only prints, never reads — that's output. A train on a one-way track that you can ride again from the start is forward. A train that can also reverse is bidirectional. A teleporter that jumps straight to seat #50 is random access. And if all the seats are bolted in one straight row with no gaps, that's contiguous. The fancier the toy, the more it can do — and the STL picks the cheapest trick each toy allows.
Socho iterator ek "smart pointer" hai jo kisi bhi container — vector, list, set, stream — ke upar same tareeke se chalne deta hai. Iska sabse bada faayda: STL algorithms (jaise sort, find, copy) ko ek hi baar likho, aur har container pe chal jaate hain, kyunki sab container iterators expose karte hain. Yahi decoupling C++ ko itna powerful banata hai.
Ab har container same speed se sab kuch nahi kar sakta, isliye iterators ki categories hoti hain. Sabse kamzor Input (sirf padho, ek baar) aur Output (sirf likho, ek baar). Uske upar Forward — dobara ghoom sakte ho. Phir Bidirectional — peeche bhi ja sakte ho (--it), jaise list aur set. Phir Random Access — seedha 50th element pe jump, it+n, O(1) mein, jaise vector aur deque. Aur sabse top Contiguous — elements ek hi continuous memory block mein, isliye &v[0] ko C function ko de sakte ho; ye sirf vector, array, string deti hain.
Important trap: deque random-access hai par contiguous nahi, kyunki uska data alag-alag chunks mein hota hai. Aur list ko std::sort se sort nahi kar sakte kyunki uske iterators sirf bidirectional hain — uske liye list.sort() use karo. std::advance ek hi naam se vector ke liye O(1) aur list ke liye O(n) kaise karta hai? Compile-time pe tag dispatch se — iterator ka category tag dekh kar sahi version chun leta hai. Yahi poori hierarchy ka asli maqsad hai: har container ko uska sabse fast algorithm mil jaaye.