COMS W4995 C++ Deep Dive for C Programmers

Index of 2025-9/code/11

Parent directory
Makefile
iterator1.cpp
iterator2.cpp

Makefile

CC  = g++
CXX = g++

CFLAGS   = -g -Wall
CXXFLAGS = -g -Wall -std=c++20

executables = iterator1 iterator2

.PHONY: default
default: $(executables)

iterator1: iterator1.o

iterator2: iterator2.o

.PHONY: clean
clean:
	rm -f *~ a.out core *.o $(executables)

.PHONY: all
all: clean default

iterator1.cpp

#include <array>
#include <vector>
#include <deque>
#include <list>
#include <forward_list>
#include <iostream>
#include <iterator>
using namespace std;

// Pretty much the same as std::for_each
template <typename I, typename F>
void For_Each(I b, I e, F f) {
    while (b != e) {
        f(*b);
        ++b;
    }
}

void print_int(int x)  { cout << x << ' '; }

int main() {
    // 1. integer array
    //
    int a[5] { 100, 101, 102, 103, 104 };
    For_Each(a, a + 5, &print_int);

    // 2. std::vector
    //
    // vector<int> v { 100, 101, 102, 103, 104 };
    // For_Each(&v[0], &v[0] + 5, &print_int);
    // For_Each(v.begin(), v.end(), &print_int);

    // 3. std::list
    //
    // list<int> v { 100, 101, 102, 103, 104 };
    // For_Each(v.begin(), v.end(), &print_int);

    // 4. Looping using iterator
    //
    // list<int> v { 100, 101, 102, 103, 104 };
    // for (list<int>::iterator i = v.begin(); i != v.end(); ++i) {
    //     *i += 200;
    //     cout << *i << ' ';
    // }

    // 5. Looping using const_iterator
    //
    // const list<int> v { 100, 101, 102, 103, 104 };
    // for (list<int>::const_iterator i = v.begin(); i != v.end(); ++i) {
    //     cout << *i << ' ';
    // }

    // 6. Using auto instead of iterator type
    //
    // const list<int> v { 100, 101, 102, 103, 104 };
    // for (auto i = v.begin(); i != v.end(); ++i) {
    //     cout << *i << ' ';
    // }

    // 7. Range-based for loop
    //
    // const list<int> v { 100, 101, 102, 103, 104 };
    // for (auto& x : v) {
    //     cout << x << ' ';
    // }

    cout << '\n';
}

iterator2.cpp

#include <array>
#include <vector>
#include <deque>
#include <list>
#include <forward_list>
#include <iostream>
#include <iterator>
#include <algorithm>
using namespace std;

template <typename Container>
struct IteratorThatPushes {
    Container& c;

    explicit IteratorThatPushes(Container& c) : c(c) {}
    IteratorThatPushes& operator*()     { return *this; }
    IteratorThatPushes& operator++()    { return *this; }
    IteratorThatPushes  operator++(int) { return *this; }

    IteratorThatPushes& operator=(const typename Container::value_type& x) {
        c.push_back(x);
        return *this;
    }
};

void print_int(int x)  { cout << x << ' '; }

int main() {
    // 1. std::copy() revisited
    //
    vector<int> v1 { 100, 101, 102, 103, 104 };
    vector<int> v2;

    copy(v1.begin(), v1.end(), v2.begin());

    for_each(v2.begin(), v2.end(), &print_int);

    // 2. vector initializers
    //
    // vector<int> v1 { 100, 101, 102, 103, 104 };
    // vector<int> v2(5);
    //
    // copy(v1.begin(), v1.end(), v2.begin());
    //
    // for_each(v2.begin(), v2.end(), &print_int);

    // 3. IteratorThatPushes
    //
    // vector<int> v1 { 100, 101, 102, 103, 104 };
    // vector<int> v2;
    //
    // copy(v1.begin(), v1.end(), IteratorThatPushes<vector<int>>{v2});
    //
    // Or use std::back_insert_iterator:
    // copy(v1.begin(), v1.end(), back_inserter(v2));
    //
    // for_each(v2.begin(), v2.end(), &print_int);

    // 4. ostream_iterator
    //
    // vector<int> v { 100, 101, 102, 103, 104 };
    //
    // ostream_iterator<int> oi {cout, "\n"};
    // copy(v.begin(), v.end(), oi);

    // 5. istream_iterator
    //
    // vector<int> v;
    // istream_iterator<int> iib {cin};
    // istream_iterator<int> iie {};
    //
    // copy(iib, iie, back_inserter(v));
    //
    // ostream_iterator<int> oi {cout, ","};
    // copy(v.begin(), v.end(), oi);

    cout << '\n';
}