Declaring Template Class Variables

 

Hey, I have implemented this Queue that takes any type. I want to use like this since I don't know the max size at time of initialization: 

Queue<double> q; 
// Work
q = Queue<double>(20); // Where 20 is the max size of the queue

This causes the following errors: 

" '>'- unexpected token", " '20' - parameter passed as reference, variable expected" " '20' - illegal operation use" 


However, this code works: 

Queue<double> *q; 
// Work 
q = new Queue<double>(20); 

How do I implement the variable 'q' without the usage of pointers (since I don't like using pointers unless their usage is a great for memory efficiency).


Here is the full implementation of the generic Queue class: 

template <typename T>
class Queue{
   private: 
      T q [];
   protected: 
      int front;
      int rear;
      int max_size;
      int curr_size; 
   public: 
   
      Queue(){}
      
      Queue(int arr_size){
         this.front = -1;
         this.rear = -1;
         this.curr_size = 0; 
         this.max_size = arr_size;
         ArrayResize(q, this.max_size);
      }
      
      ~Queue(){}
      
      bool IsEmpty(){
         return this.front == -1 && this.rear == -1; 
      }
      
      
      bool IsFull(){
         return this.curr_size == this.max_size; 
      }
      
      bool Enqueue(T element){
         if(IsFull()){
            return false; 
         }
         else if(IsEmpty()){
            this.front = 0; 
            this.rear = 0; 
         }
         else{
            this.rear = (this.rear + 1) % this.max_size; 
         }
         
         q[this.rear] = element; 
         this.curr_size++; 
         return true; 
      }
      
      bool Dequeue(T &element){
         if(IsEmpty()){
            return false;
         }
         element = q[this.front];
         
         if(this.front == this.rear){
            this.front = -1; 
            this.rear = -1; 
         }
         else{
            this.front = (this.front + 1) % this.max_size; 
         }
         
         this.curr_size--; 
         return true; 
      }
      
      int Get_Size(){
         return this.curr_size; 
      }
      
      int Get_Max_Size(){
         return this.max_size; 
      }
      
      bool Peak_At_Front(T &element){
         if(IsEmpty()){
            return false; 
         }
         
         element = q[this.front]; 
         return true; 
      }
};
 
TraderTogami:

Hey, I have implemented this Queue that takes any type. I want to use like this since I don't know the max size at time of initialization: 

This causes the following errors: 

" '>'- unexpected token", " '20' - parameter passed as reference, variable expected" " '20' - illegal operation use" 


However, this code works: 

How do I implement the variable 'q' without the usage of pointers (since I don't like using pointers unless their usage is a great for memory efficiency).


Here is the full implementation of the generic Queue class: 

Add a resize or initialize method to the class which does the same as the constructor right now. 

 
Laszlo Tormasi #:

Add a resize or initialize method to the class which does the same as the constructor right now. 

I think I kinda understand what you alluding to. What you are saying would work, but what if I make another generic type class, I don't want to be thinking about making reparameterizing methods just in case I don't know all the parameters upon initialization. Is there a general way to modify a generic type class such that a code similar to the one below would work (maybe even modifying the code below so that it works without pointers)? 


Class_A<double> q; 
// Work
q = Class_A<double>(parameters); 
 
TraderTogami #:

I think I kinda understand what you alluding to. What you are saying would work, but what if I make another generic type class, I don't want to be thinking about making reparameterizing methods just in case I don't know all the parameters upon initialization. Is there a general way to modify a generic type class such that a code similar to the one below would work (maybe even modifying the code below so that it works without pointers)? 


If I understand correctly, you would need two more constructors. A Copy Constructor for the assignment operation and a parameter constructor for the parameterization.

 
TraderTogami #:

I think I kinda understand what you alluding to. What you are saying would work, but what if I make another generic type class, I don't want to be thinking about making reparameterizing methods just in case I don't know all the parameters upon initialization. Is there a general way to modify a generic type class such that a code similar to the one below would work (maybe even modifying the code below so that it works without pointers)? 


You can not avoid writing class specific code. As Dominik mentioned you need at least a copy constructor. 

Dirty example: 

Within class: 

      void operator =(Queue*queue)
         {
         this.front = queue.front;
         this.rear = queue.rear;
         this.curr_size = queue.curr_size; 
         this.max_size = queue.max_size;
         ArrayResize(q, this.max_size);
         delete queue;
         };


Now you can: 

Queue<double> q; 

q = new Queue<double>(20); 

"q" is not a pointer here. 
 
Dominik Christian Egert #:
If I understand correctly, you would need two more constructors. A Copy Constructor for the assignment operation and a parameter constructor for the parameterization.

Thanks, this makes sense, but not sure how to implement, can you show me an example of these two methods (the example can be of a very small generic class)?

Laszlo Tormasi #:

You can not avoid writing class specific code. As Dominik mentioned you need at least a copy constructor. 

Dirty example: 

Within class: 

Now you can: 

"q" is not a pointer here. 
Interesting, but won't this form a conflict when q is defined as a pointer. It just seems weird to be assigning a non-pointer object with the new operator 
 
TraderTogami #:

Thanks, this makes sense, but not sure how to implement, can you show me an example of these two methods (the example can be of a very small generic class)?

Interesting, but won't this form a conflict when q is defined as a pointer. It just seems weird to be assigning a non-pointer object with the new operator 

Here is an example:

template <typename T>
class test3_obj
{
    public:
    T value;
    
    test3_obj() :
        value (NULL)
    { };

    test3_obj(const T p_in) :
        value (p_in)
    { };
    
    test3_obj(const test3_obj& p_in) :
        value (p_in.value)
    { Print("Copy C"); };

    test3_obj       operator=   (const test3_obj& p_in)             { value = p_in.value; return(this); };
    const bool      operator>   (const test2_obj& p_in) const       { return(value > p_in.value); };
};


template <typename T>
class test3_derived : public test3_obj<T>
{
    public:
    test3_derived()
    { };
    
    test3_derived(const T p_in) :
        test3_obj(p_in)
    { };
    
    test3_derived(const test3_derived& p_in) :
        test3_obj(p_in)
    { Print("Copy D"); };

    test3_derived   operator=   (const test3_derived& p_in)         { value = p_in.value; return(this); };
    const bool      operator>   (const test3_derived& p_in) const   { return(value > p_in.value); };
};


Assigning a "new" object to a stack object will call the assignment operator "operator=", you will loose track of the heap-object-pointer and therefore cannot call "delete" on it, so you will have memory leaks.

I dont advice this, I suggest not using the new operator instead.

 
Laszlo Tormasi #:

You can not avoid writing class specific code. As Dominik mentioned you need at least a copy constructor. 

Dirty example: 

Within class: 

Now you can: 

"q" is not a pointer here. 

Your solutiuon will lead to memory leaks, as you loose the pointer to the object created by "new". - Also you are showing an assignment-operator, not a copy constructor. - they are different in their usage, as you can see in my example. - The assignment-operator will return an object of itself, thus calling the copy constructor in this process...

Their usage has different applications, assignment is the explicit assignemtn of values, while the copy constructor is instantiating the object and asisgning the values of the object itself.

Although you could call the assignment operator inside the copoy-constructor, this is not always adviseable. - Can lead to recursion calls.


EDIT:

Yes, I saw, you called the delete operator on the passed object, this is not good practice, you should avoid such coding habbits. - Dont do it.

EDIT2:

The creator of an object is always responsible for the deletion. You really should not deviate from this good practice, it will save you lots of headache. - Only exception is when you are using some sort of container where you know, when storing a pointer in it, it will also be deleted when the containers life-spann is ending. (Having a cleanup-destructor in the container)

 
Dominik Christian Egert #:

Your solutiuon will lead to memory leaks, as you loose the pointer to the object created by "new". - Also you are showing an assignment-operator, not a copy constructor. - they are different in their usage, as you can see in my example. - The assignment-operator will return an object of itself, thus calling the copy constructor in this process...

Their usage has different applications, assignment is the explicit assignemtn of values, while the copy constructor is instantiating the object and asisgning the values of the object itself.

Although you could call the assignment operator inside the copoy-constructor, this is not always adviseable. - Can lead to recursion calls.


EDIT:

Yes, I saw, you called the delete operator on the passed object, this is not good practice, you should avoid such coding habbits. - Dont do it.

That's why I called it "dirty". Creating an object just to initialize another. I just wanted to show that writing class specific code can not be avoided does not matter if it is a copy constructor or not. As I assume op wanted to avoid writing class specific initializer or copy constructor. 

 
Laszlo Tormasi #:

That's why I called it "dirty". Creating an object just to initialize another. I just wanted to show that writing class specific code can not be avoided does not matter if it is a copy constructor or not. As I assume op wanted to avoid writing class specific initializer or copy constructor. 

I see, yes. I think your point is clear. But it should not be such a "dirty" hack. - Wouldnt it be better to stick to good practice when showing a solution. It might lead someone else to have false impressions on how to do things. - Especially when they cannot "subtract" the dirt from a shown code...

 
Dominik Christian Egert #:

Here is an example:

Assigning a "new" object to a stack object will call the assignment operator "operator=", you will loose track of the heap-object-pointer and therefore cannot call "delete" on it, so you will have memory leaks.

I dont advice this, I suggest not using the new operator instead.

What if attributes of the object are non-public? How would implementation change? Would I have to make "getter" and "setter" methods or is there another way? 

Reason: