cpp
iterators
01_iterators.cpp⚙️cpp
/**
* ============================================================
* C++ STL ITERATORS
* ============================================================
*
* This file covers:
* - Iterator categories
* - Iterator operations
* - Const and reverse iterators
* - Iterator adaptors
* - Custom iterators
* - Modern range-based iteration
*
* Compile: g++ -std=c++17 -Wall 01_iterators.cpp -o iterators
* Run: ./iterators
*
* ============================================================
*/
#include <iostream>
#include <string>
#include <vector>
#include <list>
#include <deque>
#include <set>
#include <map>
#include <array>
#include <forward_list>
#include <iterator>
#include <algorithm>
#include <numeric>
using namespace std;
// ============================================================
// MAIN FUNCTION
// ============================================================
int main() {
cout << "============================================" << endl;
cout << " C++ STL ITERATORS" << endl;
cout << "============================================" << endl << endl;
// ========================================================
// PART 1: ITERATOR BASICS
// ========================================================
cout << "--- PART 1: ITERATOR BASICS ---" << endl << endl;
vector<int> vec = {10, 20, 30, 40, 50};
// Using begin() and end()
cout << "Forward iteration with begin()/end():" << endl;
for (vector<int>::iterator it = vec.begin(); it != vec.end(); ++it) {
cout << *it << " "; // Dereference to get value
}
cout << endl;
// Using auto (preferred)
cout << "Using auto:" << endl;
for (auto it = vec.begin(); it != vec.end(); ++it) {
cout << *it << " ";
}
cout << endl;
// Modifying through iterator
cout << "Doubling values through iterator:" << endl;
for (auto it = vec.begin(); it != vec.end(); ++it) {
*it *= 2; // Modify through iterator
}
for (int x : vec) cout << x << " ";
cout << endl;
cout << endl;
// ========================================================
// PART 2: ITERATOR CATEGORIES
// ========================================================
cout << "--- PART 2: ITERATOR CATEGORIES ---" << endl << endl;
cout << "Iterator Hierarchy (most to least capable):" << endl;
cout << "─────────────────────────────────────────" << endl;
cout << "1. Random Access: vector, deque, array, string" << endl;
cout << " - Can jump anywhere: it + n, it - n, it[n]" << endl;
cout << " - Can compare: it1 < it2, it1 - it2" << endl;
cout << endl;
cout << "2. Bidirectional: list, set, map" << endl;
cout << " - Can go forward and backward: ++it, --it" << endl;
cout << endl;
cout << "3. Forward: forward_list, unordered_set/map" << endl;
cout << " - Can only go forward: ++it" << endl;
cout << endl;
cout << "4. Input: istream_iterator" << endl;
cout << " - Read-only, single pass" << endl;
cout << endl;
cout << "5. Output: ostream_iterator" << endl;
cout << " - Write-only, single pass" << endl;
cout << endl;
// Demonstrating random access
cout << "Random Access Iterator (vector):" << endl;
vector<int> v = {1, 2, 3, 4, 5};
auto it = v.begin();
cout << "it + 2 = " << *(it + 2) << endl;
cout << "it[3] = " << it[3] << endl;
cout << "(v.end() - v.begin()) = " << (v.end() - v.begin()) << endl;
// Bidirectional - no random access
cout << "\nBidirectional Iterator (list):" << endl;
list<int> lst = {1, 2, 3, 4, 5};
auto lit = lst.begin();
++lit; ++lit; // Move forward
cout << "After ++it twice: " << *lit << endl;
--lit; // Move backward
cout << "After --it: " << *lit << endl;
// lit + 2; // ERROR: not random access
cout << endl;
// ========================================================
// PART 3: CONST ITERATORS
// ========================================================
cout << "--- PART 3: CONST ITERATORS ---" << endl << endl;
vector<int> nums = {1, 2, 3, 4, 5};
// Regular iterator - can modify
cout << "Regular iterator (can modify):" << endl;
for (auto it = nums.begin(); it != nums.end(); ++it) {
*it += 10; // OK
}
for (int x : nums) cout << x << " ";
cout << endl;
// Const iterator - read only
cout << "\nConst iterator (read only):" << endl;
for (auto it = nums.cbegin(); it != nums.cend(); ++it) {
cout << *it << " ";
// *it = 0; // ERROR: cannot modify through const_iterator
}
cout << endl;
// On const container
const vector<int> constVec = {100, 200, 300};
cout << "\nIterating const container:" << endl;
for (auto it = constVec.begin(); it != constVec.end(); ++it) {
cout << *it << " "; // begin() returns const_iterator for const container
}
cout << endl;
cout << endl;
// ========================================================
// PART 4: REVERSE ITERATORS
// ========================================================
cout << "--- PART 4: REVERSE ITERATORS ---" << endl << endl;
vector<int> data = {1, 2, 3, 4, 5};
cout << "Forward: ";
for (auto it = data.begin(); it != data.end(); ++it) {
cout << *it << " ";
}
cout << endl;
cout << "Reverse: ";
for (auto it = data.rbegin(); it != data.rend(); ++it) {
cout << *it << " ";
}
cout << endl;
// Const reverse
cout << "Const reverse: ";
for (auto it = data.crbegin(); it != data.crend(); ++it) {
cout << *it << " ";
}
cout << endl;
// Converting reverse to forward iterator
auto rit = data.rbegin();
++rit; ++rit; // Points to 3 in reverse (element 2 from end)
auto fwd = rit.base(); // Convert to forward iterator (points to 4)
cout << "\nReverse iterator at 3, base() gives: " << *fwd << endl;
cout << endl;
// ========================================================
// PART 5: ITERATOR OPERATIONS
// ========================================================
cout << "--- PART 5: ITERATOR OPERATIONS ---" << endl << endl;
vector<int> ops = {10, 20, 30, 40, 50, 60, 70, 80, 90};
auto first = ops.begin();
auto last = ops.end();
// advance - moves iterator
cout << "advance(it, 3): ";
auto it1 = first;
advance(it1, 3);
cout << *it1 << endl;
// distance - counts elements between iterators
cout << "distance(begin, end): " << distance(first, last) << endl;
// next/prev - return new iterator
auto it2 = next(first, 2);
cout << "next(begin, 2): " << *it2 << endl;
auto it3 = prev(last, 3);
cout << "prev(end, 3): " << *it3 << endl;
// For bidirectional iterators
list<int> myList = {1, 2, 3, 4, 5};
auto lit2 = myList.begin();
advance(lit2, 2); // Works on bidirectional
cout << "\nadvance on list: " << *lit2 << endl;
cout << endl;
// ========================================================
// PART 6: INSERT ITERATORS
// ========================================================
cout << "--- PART 6: INSERT ITERATORS ---" << endl << endl;
vector<int> src = {1, 2, 3, 4, 5};
vector<int> dest;
// back_inserter - inserts at back
cout << "back_inserter:" << endl;
copy(src.begin(), src.end(), back_inserter(dest));
for (int x : dest) cout << x << " ";
cout << endl;
// front_inserter - inserts at front (requires push_front)
cout << "\nfront_inserter (deque):" << endl;
deque<int> dq;
copy(src.begin(), src.end(), front_inserter(dq));
for (int x : dq) cout << x << " "; // Reversed!
cout << endl;
// inserter - inserts at specific position
cout << "\ninserter at middle:" << endl;
vector<int> mid = {100, 200};
auto midIt = mid.begin() + 1; // After 100
copy(src.begin(), src.end(), inserter(mid, midIt));
for (int x : mid) cout << x << " ";
cout << endl;
cout << endl;
// ========================================================
// PART 7: STREAM ITERATORS
// ========================================================
cout << "--- PART 7: STREAM ITERATORS ---" << endl << endl;
// ostream_iterator - output
cout << "Using ostream_iterator:" << endl;
vector<int> output = {1, 2, 3, 4, 5};
copy(output.begin(), output.end(), ostream_iterator<int>(cout, " "));
cout << endl;
cout << "With different delimiter:" << endl;
copy(output.begin(), output.end(), ostream_iterator<int>(cout, ", "));
cout << endl;
// istream_iterator example (commented - would wait for input)
// cout << "Enter integers (Ctrl+D to end):" << endl;
// vector<int> input(istream_iterator<int>(cin), istream_iterator<int>());
cout << endl;
// ========================================================
// PART 8: ITERATOR WITH ALGORITHMS
// ========================================================
cout << "--- PART 8: ITERATORS WITH ALGORITHMS ---" << endl << endl;
vector<int> alg = {5, 2, 8, 1, 9, 3, 7, 4, 6};
// find
auto found = find(alg.begin(), alg.end(), 8);
if (found != alg.end()) {
cout << "Found 8 at position: " << distance(alg.begin(), found) << endl;
}
// find_if
auto evenIt = find_if(alg.begin(), alg.end(), [](int x) { return x % 2 == 0; });
cout << "First even: " << *evenIt << endl;
// count
cout << "Count of elements > 5: "
<< count_if(alg.begin(), alg.end(), [](int x) { return x > 5; }) << endl;
// sort
sort(alg.begin(), alg.end());
cout << "Sorted: ";
for (int x : alg) cout << x << " ";
cout << endl;
// binary_search (requires sorted)
cout << "binary_search(6): " << (binary_search(alg.begin(), alg.end(), 6) ? "found" : "not found") << endl;
// lower_bound/upper_bound
auto lb = lower_bound(alg.begin(), alg.end(), 5);
auto ub = upper_bound(alg.begin(), alg.end(), 5);
cout << "lower_bound(5) at index: " << distance(alg.begin(), lb) << endl;
cout << "upper_bound(5) at index: " << distance(alg.begin(), ub) << endl;
// accumulate
int sum = accumulate(alg.begin(), alg.end(), 0);
cout << "Sum: " << sum << endl;
cout << endl;
// ========================================================
// PART 9: MAP ITERATORS
// ========================================================
cout << "--- PART 9: MAP ITERATORS ---" << endl << endl;
map<string, int> scores = {
{"Alice", 95},
{"Bob", 87},
{"Charlie", 92}
};
// Iterating map
cout << "Map iteration:" << endl;
for (auto it = scores.begin(); it != scores.end(); ++it) {
cout << " " << it->first << ": " << it->second << endl;
}
// Structured bindings (C++17)
cout << "\nWith structured bindings:" << endl;
for (const auto& [name, score] : scores) {
cout << " " << name << ": " << score << endl;
}
// Finding in map
auto mapIt = scores.find("Bob");
if (mapIt != scores.end()) {
cout << "\nFound Bob with score: " << mapIt->second << endl;
}
cout << endl;
// ========================================================
// ITERATOR SUMMARY
// ========================================================
cout << "--- ITERATOR SUMMARY ---" << endl << endl;
cout << "Iterator Types:" << endl;
cout << "─────────────────────────────────────────" << endl;
cout << "iterator - Read/write forward" << endl;
cout << "const_iterator - Read-only forward" << endl;
cout << "reverse_iterator - Read/write backward" << endl;
cout << "const_reverse_iterator - Read-only backward" << endl;
cout << "\nObtaining Iterators:" << endl;
cout << "─────────────────────────────────────────" << endl;
cout << "begin()/end() - Forward iterators" << endl;
cout << "cbegin()/cend() - Const forward" << endl;
cout << "rbegin()/rend() - Reverse iterators" << endl;
cout << "crbegin()/crend() - Const reverse" << endl;
cout << "\nIterator Operations:" << endl;
cout << "─────────────────────────────────────────" << endl;
cout << "advance(it, n) - Move iterator n steps" << endl;
cout << "distance(it1,it2) - Count steps between" << endl;
cout << "next(it, n) - Return iterator n ahead" << endl;
cout << "prev(it, n) - Return iterator n behind" << endl;
cout << endl;
cout << "============================================" << endl;
cout << "STL ITERATORS COMPLETE!" << endl;
cout << "============================================" << endl;
return 0;
}
// ============================================================
// EXERCISES:
// ============================================================
/*
* 1. Create a function that:
* - Takes two iterators (any container)
* - Returns iterator to the middle element
* - Handle even/odd sizes
*
* 2. Implement a range class:
* - range(start, end, step)
* - Support begin()/end() for range-based for
* - Lazy evaluation (doesn't store values)
*
* 3. Create a filter iterator:
* - Wraps another iterator
* - Only yields elements matching predicate
* - Implement ++, *, ==, !=
*
* 4. Implement merge using iterators:
* - Take two sorted ranges
* - Output merged sorted sequence
* - Use only iterator operations
*/