// There is a standard vector class in C++, but it is based on a
// template, not on polymophism.
#include <iostream>
#include <vector>
#include <list>
#include <string>
using namespace std;
// Generic printing function. Note: This function can print the contents
// of any object which implements the iterator pattern used by the standard
// library, and whose members cout knows how to print.
template <typename CollectType>
void print_col(CollectType &v)
{
int m = 0;
for(auto i = v.begin(); i != v.end(); ++i) {
if(i != v.begin()) cout << " ";
cout << *i;
}
}
void craziness();
int main()
{
// Put some stuff in a vector of strings.
vector<string> v = { "How", "are", "you", "today?" };
v.insert(v.begin() + 3, "doing");
print_col(v);
cout << endl;
// Put some stuff in a list.
list<int> q;
q.push_back(45);
q.push_back(3);
q.push_front(-34);
q.push_back(75);
q.push_front(9);
print_col(q);
cout << endl;
// And try a string, which also offers the iterator pattern.
string mars = "Hello, Mars!";
print_col(mars);
cout << endl;
// See below. If you dare.
craziness();
}
// ==== Consider the rest of this file optional material ====
/*
* This class represents a range that can be iterated through. Not good for
* much, though I suppose it could be the start of something marginally
* useful.
*/
class Range {
public:
// Range of numbers is first to last.
Range(int first, int last) {
set(first, last);
}
// Change the range.
void set(int first, int last) {
m_first = first;
m_last = last;
}
// This is the iterator type, which is really just a
// wrapper for int. This class uses the operator keyword which
// allows a C++ programmer to define methods which give the meaning
// of certain operators. It should be used sparingly, but some are
// required to create an iterator.
class iterator {
public:
iterator(int i) { m_i = i; }
// This defines the meaning of the ++ operator on an iterator.
iterator operator++() {
++m_i;
return *this;
}
// Here's what * does to an iterator. (Just returns
// the integer.)
int operator*() const { return m_i; }
// Define how to compare.
int operator!=(iterator i) const { return m_i != i.m_i; }
private:
int m_i;
};
// Begin and end.
iterator begin() { return iterator(m_first); }
iterator end() { return iterator(m_last + 1); }
private:
// The start and end of the range.
int m_first, m_last;
};
void craziness()
{
Range ct(1,10);
print_col(ct);
cout << endl;
ct.set(6,18);
print_col(ct);
cout << endl;
}
This is similar, but the type parameter
is assumed to be something which implements the
iterator pattern. This includes any of the standard
collections, but can also include classes you define
to implement the pattern. This fact is not declared anywhere,
but is implicit in the code, and will be enforced if you try to print
a class that doesn't have the needed type and operations.
The actual implementation of the
iterator pattern requires
some features we haven't discussed, as shown in the Range
class at the bottom of the file.
- The iterator is a class internal to the Range class.
These are allowed in both C++ and Java, though not commonly used.
- The iterator uses the operator keyword to make
methods for the operators ++, * and !=. When
those operators are used on an iterator object, the
associated method is called. (Overloading operators this way is
a large topic, and won't ask you about it quizzes or exams in this course.)