//Homework Assignment from Paul Kunz C++ lectures
#include <cmath>
#include <stdio.h>
#include <iostream>

template <class T> class SimpleArrayIterator;
template <class T> class SimpleArray;

///////////////////////////////////////////////////////////////////////
template<class T> 
class SimpleArray { 
public: 
    SimpleArray(int n); 
    SimpleArray(); 
    SimpleArray(const SimpleArray<T>&); 
    ~SimpleArray(); 
    T& operator[](int i); 
    SimpleArray<T>& operator=(const SimpleArray<T>&); 
    SimpleArray<T>& operator=(T); 
    void setSize(int n); 
    friend class SimpleArrayIterator<T>;
private: 
    int num_elts; 
    T* ptr_to_data; 
    void copy(const SimpleArray<T>& a); 
};

template<class T> SimpleArray<T>::SimpleArray() { 
    num_elts = 0;
    ptr_to_data = 0; // set pointer to null 
}

template<class T> SimpleArray<T>::SimpleArray(int n) { 
    num_elts = n; 
    ptr_to_data = new T[n]; 
} 
template<class T> SimpleArray<T>::SimpleArray(const SimpleArray<T>& a) { 
    num_elts = a.num_elts; 
    ptr_to_data = new T[num_elts]; 
    copy(a); // Copy a's elements 
}

template<class T> SimpleArray<T>::~SimpleArray(){ 
    delete [] ptr_to_data; 
}
template<class T> void SimpleArray<T>::copy(const SimpleArray<T>& a){ 
// Copy a's elements into the elements of our array 
   T* p = ptr_to_data + num_elts; 
   T* q = a.ptr_to_data + num_elts; 
   while (p > ptr_to_data) *--p = *--q; 
} 

template<class T> SimpleArray<T>& SimpleArray<T>::operator=(const SimpleArray<T>& rhs){ 
    if ( ptr_to_data != rhs.ptr_to_data ) { 
        setSize( rhs.num_elts ); 
        copy(rhs); 
    } 
    return *this; 
}

template<class T> T& SimpleArray<T>::operator[](int i) {
    return ptr_to_data[i];
}

template<class T> SimpleArray<T>& SimpleArray<T>::operator=(T rhs){ 
    T* p = ptr_to_data + num_elts; 
    while (p > ptr_to_data) *--p = rhs; 
    return *this; 
} 

template<class T> void SimpleArray<T>::setSize(int n) { 
    if (n != num_elts) { 
      delete [] ptr_to_data; 
      num_elts = n; 
      ptr_to_data = new T[n]; 
    } 
}

//////////////////////////////////////////////////////////////////
template<class T>
class SimpleArrayIterator {
  public:
     SimpleArrayIterator(const SimpleArray<T>& simplearray) : 
        cur(simplearray.ptr_to_data) {
        NElems=simplearray.num_elts;            //Get Num of Elements
        last = simplearray.ptr_to_data+NElems;  //Get pointer to last element
     }
     bool       more()          const   { return cur!= last; }
     T          current()       const   { return *cur;}
     void       advance()               { cur++; }
  private:
     int NElems;
     T* cur;
     T* last;
};


int main(){
   int NElements=30;
   SimpleArray<int> MyArr(NElements);   
   for (int i=0;i<NElements;i++){ MyArr[i]=10*i;}
   //USE OF SIMPLEARRAY ITERATOR
   for (SimpleArrayIterator<int> i(MyArr); i.more() ; i.advance()) {
       std::cout<<"Number"<<i.current()<<"\n";
   }
   return 0;
}
