/*
 * An example of a template class.  This simple class holds a given instance
 * and returns copies of it.  Because the class is templated, it will
 * work with and store an element of any type.
 *
 * Author: Zach Tomaszewski
 */

// (note: contents pasted into a single file)

// HEADER portion

template <class E> class Immutable {
  E item;  // the element to hold in storage

public:  
  Immutable(const E& item);
  E get();
};


// DEFINTIONS portion

/* 
 * Constructs a new Immutable storage device containing 
 * a copy of the given item.  Assumes that the assignment
 * operator for the given item results in an independent
 * copy.
 */  
template <class E> Immutable<E>::Immutable(const E& item) {
  // Takes an E& for efficiency; declared const because won't 
  // change the passed item.
  this->item = item;
}

/*
 * Returns a copy of the item held in this Immutable storage object.
 */
template <class E> E Immutable<E>::get() {
  return this->item;  
}



// MAIN

#include <iostream>
#include <string>

using namespace std;

int main() {
  //testing immutability with a string
  string input = "unchangable";
  Immutable<string> stored(input);
  cout << "Saved value: " << stored.get() << endl;
  input[0] = 'U';
  cout << "Saved value after changing input: " << stored.get() << endl;
  stored.get()[1] = 'N';
  cout << "Saved value after changing output: " << stored.get() << endl;
  
  //testing that other data type can be stored
  Immutable<int> numStore(5);
  cout << "Stored: " << numStore.get() << endl;
  Immutable<double> doubleStore(5.5);
  cout << "Stored: " << doubleStore.get()  << endl;  

  return 0;  
}

