C++/Class/template class

Материал из C\C++ эксперт
Перейти к: навигация, поиск

A generic safe-array class that prevents array boundary errors.

<source lang="cpp">

  1. include <iostream>
  2. include <new>
  3. include <cstdlib>

using namespace std; template <class T, int len> class dyn_safe_array {

 T *aptr;  
 int length;

public:

 dyn_safe_array();
 // copy constructor.
 dyn_safe_array(const dyn_safe_array &obj);
 // Release the allocated memory when a dyn_safe_array object goes out of scope.
 ~dyn_safe_array() {
    delete [] aptr;
 }
 // Overload assignment.
 dyn_safe_array &operator=(const dyn_safe_array<T,len> &rh_op);
 // Use the subscripting operator to access elements in the safe array.
 T &operator[](int i);
 
 // Return the size of the array.
 int getlen() { return length; }

}; // constructor. template <class T, int len> dyn_safe_array<T, len>::dyn_safe_array() {

 try {
   aptr = new T[len];
 } catch(bad_alloc ba) {
   cout << "Can"t allocate array.\n";
   // Take appropriate action here. This is just
   // a placeholder response.
   exit(1);
 }
 // Initialize the array elements to their default value.
 for(int i=0; i < len; ++i) aptr[i] = T();
 length = len;

} // copy constructor. template <class T, int len> dyn_safe_array<T, len>::dyn_safe_array(const dyn_safe_array &obj) {

 cout << "Using dyn_safe_array"s copy constructor to make a copy.\n";
 try {
   aptr = new T[obj.length];
 } catch(bad_alloc ba) {
   cout << "Can"t allocate array.\n";
   exit(1);
 }
 length = obj.length;
 // Copy contents of the array.
 for(int i=0; i < length; ++i)
   aptr[i] = obj.aptr[i];

} // Overload assignment so that a copy of the array is made. // The copy is stored in an allocated memory that is separate // from that used by the right-hand operand. template<class T, int len> dyn_safe_array<T, len> & dyn_safe_array<T, len>::operator=(const dyn_safe_array<T, len> &rh_op) {

// If necessary, release the memory currently used by the object.
if(aptr && (length != rh_op.length)) {
  // Delete the previously allocated memory.
  delete aptr;
  try {
    // Allocate an array of the same size as the one used by rh_op.
    aptr = new T[rh_op.length];
  } catch(bad_alloc ba) {
    // Take appropriate action here. This is just a placeholder response.
    cout << "Can"t allocate array.\n";
    exit(1);
  }
}
length = rh_op.length;
// Copy contents of the array.
for(int i=0; i < length; ++i)
  aptr[i] = rh_op.aptr[i];
  return *this;

} template <class T, int len> T &dyn_safe_array<T, len>::operator[](int i) {

 if(i < 0 || i > length) {
   cout << "\nIndex value of " << i << " is out-of-bounds.\n";
   exit(1);
 }
 return aptr[i];

} template <class T, int len> dyn_safe_array<T, len> f(dyn_safe_array<T, len> x) {

 cout << "f() is returning a copy of x.\n";
 return x;

} class myclass { public:

 int x;
 myclass(int i) { x = i; };
 myclass() { x = -1; }

}; int main() {

 // Use the integer array.
 dyn_safe_array<int, 5> i_ar;
 for(int i=0; i < i_ar.getlen(); ++i) i_ar[i] = i;
 cout << "Contents of i_ar: ";
 for(int i=0; i < i_ar.getlen(); ++i) cout << i_ar[i] << " ";
 cout << "\n\n";
 dyn_safe_array<int, 5> i_ar2 = i_ar;
 for(int i=0; i < i_ar2.getlen(); ++i) cout << i_ar2[i] << " ";
 dyn_safe_array<int, 5> i_ar3;
 for(int i=0; i < i_ar3.getlen(); ++i) cout << i_ar3[i] << " ";
 cout <<"\n\n";
 i_ar3 = f(i_ar);
 for(int i=0; i < i_ar3.getlen(); ++i)  cout << i_ar3[i] << " ";
 cout << "\n\n";
 dyn_safe_array<myclass, 3> mc_ar;
 cout << "Original contents of mc_ar: ";
 for(int i=0; i < mc_ar.getlen(); ++i) cout << mc_ar[i].x << " ";
 cout << endl;
 mc_ar[0].x = 9;
 mc_ar[1].x = 8;
 mc_ar[2].x = 7;
 for(int i=0; i < mc_ar.getlen(); ++i) cout << mc_ar[i].x << " ";
 cout << "\n\n";
 cout << "   mc_ar2 = f(mc_ar);\n\n";
 dyn_safe_array<myclass, 3> mc_ar2;
 mc_ar2 = f(mc_ar);
 cout << "Contents of mc_ar2 after receiving f(mc_ar): ";
 for(int i=0; i < mc_ar2.getlen(); ++i) cout << mc_ar2[i].x << " ";
 cout << endl;
 return 0;

}


 </source>


An Example with Two Generic Data Types

<source lang="cpp">

  1. include <iostream>

using namespace std;

template <class Type1, class Type2> class myclass {

 Type1 i;
 Type2 j;

public:

 myclass(Type1 a, Type2 b) { i = a; j = b; }
 void show() { cout << i << " " << j << "\n"; }

};

int main() {

 myclass<int, double> ob1(10, 0.23);
 myclass<char, char *> ob2("X", "Templates add power.");
  
 ob1.show(); 
 ob2.show(); 
  
 return 0;

}


 </source>


Applying Template Classes: A Generic Array Class

<source lang="cpp">

  1. include <iostream>
  2. include <cstdlib>

using namespace std;

const int SIZE = 10;

template <class T> class MyClass {

 T a[SIZE];

public:

 MyClass() {
   register int i;
   for(i=0; i<SIZE; i++) a[i] = i;
 }
 T &operator[](int i);

};

template <class T> T &MyClass<T>::operator[](int i) {

 if(i<0 || i> SIZE-1) {
   cout << "\nIndex value of ";
   cout << i << " is out-of-bounds.\n";
   exit(1);
 }
 return a[i];

}

int main() {

 MyClass<int> intob; // integer array
 MyClass<double> doubleob; // double array
  
 for(int i=0; i<SIZE; i++) intob[i] = i;
 for(int i=0; i<SIZE; i++) cout << intob[i] << endl;
  
 for(int i=0; i<SIZE; i++) doubleob[i] = (double) i/3;
 for(int i=0; i<SIZE; i++) cout << doubleob[i] << endl;
  
 return 0;

}


 </source>


Demonstrate a very simple safe pointer class.

<source lang="cpp">

  1. include <iostream>
  2. include <string>

using namespace std; // The exception type thrown by the safe pointer. class bad_ptr { public:

 string msg;
 bad_ptr(string str) { msg = str; }

}; // A class used to demonstrate the safe pointer. class myclass { public:

 int alpha;
 int beta;
 myclass(int p, int q) { alpha = p; beta = q; }

}; template <class T> class safe_ptr {

 T *ptr;

public:

 safe_ptr() { ptr = 0; }
 T *operator->() {
   if(!ptr != 0) throw bad_ptr("Attempt to use -> on null pointer.");
   else return ptr;
 }
 T &operator*() {
   if(!ptr) throw bad_ptr("Attempt to dereference null pointer.");
   else return *ptr;
 }
 operator T *() { return ptr; }
 T *operator=(T *val) { ptr = val; return ptr; }

}; int main() {

 safe_ptr<int> intptr;
 try {
   *intptr = 23;
   cout << "The value pointed to by intptr is: " << *intptr << endl;
 } catch(bad_ptr bp) {
   cout << bp.msg << endl;
 }
 intptr = new int;
 try {
   *intptr = 23;
   cout << "The value pointed to by intpr is: " << *intptr << "\n\n";
 } catch(bad_ptr bp) {
   cout << bp.msg << endl;
 }
 safe_ptr<myclass> mcptr;
 try {
   mcptr = new myclass(100, 200);
   cout << "The values of alpha and beta for mcptr are: "
        << mcptr->alpha << " and " << mcptr->beta << endl;
   mcptr->alpha = 27;
   cout << "New value for mcptr->alpha: " << mcptr->alpha << endl;
   cout << "Same as (*mcptr).alpha: " << (*mcptr).alpha << endl;
   mcptr->beta = 99;
   cout << "New value for mcptr->beta: " << mcptr->beta << "\n\n";
 } catch(bad_ptr bp) {
   cout << bp.msg << endl;
 }
 safe_ptr<myclass> mcptr2;
 try {
   mcptr2->alpha = 88;
 } catch(bad_ptr bp) {
   cout << bp.msg << endl;
 }
 delete intptr;
 delete mcptr;
 return 0;

}


 </source>


Explicit Class Specializations for generic template class

<source lang="cpp">

  1. include <iostream>

using namespace std;

template <class T> class myclass {

 T x;

public:

 myclass(T a) {
   cout << "Inside generic myclass\n";
   x = a;
 }
 T getx() { return x; }

};

template <> class myclass<int> {

 int x;

public:

 myclass(int a) {
   cout << "Inside myclass<int> specialization\n";
   x = a * a;
 }
 int getx() { return x; }

};

int main() {

 myclass<double> d(10.1);
 cout << "double: " << d.getx() << "\n\n";
  
 myclass<int> i(5);
 cout << "int: " << i.getx() << "\n";
  
 return 0;

}


 </source>


Generic Classes: demonstrates a generic stack.

<source lang="cpp">

  1. include <iostream>

using namespace std;

const int SIZE = 10;

template <class StackType> class stack {

 StackType stck[SIZE]; 
 int tos; 
  

public:

 stack() { tos = 0; } 
 void push(StackType ob); 
 StackType pop(); 

}; template <class StackType> void stack<StackType>::push(StackType ob) {

 if(tos==SIZE) {
   cout << "Stack is full.\n";
   return;
 }
 stck[tos] = ob;
 tos++;

} template <class StackType> StackType stack<StackType>::pop() {

 if(tos==0) {
   cout << "Stack is empty.\n";
   return 0; // return null on empty stack
 }
 tos--;
 return stck[tos];

}

int main() {

 stack<char> s1, s2;
  
 s1.push("a");
 s2.push("x");
 s1.push("b");
 s2.push("y");
 s1.push("c");
 s2.push("z");
  
 for(int i=0; i<3; i++) cout << "Pop s1: " << s1.pop() << "\n";
 for(int i=0; i<3; i++) cout << "Pop s2: " << s2.pop() << "\n";
  
 stack<double> ds1, ds2;
  
 ds1.push(1.1);
 ds2.push(2.2);
 ds1.push(3.3);
 ds2.push(4.4);
 ds1.push(5.5);
 ds2.push(6.6);
  
 for(int i=0; i<3; i++) cout << "Pop ds1: " << ds1.pop() << "\n";
 for(int i=0; i<3; i++) cout << "Pop ds2: " << ds2.pop() << "\n";
  
 return 0;

}


 </source>


generic stack template class

<source lang="cpp">

  1. include <iostream>

using namespace std; const int SIZE = 100; template <class SType> class stack {

  SType stck[SIZE];
  int tos;
public:
  stack(void);
  ~stack(void);
  void push(SType i);
  SType pop(void);
};

template <class SType> stack<SType>::stack() {

  tos = 0;
  cout << "Stack Initialized." << endl;

} template <class SType> stack<SType>::~stack() {

  cout << "Stack Destroyed." << endl;

} template <class SType> void stack<SType>::push(SType i) {

  if(tos==SIZE)
   {
     cout << "Stack is full." << endl;
     return;
   }
  stck[tos++] = i;

} template <class SType> SType stack<SType>::pop(void) {

  if(tos==0)
   {
     cout << "Stack underflow." << endl;
     return 0;
   }
  return stck[--tos];

} int main(void) {

  stack<int> a;
  stack<double> b;
  stack<char> c;
  int i;
  a.push(1);
  a.push(2);
  b.push(99.3);
  b.push(-12.23);
  cout << a.pop() << " ";
  cout << a.pop() << " ";
  cout << b.pop() << " ";
  cout << b.pop() << endl;
  for(i=0; i<10; i++)
     c.push((char) "A" + i);
  for(i=0; i<10; i++)
     cout << c.pop();
  cout << endl;

}


 </source>


Get storage off stack for array

<source lang="cpp">

  1. include <iostream>

using namespace std; template <class T, int n> class assign_array { public:

  T  a[n];

}; int main() {

  assign_array<double, 50>  x, y;
  for (int i = 0; i < 50; ++i)
     x.a[i] = i;
  for (int i = 0; i < 50; ++i)
     y.a[i] = i * 2;
  for (int i = 0; i < 50; ++i)
     cout << x.a[i] << "\t";
  for (int i = 0; i < 50; ++i)
     cout << y.a[i] << "\t";
  x = y;                     //should work efficiently
  for (int i = 0; i < 50; ++i)
     cout << x.a[i] << "\t";

}


 </source>


Passing by reference and using virtual functions in exceptions.

<source lang="cpp">

  1. include <iostream>

using namespace std; const int DefaultSize = 10; class Array { public:

   Array(int itsSize = DefaultSize);
   Array(const Array &rhs);
   ~Array() { delete [] pType;}
   Array& operator=(const Array&);
   int& operator[](int offSet);
   const int& operator[](int offSet) const;
   int GetitsSize() const { return itsSize; }
   friend ostream& operator<< (ostream&, const Array&);
   class xBoundary {};
   class xSize
   {
   public:
      xSize(int size):itsSize(size) {}
      ~xSize(){}
      virtual int GetSize() { return itsSize; }
      virtual void PrintError() 
      { 
          cout << "Size error. Received: ";
          cout << itsSize << endl; 
      }
   protected:
      int itsSize;
   };
   class xTooBig : public xSize
   {
   public:
      xTooBig(int size):xSize(size){}
      virtual void PrintError() 
      { 
          cout << "Too big! Received: ";
          cout << xSize::itsSize << endl; 
      }
   };
   class xTooSmall : public xSize
   {
   public:
      xTooSmall(int size):xSize(size){}
      virtual void PrintError() 
      { 
          cout << "Too small! Received: ";
          cout << xSize::itsSize << endl; 
      }
   };
   class xZero  : public xTooSmall
   {
   public:
      xZero(int size):xTooSmall(size){}
      virtual void PrintError() 
      { 
          cout << "Zero!!. Received: " ;
          cout << xSize::itsSize << endl; 
      }
   };
   class xNegative : public xSize
   {
   public:
      xNegative(int size):xSize(size){}
      virtual void PrintError() 
      { 
          cout << "Negative! Received: ";
          cout << xSize::itsSize << endl; 
      }
   };
private:
   int *pType;
   int  itsSize;
};
Array::Array(int size):
itsSize(size)
{
   if (size == 0)
      throw xZero(size);
   if (size > 30000)
      throw xTooBig(size);
   if (size <1)
      throw xNegative(size);
   if (size < 10)
       throw xTooSmall(size);
    pType = new int[size];
    for (int i = 0; i<size; i++)
      pType[i] = 0;
 }
 int& Array::operator[] (int offSet)
 {
     int size = GetitsSize();
     if (offSet >= 0 && offSet < GetitsSize())
       return pType[offSet];
     throw xBoundary();
     return pType[0];
 }
 const int& Array::operator[] (int offSet) const
 {
     int size = GetitsSize();
     if (offSet >= 0 && offSet < GetitsSize())
       return pType[offSet];
     throw xBoundary();
     return pType[0];
 }
  int main()
  {
     try
     {
        Array intArray(9);
        for (int j = 0; j< 100; j++)
        {
           intArray[j] = j;
           cout << "intArray[" << j << "] okay...\n";
        }
     }
     catch (Array::xBoundary)
    {
       cout << "Unable to process your input!\n";
    }
    catch (Array::xSize& theException)
    {
       theException.PrintError();
    }
    catch (...)
    {
       cout << "Something went wrong!\n";
    }
    cout << "Done.\n";
   return 0;

}


 </source>


sequence template

<source lang="cpp">

  1. include <iostream>

using namespace std; template <class T, int N> class sequence {

   T memblock [N];
 public:
   void setmember (int x, T value);
   T getmember (int x);

}; template <class T, int N> void sequence<T,N>::setmember (int x, T value) {

 memblock[x]=value;

} template <class T, int N> T sequence<T,N>::getmember (int x) {

 return memblock[x];

} int main () {

 sequence <int,5> myints;
 sequence <double,5> myfloats;
 myints.setmember (0,100);
 myfloats.setmember (3,3.1416);
 cout << myints.getmember(0) << "\n";
 cout << myfloats.getmember(3) << "\n";
 return 0;

}


 </source>


template class with generic parameter

<source lang="cpp">

  1. include <iostream>

using namespace std; template<class T> class Distance {

 public:
   Distance(T distance); 
   void show_distance(void) { 
      cout << "The distance is " << distance << " miles\n"; 
   };
 private:
   T distance;

}; template<class T> Distance<T>::Distance(T distance) { Distance::distance = distance; }; int main(void) {

   Distance<int> short_distance(100);
   Distance<long> long_distance(2000000L);
   short_distance.show_distance();
   long_distance.show_distance();

}


 </source>


template class with two generic parameters

<source lang="cpp">

  1. include <iostream>

using namespace std; template <class T1, class T2> class two_gen {

  T1 i;
  T2 j;
public:
  two_gen(T1 a, T2 b)
     { i=a; j=b;}
  void show(void)
     { cout << i << " " << j << endl; }

}; int main(void) {

  two_gen<int, double> obj1(10, 0.23);
  two_gen<char, char *> obj2("X", "This is a test.");
  obj1.show();
  obj2.show();

}


 </source>


template class with type parameter

<source lang="cpp">

  1. include <iostream>
  2. include <stdlib.h>

using namespace std; const int SIZE = 10; template <class T> class MyClass {

  T a[SIZE];
public:
  MyClass(void)
   {
     int i;
     for(i=0; i<SIZE; i++)
        a[i] = i;
   }
  T &operator[](int i);

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

  if(i<0 || i> SIZE-1)
   {
     cout << endl << "Index value of ";
     cout << i << " is out of bounds." << endl;
   }
  return a[i];

} int main(void) {

  MyClass<int> int_array;
  MyClass<double> double_array;
  int i;
  cout << "Integer array: ";
  for(i=0; i<SIZE; i++)
     int_array[i] = i;
  for(i=0; i<SIZE; i++)
     cout << int_array[i] << " ";
  cout << endl;
  cout << "Double array: ";
  cout.precision(2);
  for(i=0; i<SIZE; i++)
     double_array[i] = (double)i/3;
  for(i=0; i<SIZE; i++)
     cout << double_array[i] << " ";
  cout << endl;
  int_array[12] = 100;                 // Calls overloaded array operator

}


 </source>


template extending

<source lang="cpp"> template <typename T> class SimpleTemplate {

public:
 SimpleTemplate(T &inObject);
 const T& get();
 void set(T& inObject);
protected:
 T& mObject;

}; template <typename T> SimpleTemplate<T>::SimpleTemplate(T &inObject) : mObject(inObject) { } template <typename T> const T& SimpleTemplate<T>::get() {

 return mObject;

} template <typename T> void SimpleTemplate<T>::set(T& inObject) {

 mObject = inObject;

}

  1. include <iostream>
  2. include <string>

using namespace std; int main(int argc, char** argv) {

 int i = 7;
 SimpleTemplate<int> intWrapper(i);
 i = 2;
 cout << "wrapper value is " << intWrapper.get() << endl;
 string str = "test";
 SimpleTemplate<string> stringWrapper(str);
 str += "!";
 cout << "wrapper value is " << stringWrapper.get() << endl;

}


 </source>


Template Version of Generic binary sorted Tree.

<source lang="cpp">

  1. include <iostream>
  2. include <string.h>

using namespace std; //A generic binary sorted tree. template <class T> class gen_tree; //forward decl template <class T> class bnode { private:

  friend class gen_tree<T>;
  bnode<T>*  left;
  bnode<T>*  right;
  T          data;
  int        count;
  bnode(T d, bnode<T>* l, bnode<T>* r) :
        data(d), left(l), right(r), count(1) { }
  void  print() const
     { cout << data << " : " << count << "\t"; }

}; template <class T> class gen_tree { public:

  gen_tree() { root = 0; }
  void  insert(T d);
  T  find(T d) const { return (find(root, d)); }
  void  print() const { print(root); }

private:

  bnode<T>*  root;
  T  find(bnode<T>* r, T d) const;
  void  print(bnode<T>* r) const;

}; template <class T> void gen_tree<T>::insert(T d) {

  bnode<T>*  temp = root;
  bnode<T>*  old;
  if (root == 0) {
     root = new bnode<T>(d, 0, 0);
     return;
  }
  while (temp != 0) {
     old = temp;
     if (comp(temp -> data, d) == 0) {
        (temp -> count)++;
        return;
     }
     if (comp(temp -> data, d) > 0)
        temp = temp -> left;
     else
        temp = temp -> right;
  }
  if (comp(old -> data, d) > 0)
     old -> left = new bnode<T>(d, 0, 0);
  else
     old -> right = new bnode<T>(d, 0, 0);

} template <class T> T gen_tree<T>::find(bnode<T>* r, T d) const {

  if (r == 0)
     return 0;
  else if (comp(r -> data, d) ==  0)
     return (r -> data);
  else if (comp(r -> data, d) > 0)
     return (find( r -> left, d));
  else
     return (find( r -> right, d));

} template <class T> void gen_tree<T>::print(bnode<T> *r) const {

  if (r != 0) {
     print( r -> left);
     r -> bnode<T>::print();
     print ( r -> right);
  }

} template <class T> //general case int comp(T i, T j) {

  if (i == j)          //assumes ==  < defined for T
     return 0;
  else
     return ( (i < j) ? -1 : 1 );

} //specialization for const char* int comp(const char* i, const char* j){

  return (strcmp(i, j));

} int main() {

  char             dat[256];
  gen_tree<char*>  t;
  char*            p;
  while (cin>>dat){
     p = new char[strlen(dat) + 1];
     strcpy(p, dat);
     t.insert(p);
  }
  t.print();
  cout << "EOF" << endl << endl;
  gen_tree<int>  i_tree;
  for (int i = 15; i > -5; --i)
     i_tree.insert(i);
  i_tree.print();

}


 </source>


Using Default Arguments with Template Classes

<source lang="cpp">

  1. include <iostream>
  2. include <cstdlib>

using namespace std;

template <class T=int, int size=10> class MyClass {

 T a[size]; // size of array is passed in size

public:

 MyClass() {
   register int i;
   for(i=0; i<size; i++) a[i] = i;
 }
 T &operator[](int i);

};

template <class T, int size> T &MyClass<T, size>::operator[](int i) {

 if(i<0 || i> size-1) {
   cout << "\nIndex value of ";
   cout << i << " is out-of-bounds.\n";
   exit(1);
 }
 return a[i];

}

int main() {

 MyClass<int, 100> intarray;  
 MyClass<double> doublearray; 
 MyClass<> defarray;          
  
 cout << "int array: ";
 for(int i=0; i<100; i++) intarray[i] = i;
 for(int i=0; i<100; i++) cout << intarray[i] << endl;
  
 cout << "double array: ";
 for(int i=0; i<10; i++) doublearray[i] = (double) i/3;
 for(int i=0; i<10; i++) cout << doublearray[i] << endl;
  
 cout << "defarray array: ";
 for(int i=0; i<10; i++) defarray[i] = i;
 for(int i=0; i<10; i++) cout << defarray[i] << endl;
  
 return 0;

}


 </source>


Using exceptions with templates.

<source lang="cpp">

  1. include <iostream>

using namespace std; const int DefaultSize = 10; class xBoundary {}; template <class T> class Array { public:

   Array(int itsSize = DefaultSize);
   Array(const Array &rhs);
   ~Array() { delete [] pType;}
   Array& operator=(const Array<T>&);
   T& operator[](int offSet);
   const T& operator[](int offSet) const;
   int GetitsSize() const { return itsSize; }
   friend ostream& operator<< (ostream&, const Array<T>&);
   class xSize {};
private:
   int *pType;
   int  itsSize;
};
template <class T>
Array<T>::Array(int size):
itsSize(size)
{
   if (size <10 || size > 30000)
      throw xSize();
   pType = new T[size];
   for (int i = 0; i<size; i++)
     pType[i] = 0;
}
template <class T>
Array<T>& Array<T>::operator=(const Array<T> &rhs)
{
   if (this == &rhs)
      return *this;
   delete [] pType;
   itsSize = rhs.GetitsSize();
   pType = new T[itsSize];
   for (int i = 0; i<itsSize; i++)
      pType[i] = rhs[i];
}
template <class T>
Array<T>::Array(const Array<T> &rhs)
{
   itsSize = rhs.GetitsSize();
   pType = new T[itsSize];
   for (int i = 0; i<itsSize; i++)
      pType[i] = rhs[i];
}
template <class T>
T& Array<T>::operator[](int offSet)
{
   int size = GetitsSize();
   if (offSet >= 0 && offSet < GetitsSize())
      return pType[offSet];
   throw xBoundary();
   return pType[0];
}
template <class T>
const T& Array<T>::operator[](int offSet) const
{
   int mysize = GetitsSize();
   if (offSet >= 0 && offSet < GetitsSize())
      return pType[offSet];
   throw xBoundary();
}
template <class T>
ostream& operator<< (ostream& output, const Array<T>& theArray)
{
   for (int i = 0; i<theArray.GetitsSize(); i++)
      output << "[" << i << "] " << theArray[i] << endl;
   return output;
}

int main(){

   try
   {
      Array<int> intArray(9);
      for (int j = 0; j< 100; j++)
       {
          intArray[j] = j;
          cout << "intArray[" << j << "] okay..." << endl;
       }
    }
    catch (xBoundary)
    {
       cout << "Unable to process your input!\n";
    }
    catch (Array<int>::xSize)
    {
       cout << "Bad Size!\n";
    }
    cout << "Done.\n";
    return 0;

}


 </source>


Using Non-Type Arguments with Generic Classes

<source lang="cpp">

  1. include <iostream>
  2. include <cstdlib>

using namespace std;

template <class T, int size> class MyClass {

 T a[size]; // length of array is passed in size

public:

 MyClass() {
   register int i;
   for(i=0; i<size; i++) a[i] = i;
 }
 T &operator[](int i);

};

template <class T, int size> T &MyClass<T, size>::operator[](int i) {

 if(i<0 || i> size-1) {
   cout << i << " is out-of-bounds.\n";
   exit(1);
 }
 return a[i];

}

int main() {

 MyClass<int, 10> intob;       
 MyClass<double, 15> doubleob; 
  
 for(int i=0; i<10; i++) 
    intob[i] = i;
 for(int i=0; i<10; i++) 
    cout << intob[i] << endl;
  
 for(int i=0; i<15; i++) 
    doubleob[i] = (double) i/3;
 for(int i=0; i<15; i++) 
    cout << doubleob[i] << "  ";
  
 return 0;

}


 </source>