Array.h

#pragma once

#include<stdexcept>

using std::out_of_range;

#include<iostream>

using std::ostream;

/* A fixed-size array class with an iterator

* This would need some additional functions and a const iterator to be const-correct

*/

template<class T>

class Array

{

public:

Array(const unsigned int sz) : m_size(sz), m_items(new T[m_size]) {}

Array(const Array& a)

{

m_size = a.m_size;

m_items = new T[a.m_size];

for(unsigned int i = 0; i < m_size; i++)

m_items[i] = a.m_items[i];

}

~Array()

{

delete [] m_items;

}

Array& operator=(const Array a)

{

using std::swap; // copy-and-swap idiom

swap(a.m_size, m_size);

swap(a.m_items, m_items);

return *this;

}

// Accessors

unsigned int size() const { return m_size; }

T& operator[](const unsigned int idx)

{

if(idx >= m_size)

throw out_of_range("idx too large");

return m_items[idx];

}

friend ostream& operator<<(ostream& out, Array& a)

{

out << "[";

for(auto elem : a)

out << elem << ",";

out << "\b]"; // this is cheating

return out;

}

/* Iterator

* This can be iterated forward and backwards, either one at a time or in jumps.

* You could also implement this as a pointer right into the Array's member,

* but that would require some extra stuff to keep you from indexing out of bounds.

* (Here, we just rely on the Array to stop us from doing that.)

*/

class iterator

{

public:

iterator(Array* a, unsigned int idx): m_array(a), m_idx(idx) {}

T& operator*() { return (*m_array)[m_idx]; }

T& operator->() { return (*m_array)[m_idx]; } // for arrays of structs/classes

iterator& operator++()

{

m_idx++;

return *this;

}

iterator operator++(int)

{

iterator temp = *this;

m_idx++;

return temp;

}

iterator& operator+=(const unsigned int inc)

{

m_idx += inc;

return *this;

}

iterator& operator--()

{

m_idx--;

return *this;

}

iterator operator--(int)

{

iterator temp = *this;

m_idx--;

return temp;

}

iterator& operator-=(const unsigned int dec)

{

m_idx -= dec;

return *this;

}

friend bool operator==(const iterator& a, const iterator& b)

{

return a.m_array == b.m_array && a.m_idx == b.m_idx;

}

friend bool operator!=(const iterator& a, const iterator& b)

{

return !(a == b);

}

private:

Array* m_array;

unsigned int m_idx;

};

// If you implement these two functions, range-based for loops Just Work (TM)

// (that is, std::begin() and std::end() will know what to do)

iterator begin() { return iterator(this, 0); }

iterator end() { return iterator(this, m_size); }

private:

unsigned int m_size;

T* m_items;

};