Template Class Help

I am attempting to convert a class to a template class, I am confused how to call from the declaration of the template class from the function. If anyone has some advice or examples that would help me better understand what I need to be doing. I already looked on Google and thought it was helping but I don't think it fully applies to my situation.

FiniteStack.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#ifndef FINITESTACK_H
#define FINITESTACK_H

//class  IntFiniteStack {
template <class C> 
class FiniteStack {
  private:
   // int* items;
	 C* items; 
   // int size; // array size (capacity of stack)
	 C size() const; 
    //int top;
	 C & top; 
  public:
    class StackEmptyException{ }; // empty inner class for exception handling
    class StackFullException{ }; // empty inner class for exception handling
    //IntFiniteStack();
	FiniteStack();
    //IntFiniteStack(int size);
	FiniteStack(C size); 
    virtual ~FiniteStack();
    void push(C const & c) ;
    C pop();
    bool isEmpty();
    bool isFull();
};

#endif 


FiniteStack.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include "FiniteStack.h"
template <class C>
FiniteStack<C>::FiniteStack() {
  top = 0;
  size = 10;
  items = new int[10]; //default size
}
template <class C> 
FiniteStack<C>::FiniteStack(C size) {
  top = 0;
  this->size = size;
  items = new int[size];
}

// destructor: free all the memory allocated for the stack
template <class C> 
FiniteStack<C>::~FiniteStack() {
  delete [] items;
}

// push a data onto the stack
template <class C>
void FiniteStack<C>::push(C const &data) {
  if (isFull())
    throw StackFullException();
  items[top] = data;
  top++; // to combine two lines ==> items[top++] = data
}

// pop the data from the stack
template <class C>
C FiniteStack<C>::pop() {
  if (isEmpty())
    throw StackEmptyException();
  --top;
  return items[top]; // to combine two lines ==> return items[--top];
}

// is stack empty?
template <class C> 
bool FiniteStack<C>::isEmpty() {
  if (top == 0) return true;
  else return false;
}

// is stack full?
template <class C> 
bool FiniteStack<C>::isFull() {
  if (top == size) return true;
  else return false;
}


main.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
#include <iostream>
using namespace std;

#include "FiniteStack.h"

int main() {
 
  FiniteStack<int> s1(5);
 
  // Stack empty test
  if (s1.isEmpty()) {
      cout << "s1 is empty at the beginning." << endl;
  } else {
      cout << "s1 must be empty. Something's wrong!" << endl;
  }
  
    s1.push(1);
    s1.push(2);	
    s1.push(3);
    s1.push(4);
    s1.push(5);
  
  // Stack full test
  if (s1.isFull()) {
      cout << "s1 is full after five push() calls." << endl;
  } else {
      cout << "s1 must be full. Something's wrong!" << endl;
  }
  
  // pop() test: reverses the items
  cout << "Expected: 5 4 3 2 1 -->" << endl;
  for (int i = 0; i < 5; i++) {
      cout << s1.pop() << endl;
  }
  
  // Stack empty test
  if (s1.isEmpty()) {
      cout << "s1 is empty after five pop() calls." << endl;
  } else {
      cout << "s1 must be full. Something's wrong!" << endl;
  }

  // StackFullException test
  cout << "Expected: StackFullException --> ";
  try {
    s1.push(1);
    s1.push(2);
    s1.push(3);
    s1.push(4);
    s1.push(5);
    s1.push(6);
  } catch (FiniteStack::StackEmptyException) {
    cout << "Exception: cannot pop, stack is empty" << endl;
  } catch (FiniteStack::StackFullException) {
    cout << "Exception: cannot push, stack is full" << endl;
  }
  
  // StackEmptyException test
  cout << "Expected: StackEmptyException --> ";
  try {
    s1.pop(); s1.pop(); s1.pop(); s1.pop(); s1.pop(); s1.pop();

  } catch (FiniteStack::StackEmptyException) {
    cout << "Exception: cannot pop, stack is empty" << endl;
  } catch (FiniteStack::StackFullException) {
    cout << "Exception: cannot push, stack is full" << endl;
  }
  
  return 0;

}
closed account (o1vk4iN6)

If you use FiniteStack<float> there will be some errors. As such you can not use a float as an index for an array.

1
2
3
4
5
6
7

C & top; // this shouldn't be a reference, and should be of type uint (not C)

C size() const; // should return uint (unsigned int)

FiniteStack(C size); // should take parameter of uint (not C)


also:

1
2
3
4

  if (top == 0) return true;
  else return false;


This is redundant, using a if statement to check a condition just to return the same condition.

 
return top == 0; // same thing 
So I think the declrations should looks something more like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#ifndef FINITESTACK_H
#define FINITESTACK_H

//class  IntFiniteStack {
template <class C> 
class FiniteStack {
  private:
   // int* items;
	 int* items; 
   // int size; // array size (capacity of stack)
	 int size() const; 
    //int top;
	 int & top; 
  public:
    class StackEmptyException{ }; // empty inner class for exception handling
    class StackFullException{ }; // empty inner class for exception handling
    //IntFiniteStack();
	FiniteStack();
    //IntFiniteStack(int size);
	FiniteStack(C size); 
    virtual ~FiniteStack();
    void push(int) ;
    int pop();
    bool isEmpty();
    bool isFull();
};

#endif

I thought the whole point of a template class was so that you could define an element with type "T" or whatever you choose when initializing the template, and then you could stack variables with that template variable and then later declare it as a unit type, such as, int or string.
The items var can be of type "T", but top and size must be an int as you are using it as an index.

1
2
3
4
5
6
   // C* items;
	 C* items; 
   // int size; // array size (capacity of stack)
	 int size() const; 
    //index of top item;
	 int top; 
Last edited on
thanks for your help spaggy and xerzi, my compiler is taking everything except the StackEmptyException and StackFullException. When I attmpt to build it returns the following errors:

1>c:\users\ryan\documents\visual studio 11\projects\programming ii\prog07-part1\prog07-part1\main.cpp(52): error C2065: 'StackEmptyException' : undeclared identifier
1>c:\users\ryan\documents\visual studio 11\projects\programming ii\prog07-part1\prog07-part1\main.cpp(52): error C2316: 'FiniteStack' : cannot be caught as the destructor and/or copy constructor are inaccessible
1>c:\users\ryan\documents\visual studio 11\projects\programming ii\prog07-part1\prog07-part1\main.cpp(54): error C2065: 'StackFullException' : undeclared identifier
1>c:\users\ryan\documents\visual studio 11\projects\programming ii\prog07-part1\prog07-part1\main.cpp(54): error C2316: 'FiniteStack' : cannot be caught as the destructor and/or copy constructor are inaccessible
1>c:\users\ryan\documents\visual studio 11\projects\programming ii\prog07-part1\prog07-part1\main.cpp(54): error C2312: 'FiniteStack' : is caught by 'FiniteStack' on line 52
1>c:\users\ryan\documents\visual studio 11\projects\programming ii\prog07-part1\prog07-part1\main.cpp(63): error C2065: 'C' : undeclared identifier
1>c:\users\ryan\documents\visual studio 11\projects\programming ii\prog07-part1\prog07-part1\main.cpp(63): error C2955: 'FiniteStack' : use of class template requires template argument list
1> c:\users\ryan\documents\visual studio 11\projects\programming ii\prog07-part1\prog07-part1\finitestack.h(6) : see declaration of 'FiniteStack'
1>c:\users\ryan\documents\visual studio 11\projects\programming ii\prog07-part1\prog07-part1\main.cpp(63): error C2316: 'FiniteStack<C>::StackEmptyException' : cannot be caught as the destructor and/or copy constructor are inaccessible
1>c:\users\ryan\documents\visual studio 11\projects\programming ii\prog07-part1\prog07-part1\main.cpp(65): error C2065: 'C' : undeclared identifier
1>c:\users\ryan\documents\visual studio 11\projects\programming ii\prog07-part1\prog07-part1\main.cpp(65): error C2955: 'FiniteStack' : use of class template requires template argument list
1>c:\users\ryan\documents\visual studio 11\projects\programming ii\prog07-part1\prog07-part1\main.cpp(65): error C2316: 'FiniteStack<C>::StackFullException' : cannot be caught as the destructor and/or copy constructor are inaccessible
1> FiniteStack.cpp
closed account (o1vk4iN6)
1
2
3
4
5
6
7
8
9
10
11
12

  try
  {
    /* ... */
  } 
  catch (FiniteStack<int>::StackEmptyException) 
  {
  } 
  catch (FiniteStack<int>::StackFullException)
  {
  }


As it is a template type you need to specify the template as well if you want to access the exception classes. You could possibly create a "base" stack class which FiniteStack inherits which would define the exception classes instead.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

class BaseStack
{
public:
    class StackEmptyException { };
    class StackFullException { };
};

template<class C>
class FiniteStack : BaseStack
{
    /* ... */
};


try
{
}
catch( BaseStack::StackFullException )
{
}


Also why do you have a virtual destructor ? You are adding overhead to the class for no reason.
Last edited on
Not sure why i had the virtual in there but I got rid of that. Also I found out that I was suppose to have the function declarations in the h file instead of the cpp. I was able to get everything to work, and I am very grateful for everyone's help, don't worry i'll have another program soon that I cannot figure out :)

Heres what I got to work for anyone who wants to know:

FiniteStack.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
#ifndef FINITESTACK_H
#define FINITESTACK_H

#include <iostream>
#include <cstdlib>

using namespace std; 

template <typename C> 
class FiniteStack {
  private:
	 C *items; 
	 int size; 
	 int top; 
  public:
    class StackEmptyException{ };; // empty inner class for exception handling
    class StackFullException{ };;// empty inner class for exception handling
	FiniteStack();
	FiniteStack(int size); 
	//FiniteStack(const FiniteStack<C>&); 
    ~FiniteStack();
    void push(int) ;
    int pop();
    bool isEmpty();
    bool isFull();
};

template <typename C>
FiniteStack<C>::FiniteStack() {
  top = 0;
  size = 10;
  items = new int[10]; //default size
}
template <typename C> 
FiniteStack<C>::FiniteStack(int size){
  top = 0;
  this->size = size;
  items = new int[size];
}

// destructor: free all the memory allocated for the stack
template <typename C> 
FiniteStack<C>::~FiniteStack() {
  delete [] items;
}

// push a data onto the stack
template <typename C>
void FiniteStack<C>::push(int data) {
  if (isFull())
    throw StackFullException();
  items[top] = data;
  top++; // to combine two lines ==> items[top++] = data
}

// pop the data from the stack
template <typename C>
int FiniteStack<C>::pop() {
  if (isEmpty())
    throw StackEmptyException();
  --top;
  return items[top]; // to combine two lines ==> return items[--top];
}

// is stack empty?
template <typename C> 
bool FiniteStack<C>::isEmpty() {
  if (top == 0) return true;
  else return false;
}

// is stack full?
template <typename C> 
bool FiniteStack<C>::isFull() {
  if (top == size) return true;
  else return false;
}
#endif 


main.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#include <iostream>
using namespace std;

#include "FiniteStack.h"

int main() {
	FiniteStack<int> s1(5);

  // Stack empty test
  if (s1.isEmpty()) {
      cout << "s1 is empty at the beginning." << endl;
  } else {
      cout << "s1 must be empty. Something's wrong!" << endl;
  }
  
    s1.push(1);
    s1.push(2);	
    s1.push(3);
    s1.push(4);
    s1.push(5);
  
  // Stack full test
  if (s1.isFull()) {
      cout << "s1 is full after five push() calls." << endl;
  } else {
      cout << "s1 must be full. Something's wrong!" << endl;
  }
  
  // pop() test: reverses the items
  cout << "Expected: 5 4 3 2 1 -->" << endl;
  for (int i = 0; i < 5; i++) {
      cout << s1.pop() << endl;
  }
  
  // Stack empty test
  if (s1.isEmpty()) {
      cout << "s1 is empty after five pop() calls." << endl;
  } else {
      cout << "s1 must be full. Something's wrong!" << endl;
  }

  // StackFullException test
  cout << "Expected: StackFullException --> ";
  try {
    s1.push(1);
    s1.push(2);
    s1.push(3);
    s1.push(4);
    s1.push(5);
    s1.push(6);
  } catch (FiniteStack<int>::StackEmptyException) {
    cout << "Exception: cannot pop, stack is empty" << endl;
  } catch (FiniteStack<int>::StackFullException) {
    cout << "Exception: cannot push, stack is full" << endl;
  }
  
  // StackEmptyException test
  cout << "Expected: StackEmptyException --> ";
  try {
    s1.pop(); s1.pop(); s1.pop(); s1.pop(); s1.pop(); s1.pop();

  } catch (FiniteStack<int>::StackEmptyException) {
    cout << "Exception: cannot pop, stack is empty" << endl;
  } catch (FiniteStack<int>::StackFullException) {
    cout << "Exception: cannot push, stack is full" << endl;
  }
  
  return 0;

}
Topic archived. No new replies allowed.