C++98stlbeginner
std::iterator
C++98 · The Foundation · Compiler flag: -std=c++98
Explanation
Base class for defining custom iterators.
Real-World Scenario
Create a custom iterator for a user-defined container.
Quick Snippet
snippet.cpp
#include <iterator> class MyIterator : public std::iterator<std::forward_iterator_tag, int> {};Full Example
iterator.cpp
// CodeNebula - C++98 Example: iterator
// Compile: g++ -std=c++98 -Wall -Wextra -o example iterator.cpp
// In C++98, custom iterators can inherit from std::iterator to automatically
// define the required typedefs (iterator_category, value_type, difference_type,
// pointer, reference). This base class was deprecated in C++17.
#include <iostream>
#include <iterator>
#include <algorithm>
#include <vector>
// ============================================================================
// Example 1: A custom iterator over a fixed-size array
// ============================================================================
template <typename T, int N>
class FixedArray {
public:
FixedArray() {
for (int i = 0; i < N; ++i) {
data_[i] = T();
}
}
T& operator[](int i) { return data_[i]; }
const T& operator[](int i) const { return data_[i]; }
int size() const { return N; }
// --- Custom iterator inheriting from std::iterator ---
class iterator : public std::iterator<std::random_access_iterator_tag, T> {
public:
iterator() : ptr_(NULL) {}
explicit iterator(T* p) : ptr_(p) {}
T& operator*() const { return *ptr_; }
T* operator->() const { return ptr_; }
T& operator[](int n) const { return ptr_[n]; }
iterator& operator++() { ++ptr_; return *this; }
iterator operator++(int) { iterator tmp = *this; ++ptr_; return tmp; }
iterator& operator--() { --ptr_; return *this; }
iterator operator--(int) { iterator tmp = *this; --ptr_; return tmp; }
iterator& operator+=(int n) { ptr_ += n; return *this; }
iterator& operator-=(int n) { ptr_ -= n; return *this; }
iterator operator+(int n) const { return iterator(ptr_ + n); }
iterator operator-(int n) const { return iterator(ptr_ - n); }
typename std::iterator<std::random_access_iterator_tag, T>::difference_type
operator-(const iterator& other) const { return ptr_ - other.ptr_; }
bool operator==(const iterator& other) const { return ptr_ == other.ptr_; }
bool operator!=(const iterator& other) const { return ptr_ != other.ptr_; }
bool operator<(const iterator& other) const { return ptr_ < other.ptr_; }
bool operator>(const iterator& other) const { return ptr_ > other.ptr_; }
bool operator<=(const iterator& other) const { return ptr_ <= other.ptr_; }
bool operator>=(const iterator& other) const { return ptr_ >= other.ptr_; }
private:
T* ptr_;
};
// --- Const iterator ---
class const_iterator : public std::iterator<std::random_access_iterator_tag, T,
std::ptrdiff_t, const T*, const T&> {
public:
const_iterator() : ptr_(NULL) {}
explicit const_iterator(const T* p) : ptr_(p) {}
const_iterator(const iterator& it) : ptr_(&(*it)) {}
const T& operator*() const { return *ptr_; }
const T* operator->() const { return ptr_; }
const_iterator& operator++() { ++ptr_; return *this; }
const_iterator operator++(int) { const_iterator tmp = *this; ++ptr_; return tmp; }
const_iterator& operator--() { --ptr_; return *this; }
const_iterator operator--(int) { const_iterator tmp = *this; --ptr_; return tmp; }
const_iterator operator+(int n) const { return const_iterator(ptr_ + n); }
const_iterator operator-(int n) const { return const_iterator(ptr_ - n); }
std::ptrdiff_t operator-(const const_iterator& other) const {
return ptr_ - other.ptr_;
}
bool operator==(const const_iterator& other) const { return ptr_ == other.ptr_; }
bool operator!=(const const_iterator& other) const { return ptr_ != other.ptr_; }
bool operator<(const const_iterator& other) const { return ptr_ < other.ptr_; }
private:
const T* ptr_;
};
iterator begin() { return iterator(data_); }
iterator end() { return iterator(data_ + N); }
const_iterator begin() const { return const_iterator(data_); }
const_iterator end() const { return const_iterator(data_ + N); }
private:
T data_[N];
};
// ============================================================================
// Example 2: A range iterator (generates values on the fly)
// ============================================================================
class RangeIterator : public std::iterator<std::forward_iterator_tag, int> {
public:
RangeIterator() : value_(0), step_(1) {}
RangeIterator(int val, int step) : value_(val), step_(step) {}
int operator*() const { return value_; }
RangeIterator& operator++() {
value_ += step_;
return *this;
}
RangeIterator operator++(int) {
RangeIterator tmp = *this;
value_ += step_;
return tmp;
}
bool operator==(const RangeIterator& other) const {
return value_ == other.value_;
}
bool operator!=(const RangeIterator& other) const {
return value_ != other.value_;
}
private:
int value_;
int step_;
};
// Convenience class for range-based iteration
class Range {
public:
Range(int start, int end, int step = 1)
: start_(start), end_(end), step_(step) {
// Adjust end to be an exact multiple of step from start
int count = (end_ - start_ + step_ - 1) / step_;
end_ = start_ + count * step_;
}
RangeIterator begin() const { return RangeIterator(start_, step_); }
RangeIterator end() const { return RangeIterator(end_, step_); }
private:
int start_;
int end_;
int step_;
};
int main() {
// --- FixedArray with custom iterator ---
std::cout << "=== FixedArray with custom iterator ===" << std::endl;
FixedArray<int, 6> arr;
for (int i = 0; i < 6; ++i) {
arr[i] = (i + 1) * 10;
}
// Forward iteration
std::cout << "Forward: ";
for (FixedArray<int, 6>::iterator it = arr.begin(); it != arr.end(); ++it) {
std::cout << *it << " ";
}
std::cout << std::endl;
// Reverse iteration
std::cout << "Reverse: ";
FixedArray<int, 6>::iterator it = arr.end();
while (it != arr.begin()) {
--it;
std::cout << *it << " ";
}
std::cout << std::endl;
// Random access
std::cout << "arr.begin()[2] = " << arr.begin()[2] << std::endl;
std::cout << "*(arr.begin() + 4) = " << *(arr.begin() + 4) << std::endl;
// --- Using STL algorithms with custom iterator ---
std::cout << "\n=== STL algorithms with custom iterator ===" << std::endl;
// std::sort
FixedArray<int, 5> unsorted;
unsorted[0] = 50;
unsorted[1] = 10;
unsorted[2] = 40;
unsorted[3] = 20;
unsorted[4] = 30;
std::cout << "Before sort: ";
for (FixedArray<int, 5>::iterator it2 = unsorted.begin();
it2 != unsorted.end(); ++it2) {
std::cout << *it2 << " ";
}
std::cout << std::endl;
std::sort(unsorted.begin(), unsorted.end());
std::cout << "After sort: ";
for (FixedArray<int, 5>::iterator it2 = unsorted.begin();
it2 != unsorted.end(); ++it2) {
std::cout << *it2 << " ";
}
std::cout << std::endl;
// std::find
FixedArray<int, 5>::iterator found = std::find(unsorted.begin(), unsorted.end(), 30);
if (found != unsorted.end()) {
std::cout << "Found 30 at position: " << (found - unsorted.begin()) << std::endl;
}
// std::copy to vector
std::vector<int> vec(unsorted.begin(), unsorted.end());
std::cout << "Copied to vector: ";
for (std::vector<int>::iterator vit = vec.begin(); vit != vec.end(); ++vit) {
std::cout << *vit << " ";
}
std::cout << std::endl;
// --- Verify iterator_traits work ---
std::cout << "\n=== iterator_traits verification ===" << std::endl;
typedef std::iterator_traits<FixedArray<int, 5>::iterator> traits;
std::cout << "Category is random_access: "
<< (typeid(traits::iterator_category) ==
typeid(std::random_access_iterator_tag) ? "true" : "false")
<< std::endl;
// --- RangeIterator (forward iterator) ---
std::cout << "\n=== RangeIterator (forward) ===" << std::endl;
std::cout << "Range(0, 10, 2): ";
Range r(0, 10, 2);
for (RangeIterator rit = r.begin(); rit != r.end(); ++rit) {
std::cout << *rit << " ";
}
std::cout << std::endl;
std::cout << "Range(1, 6, 1): ";
Range r2(1, 6, 1);
for (RangeIterator rit = r2.begin(); rit != r2.end(); ++rit) {
std::cout << *rit << " ";
}
std::cout << std::endl;
// Copy range into a vector
std::vector<int> range_vec;
Range r3(10, 15, 1);
for (RangeIterator rit = r3.begin(); rit != r3.end(); ++rit) {
range_vec.push_back(*rit);
}
std::cout << "Range(10,15) in vector: ";
for (std::vector<int>::iterator vit = range_vec.begin();
vit != range_vec.end(); ++vit) {
std::cout << *vit << " ";
}
std::cout << std::endl;
return 0;
}
/*
Expected output:
=== FixedArray with custom iterator ===
Forward: 10 20 30 40 50 60
Reverse: 60 50 40 30 20 10
arr.begin()[2] = 30
*(arr.begin() + 4) = 50
=== STL algorithms with custom iterator ===
Before sort: 50 10 40 20 30
After sort: 10 20 30 40 50
Found 30 at position: 2
Copied to vector: 10 20 30 40 50
=== iterator_traits verification ===
Category is random_access: true
=== RangeIterator (forward) ===
Range(0, 10, 2): 0 2 4 6 8
Range(1, 6, 1): 1 2 3 4 5
Range(10,15) in vector: 10 11 12 13 14
*/
Run command
g++ -std=c++98 -Wall -Wextra -o example iterator.cpp