C++98stlbeginner
Iterator Traits
C++98 · The Foundation · Compiler flag: -std=c++98
Explanation
Provides metadata about iterator types (e.g., value_type).
Real-World Scenario
Write generic algorithms that adapt to iterator types.
Quick Snippet
snippet.cpp
std::iterator_traits<It>::value_type val;Full Example
iterator_traits.cpp
// CodeNebula - C++98 Example: iterator_traits
// Compile: g++ -std=c++98 -Wall -Wextra -o example iterator_traits.cpp
// std::iterator_traits provides a uniform interface to query properties of
// iterators (value_type, difference_type, pointer, reference, iterator_category).
// This enables writing generic algorithms that adapt to iterator capabilities.
#include <iostream>
#include <iterator>
#include <vector>
#include <list>
#include <string>
#include <typeinfo>
// --- Helper: print the iterator category name ---
std::string category_name(std::input_iterator_tag) {
return "input_iterator_tag";
}
std::string category_name(std::output_iterator_tag) {
return "output_iterator_tag";
}
std::string category_name(std::forward_iterator_tag) {
return "forward_iterator_tag";
}
std::string category_name(std::bidirectional_iterator_tag) {
return "bidirectional_iterator_tag";
}
std::string category_name(std::random_access_iterator_tag) {
return "random_access_iterator_tag";
}
// --- Generic function using iterator_traits ---
template <typename Iterator>
void print_iterator_info(const std::string& name) {
typedef typename std::iterator_traits<Iterator>::value_type value_type;
typedef typename std::iterator_traits<Iterator>::difference_type difference_type;
typedef typename std::iterator_traits<Iterator>::iterator_category category;
std::cout << name << ":" << std::endl;
std::cout << " value_type: " << typeid(value_type).name() << std::endl;
std::cout << " difference_type: " << typeid(difference_type).name() << std::endl;
std::cout << " category: " << category_name(category()) << std::endl;
}
// --- A generic advance_n that uses tag dispatch ---
// For random access iterators: O(1) jump
template <typename Iterator>
void advance_impl(Iterator& it, int n, std::random_access_iterator_tag) {
std::cout << " [Using random access: it += " << n << "]" << std::endl;
it += n;
}
// For bidirectional iterators: O(n) step-by-step, forward or backward
template <typename Iterator>
void advance_impl(Iterator& it, int n, std::bidirectional_iterator_tag) {
std::cout << " [Using bidirectional: stepping " << n << " times]" << std::endl;
if (n > 0) {
for (int i = 0; i < n; ++i) ++it;
} else {
for (int i = 0; i > n; --i) --it;
}
}
// For input/forward iterators: O(n) step forward only
template <typename Iterator>
void advance_impl(Iterator& it, int n, std::input_iterator_tag) {
std::cout << " [Using input/forward: stepping " << n << " times forward]" << std::endl;
for (int i = 0; i < n; ++i) ++it;
}
// Main dispatch function
template <typename Iterator>
void my_advance(Iterator& it, int n) {
typedef typename std::iterator_traits<Iterator>::iterator_category category;
advance_impl(it, n, category());
}
// --- Generic distance using iterator_traits ---
template <typename Iterator>
typename std::iterator_traits<Iterator>::difference_type
my_distance_impl(Iterator first, Iterator last, std::random_access_iterator_tag) {
std::cout << " [random access subtraction]" << std::endl;
return last - first;
}
template <typename Iterator>
typename std::iterator_traits<Iterator>::difference_type
my_distance_impl(Iterator first, Iterator last, std::input_iterator_tag) {
std::cout << " [counting increments]" << std::endl;
typename std::iterator_traits<Iterator>::difference_type n = 0;
while (first != last) {
++first;
++n;
}
return n;
}
template <typename Iterator>
typename std::iterator_traits<Iterator>::difference_type
my_distance(Iterator first, Iterator last) {
typedef typename std::iterator_traits<Iterator>::iterator_category category;
return my_distance_impl(first, last, category());
}
// --- Generic sum using value_type ---
template <typename Iterator>
typename std::iterator_traits<Iterator>::value_type
generic_sum(Iterator first, Iterator last) {
typedef typename std::iterator_traits<Iterator>::value_type T;
T sum = T();
while (first != last) {
sum += *first;
++first;
}
return sum;
}
int main() {
// --- Query iterator traits ---
std::cout << "=== Iterator traits info ===" << std::endl;
print_iterator_info<std::vector<int>::iterator>("vector<int>::iterator");
std::cout << std::endl;
print_iterator_info<std::list<double>::iterator>("list<double>::iterator");
std::cout << std::endl;
print_iterator_info<int*>("int*");
std::cout << std::endl;
print_iterator_info<const char*>("const char*");
// --- Tag dispatch: my_advance ---
std::cout << "\n=== Tag dispatch: my_advance ===" << std::endl;
// Random access (vector)
std::vector<int> vec;
vec.push_back(10);
vec.push_back(20);
vec.push_back(30);
vec.push_back(40);
vec.push_back(50);
std::vector<int>::iterator vit = vec.begin();
std::cout << "Vector advance(3) from " << *vit << ":" << std::endl;
my_advance(vit, 3);
std::cout << " Result: " << *vit << std::endl;
// Bidirectional (list)
std::list<int> lst;
lst.push_back(100);
lst.push_back(200);
lst.push_back(300);
lst.push_back(400);
std::list<int>::iterator lit = lst.begin();
std::cout << "\nList advance(2) from " << *lit << ":" << std::endl;
my_advance(lit, 2);
std::cout << " Result: " << *lit << std::endl;
std::cout << "\nList advance(-1) from " << *lit << ":" << std::endl;
my_advance(lit, -1);
std::cout << " Result: " << *lit << std::endl;
// Raw pointer
int arr[] = {1, 2, 3, 4, 5};
int* p = arr;
std::cout << "\nPointer advance(4) from " << *p << ":" << std::endl;
my_advance(p, 4);
std::cout << " Result: " << *p << std::endl;
// --- Tag dispatch: my_distance ---
std::cout << "\n=== Tag dispatch: my_distance ===" << std::endl;
std::cout << "Vector distance:" << std::endl;
std::cout << " = " << my_distance(vec.begin(), vec.end()) << std::endl;
std::cout << "List distance:" << std::endl;
std::cout << " = " << my_distance(lst.begin(), lst.end()) << std::endl;
// --- Generic sum using value_type ---
std::cout << "\n=== Generic sum using value_type ===" << std::endl;
std::cout << "Vector sum: " << generic_sum(vec.begin(), vec.end()) << std::endl;
std::cout << "Array sum: " << generic_sum(arr, arr + 5) << std::endl;
std::vector<double> dvec;
dvec.push_back(1.5);
dvec.push_back(2.5);
dvec.push_back(3.5);
std::cout << "Double sum: " << generic_sum(dvec.begin(), dvec.end()) << std::endl;
return 0;
}
/*
Expected output (type names are compiler-specific, shown as examples):
=== Iterator traits info ===
vector<int>::iterator:
value_type: i
difference_type: ...
category: random_access_iterator_tag
list<double>::iterator:
value_type: d
difference_type: ...
category: bidirectional_iterator_tag
int*:
value_type: i
difference_type: ...
category: random_access_iterator_tag
const char*:
value_type: c
difference_type: ...
category: random_access_iterator_tag
=== Tag dispatch: my_advance ===
Vector advance(3) from 10:
[Using random access: it += 3]
Result: 40
List advance(2) from 100:
[Using bidirectional: stepping 2 times]
Result: 300
List advance(-1) from 300:
[Using bidirectional: stepping -1 times]
Result: 200
Pointer advance(4) from 1:
[Using random access: it += 4]
Result: 5
=== Tag dispatch: my_distance ===
Vector distance:
[random access subtraction]
= 5
List distance:
[counting increments]
= 4
=== Generic sum using value_type ===
Vector sum: 150
Array sum: 15
Double sum: 7.5
*/
Run command
g++ -std=c++98 -Wall -Wextra -o example iterator_traits.cpp