C++98stlbeginner
Forward Iterator
C++98 · The Foundation · Compiler flag: -std=c++98
Explanation
Reads/writes elements, supports multiple passes in one direction.
Real-World Scenario
Traverse a linked list in a navigation system.
Quick Snippet
snippet.cpp
std::list<int>::iterator it = lst.begin();Full Example
forward_iterator.cpp
// CodeNebula - C++98 Example: forward_iterator
// Compile: g++ -std=c++98 -Wall -Wextra -o example forward_iterator.cpp
// Forward iterators support multi-pass forward traversal (++ but not --).
// They can read and write elements, and the same range can be traversed
// multiple times. In C++98, there is no std::forward_list, but we can
// demonstrate the concept with a custom singly-linked list.
#include <iostream>
#include <iterator>
#include <algorithm>
#include <string>
// A simple singly-linked list node
template <typename T>
struct SListNode {
T data;
SListNode* next;
SListNode(const T& val) : data(val), next(NULL) {}
};
// A simple singly-linked list with a forward iterator
template <typename T>
class SList {
public:
// --- Forward Iterator class ---
class iterator {
public:
// Required typedefs for iterator_traits
typedef std::forward_iterator_tag iterator_category;
typedef T value_type;
typedef std::ptrdiff_t difference_type;
typedef T* pointer;
typedef T& reference;
iterator() : node_(NULL) {}
explicit iterator(SListNode<T>* n) : node_(n) {}
reference operator*() const { return node_->data; }
pointer operator->() const { return &(node_->data); }
iterator& operator++() {
node_ = node_->next;
return *this;
}
iterator operator++(int) {
iterator tmp = *this;
node_ = node_->next;
return tmp;
}
bool operator==(const iterator& other) const { return node_ == other.node_; }
bool operator!=(const iterator& other) const { return node_ != other.node_; }
private:
SListNode<T>* node_;
};
// --- Const Forward Iterator class ---
class const_iterator {
public:
typedef std::forward_iterator_tag iterator_category;
typedef T value_type;
typedef std::ptrdiff_t difference_type;
typedef const T* pointer;
typedef const T& reference;
const_iterator() : node_(NULL) {}
explicit const_iterator(const SListNode<T>* n) : node_(n) {}
const_iterator(const iterator& it) : node_(NULL) {
// Conversion from iterator to const_iterator
// This is a simplified version; in production code you'd store the node
(void)it;
}
reference operator*() const { return node_->data; }
pointer operator->() const { return &(node_->data); }
const_iterator& operator++() {
node_ = node_->next;
return *this;
}
const_iterator operator++(int) {
const_iterator tmp = *this;
node_ = node_->next;
return tmp;
}
bool operator==(const const_iterator& other) const { return node_ == other.node_; }
bool operator!=(const const_iterator& other) const { return node_ != other.node_; }
private:
const SListNode<T>* node_;
};
SList() : head_(NULL), size_(0) {}
~SList() {
while (head_) {
SListNode<T>* next = head_->next;
delete head_;
head_ = next;
}
}
void push_front(const T& val) {
SListNode<T>* node = new SListNode<T>(val);
node->next = head_;
head_ = node;
++size_;
}
iterator begin() { return iterator(head_); }
iterator end() { return iterator(NULL); }
const_iterator begin() const { return const_iterator(head_); }
const_iterator end() const { return const_iterator(NULL); }
std::size_t size() const { return size_; }
bool empty() const { return head_ == NULL; }
private:
SListNode<T>* head_;
std::size_t size_;
// Prevent copying for simplicity
SList(const SList&);
SList& operator=(const SList&);
};
int main() {
// --- Create and populate the singly-linked list ---
std::cout << "=== Singly-linked list with forward iterator ===" << std::endl;
SList<int> slist;
slist.push_front(50);
slist.push_front(40);
slist.push_front(30);
slist.push_front(20);
slist.push_front(10);
// --- Forward traversal ---
std::cout << "Forward traversal: ";
for (SList<int>::iterator it = slist.begin(); it != slist.end(); ++it) {
std::cout << *it << " ";
}
std::cout << std::endl;
// --- Multi-pass: traverse multiple times ---
std::cout << "\n=== Multi-pass traversal ===" << std::endl;
std::cout << "Pass 1: ";
for (SList<int>::iterator it = slist.begin(); it != slist.end(); ++it) {
std::cout << *it << " ";
}
std::cout << std::endl;
std::cout << "Pass 2: ";
for (SList<int>::iterator it = slist.begin(); it != slist.end(); ++it) {
std::cout << *it << " ";
}
std::cout << std::endl;
// --- Modifying through the iterator ---
std::cout << "\n=== Modify through iterator ===" << std::endl;
for (SList<int>::iterator it = slist.begin(); it != slist.end(); ++it) {
*it *= 2;
}
std::cout << "After doubling: ";
for (SList<int>::iterator it = slist.begin(); it != slist.end(); ++it) {
std::cout << *it << " ";
}
std::cout << std::endl;
// --- Using std::find with forward iterator ---
std::cout << "\n=== std::find ===" << std::endl;
SList<int>::iterator found = std::find(slist.begin(), slist.end(), 60);
if (found != slist.end()) {
std::cout << "Found: " << *found << std::endl;
} else {
std::cout << "60 not found" << std::endl;
}
found = std::find(slist.begin(), slist.end(), 999);
if (found == slist.end()) {
std::cout << "999 not found" << std::endl;
}
// --- Using std::count with forward iterator ---
std::cout << "\n=== std::count ===" << std::endl;
SList<int> dup_list;
dup_list.push_front(10);
dup_list.push_front(20);
dup_list.push_front(10);
dup_list.push_front(30);
dup_list.push_front(10);
int cnt = static_cast<int>(std::count(dup_list.begin(), dup_list.end(), 10));
std::cout << "Count of 10: " << cnt << std::endl;
// --- String singly-linked list ---
std::cout << "\n=== String SList ===" << std::endl;
SList<std::string> str_list;
str_list.push_front("cherry");
str_list.push_front("banana");
str_list.push_front("apple");
std::cout << "Strings: ";
for (SList<std::string>::iterator it = str_list.begin();
it != str_list.end(); ++it) {
std::cout << *it << " ";
}
std::cout << std::endl;
// --- Key properties of forward iterators ---
std::cout << "\n=== Forward iterator properties ===" << std::endl;
std::cout << "1. Multi-pass: the same range can be traversed multiple times" << std::endl;
std::cout << "2. Read/Write: *it can be read and assigned" << std::endl;
std::cout << "3. Supports: ++it, it++, *it, it == end, it != end" << std::endl;
std::cout << "4. Does NOT support: --it (backward), it + n, it[n]" << std::endl;
std::cout << "5. Category: std::forward_iterator_tag" << std::endl;
return 0;
}
/*
Expected output:
=== Singly-linked list with forward iterator ===
Forward traversal: 10 20 30 40 50
=== Multi-pass traversal ===
Pass 1: 10 20 30 40 50
Pass 2: 10 20 30 40 50
=== Modify through iterator ===
After doubling: 20 40 60 80 100
=== std::find ===
Found: 60
999 not found
=== std::count ===
Count of 10: 3
=== String SList ===
Strings: apple banana cherry
=== Forward iterator properties ===
1. Multi-pass: the same range can be traversed multiple times
2. Read/Write: *it can be read and assigned
3. Supports: ++it, it++, *it, it == end, it != end
4. Does NOT support: --it (backward), it + n, it[n]
5. Category: std::forward_iterator_tag
*/
Run command
g++ -std=c++98 -Wall -Wextra -o example forward_iterator.cpp