Templates, I got some problems with function calling

I was working a bit with this code:

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
//This code tells us what happens in the scope of Stack

#include <iostream>
using namespace std ;
#include "stack.hh"    //the header file declares Stack
                      

  void Stack::push(double c) { 
    if (full()) {
      cout << "Stack::push() the Stack is getting 10 more elements" << endl ;
      _s.resize(_s.size()+10);
    }
    _s[count++] = c ;
  }
  
  double Stack::pop() { 
    if (empty()) {
      cout << "Stack::pop() Error: stack is empty" << endl ;
      return 0 ;
    }    
    return _s[--count] ;
  }

void Stack::inspect() {       // an inspection function that prints the
int i;                        // stack contents in the right order and
for(i=count-1 ; i>=0 ; i--){  // and gives the value of the stack content
cout<< "[" << i << "] = " << _s[i] << endl;
} 
}

Stack::Stack(int length, double def)
	{
	  Array<def> _s(int length, def);
	  }


and it uses this code for the template function Array:


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
79
80
81
82
83
84
#include<iostream>
#ifndef ARRAY_HH
#define ARRAY_HH
using namespace std;

template <class T>
class Array {
public:

 
  Array(int size, T def) : _size(size), _arr(0), blank(def) {  //Making and Filling up the array with default values
    _arr = new T[_size] ;   
    for(int i=0; i<_size ; i++){
      _arr[i] = blank ;
    }
  }

  Array(const Array<T>& other) : _size(other._size) { //copying an array into a new array
    _arr = new T[other._size] ;
    // Copy elements
    for (int i=0 ; i<_size ; i++) {
      _arr[i] = other._arr[i] ;
    }
  }

  ~Array() {                       //destructor
    delete[] _arr ;
  }

  Array<T>& operator=(const Array<T>& other) 
  {
    if (&other==this) return *this ;
    if (_size != other._size) {
      resize(other._size) ;
    }
    for (int i=0 ; i<_size ; i++) {
      _arr[i] = other._arr[i] ;
    }
  }

  T& operator[](int index) {         //when an element beyond the range of the array is accessed, this operator resizes the array so the called for element is included in the array
    if(index >= _size) {
      resize(index + 1);
    }
    return _arr[index] ;
  }
  const T& operator[](int index) const {
    if(index >= _size) {
      resize(index + 1);
    }
    return _arr[index] ;
  }

  int size() const { return _size ; }

  void resize(int newSize)      //resizing the array to the desired length
  {
    // Allocate new array
    T* newArr = new T[newSize] ;
    // Copy elements
    for (int i=0 ; i< _size ; i++) {
      newArr[i] = _arr[i] ;
    }
    
    for(int i = _size; i < newSize ; i++ ){         //filling up the undefined elements with default values
    newArr[i] = blank;
    }

    // Delete old array and install new one
    if (_arr) {
      delete[] _arr ;
    }
    _size = newSize ;
    _arr = newArr ;
  }

private:
  int _size ;
  T* _arr ;
  T blank;
} ;

#endif


I also have a header file and a main, but they don't give any trouble.

when i try to compile it, I get this error message:

1
2
3
4
5
6
7
8
stack.cc: In constructor ‘Stack::Stack(int, double)’:
stack.cc:31: error: no matching function for call to ‘Array<double>::Array()’
Array.hh:18: note: candidates are: Array<T>::Array(const Array<T>&) [with T = double]
Array.hh:11: note:                 Array<T>::Array(int, T) [with T = double]
stack.cc:33: error: ‘def’ cannot appear in a constant-expression
stack.cc:33: error: template argument 1 is invalid
stack.cc:33: error: ‘def’ is not a type
stack.cc:33: error: invalid type in declaration before ‘;’ token


What's the best thing I can do here? Cuz I tried a lot of things to get rid of this error in line 31, but all attempts failed.
1
2
3
4
Stack::Stack(int length, double def)
	{
	  Array<def> _s(int length, def);
	  }


You are trying to construct a template using a variable name instead of a typename which you cannot do. It makes no sense. Also why are you creating a temporary array which would be destroyed immediately after the constructor finishes? Why do you think that _s would exist for the other functions? If it is a class attribute then you have a major problem with the design of the Stack class. Your Stack class looks like it also needs to be a template and its template type would have to be used for constructing _s. You should rework this and if you have more question post your declaration of Stack, array, and a main function that tries to use them so that we can fully understand what you are trying to do.
This is all wrong:

Stack::Stack(int length, double def)
{
    Array<def> _s(int length, def);

}


Should be ?

Stack::Stack(int length, double def)
{
    Array<double> _s(length, def);

}
The compiler error is very informative. It says that in the constructor, you are attempting to create an Array<double> using its [non-existent] default constructor (line 33). Additionally, it continues to suggest that the template parameter (also on line 33) should not be 'def'. I think 'double' is what you are after. Then (still on line 33), there is a extra 'int'. You'll probably find that fixing the 'int' one will fix the first one, sometimes the errors are related.

However, this constructor is only creating a local Array, anyway; so line 33 could effectively be removed altogether. I suspect that in stack.hh, there is a member (maybe named _s?) that you are trying to initialize or assign to. Post stack.hh for advice.
Thanks for your reply moorecem, the most useful for me sofar
Ok, here is my stack.hh:

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
//In this header file all the functions are being declared
#include <iostream>
#include "Array.hh"
#ifndef STACK_HH
#define STACK_HH
using namespace std;

struct Stack {
public:  
  // Interface
  Stack(int length, double def);                //constructor
  /*
  Stack(const Stack& copy) ;         // copy constructor
  ~Stack() { close() ; };              //destructor
  */
  int nitems() { return count ; }
  bool full() { return (count==_s.size()) ; }
  bool empty() { return (count==0) ; }
  
  void push(double c);
  double pop();
  
  void inspect();
  
    private:      // Implementation
  Array<double> _s;
  int count ;
  
};
#endif



and here's the main code:

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
//This is the main code for the Stack exercise

#include <iostream>
#include "stack.hh"         //The Header file declares Stack
using namespace std;

int main() {
  
  Stack s(5,0) ;               //Stack is being referred to a s throughout the code
  
  // Write doubles into Stack
  int i ;
  for (i=0 ; i<5 ; i++) {
    cout << "pushing value " << i*100 << " in stack" << endl ;
    s.push(i*100) ;
  }
  s.inspect();
  
  // Count doubles in stack
  cout << s.nitems() << " value in stack" << endl ;
  
  /*
  Stack sclone(s) ;
  cout << "cloned stack after cloning" << endl;
  sclone.inspect() ;
  */
  
  // Read doubles back from stack
  while (!s.empty()) {
    double val = s.pop() ;
    cout << "popping value " << val << " from stack" << endl ;
  }
  s.inspect();

  return 0 ;
}


I use this program to practice with templates function. Later on I have to change the class stack into a template as well, but before that I want to check if this is working properly.

One of my problems is that I have still problems with the basics. At some points I have kinda an idea what my code is doing, but not exactly. So that may be the reason why I am doing weird or funny stuff on some places, just because I don't know any better.
Ok, so there is a member _s. So in the Stack constructor, there is no need to declare another Array<double>. Additionally, though, since Array does not have a default constructor you'll have to specify its constructor's arguments in the initialization list.

Try this on for size:
1
2
3
4
Stack::Stack(int length, double def)
 : _s( length, def )  // this calls the constructor for _s, which is 'Array<T>::Array( int, T ) [with T = double]' 
{
}


Without the initialization list, the Stack constructor attempts to default construct _s, until you [optionally] assign it a value later. Later could actually be quite soon--as soon as inside the {}'s of the constructor, for example!
Last edited on
It's been a while since I had no time to work on my code.
Thanks, now my code finally compiles without any complaints.

Sadly enough I encountered another problem. While I'm running the program, I get this message:

1
2
3
4
pushing value 0 in stack
terminate called after throwing an instance of 'std::bad_alloc'
  what():  std::bad_alloc
Aborted


Something must go wrong with the memory allocation, but I've not really an idea why.
never mind. I found the culprit of my problem. In my code I didn't set "count = 0" while calling the Stack constructor and therefore I get a problem in Stack::push _s[count++] = c. Count is set to nitems(), so doing _s[count++] I am trying to assign c to an element of my stack that has no allocated memory.
Topic archived. No new replies allowed.