0

We have just started OOP but due to sudden vacation we got an assignment in which many concepts weren't taught like templates, so I am still skeptical about whether I used it correctly or not. And this is my first question here, so sorry if my formatting is not correct.

#include<iostream>
using namespace std;
#include<string>
//global error flag for dequeue
bool ERR_Flag = false;
template<class T>
class queue
{
    protected:
    int front;
    int rear;
    int capacity;
    T *ele;
    public:
    //constructor to allocate memory and initialize data members
    queue();
    bool isempty();
    bool isfull();
    //Check if queue is full before insertion
    //if queue is full return false
    // insert element and return true otherwise
    bool enqueue(T data);
    //funtion to remove an element and return
    T dequeue();
    ~queue();
    void print();
};
template<class T>
class deque:public queue<T>
{
    public:
    bool push_Back(T data);
    bool push_Front(T data);
    T pop_Front();
    T pop_Back();
};
template<>
queue<int> :: queue()
{
    front = -1;
    rear = -1;
    capacity = 5;
    int ele[5];
}
template<>
bool queue<int> :: isempty()
{
    if(front == -1 && rear == -1)
    {
        return 1;
    }
    else
    {
        return 0;
    }
}
template<>
bool queue<int> :: isfull()
{
    if(rear = capacity - 1)
    {
        return 1;
    }
    else
    {
        return 0;
    }
}
template<>
bool queue<int> :: enqueue(int data)
{
    if(front == -1 && rear == -1)
    {
        front++;
        rear++;
        ele[rear] = data;
        return 1;
    }
    else if(rear == capacity - 1)
    {
        rear++;
        ele[rear] = data;
        return 1;
    }
    else
    {
        return 0;
    }
}
template<>
int queue<int> :: dequeue()
{
    if(front == -1)
    {
        ERR_Flag = 0;
    }
    else
    {
        int a;
        a = ele[front];
        return a;
        front--;
    }
}
template<>
void queue<int> :: print()
{
    cout<<ele[front];
}
template<>
bool deque<string> :: push_Front(string data)
{
    if(front == -1 && rear == -1)
    {
        front = 0;
        rear = 0;
        ele[front] = data;
        return 1;
    }
    else if(rear == capacity - 1)
    {
        return 0;
    }
    else
    {
        for(int i = rear; i >= 0; i--)
        {
            ele[i+1] = ele[i];
        }
        rear++;
        ele[front] = data;
        return 1;
    }
}
template<>
bool deque<string> :: push_Back(string data)
{
    if(front == -1 && rear == -1)
    {
        front = 0;
        rear = 0;
        ele[0] = data;
        return 1;
    }
    else if(rear == capacity - 1)
    {
        return 0;
    }
    else
    {
        rear++;
        ele[rear] = data;
        return 1;
    }
}
template<>
string deque<string> :: pop_Front()
{
    if(front == -1)
    {
        ERR_Flag = 0;
    }
    else
    {
        string s;
        s = ele[front];
        front++;
        return s;
    }
}
template<>
string deque<string> :: pop_Back()
{
    if(front == -1)
    {
        ERR_Flag = 0;
    }
    else
    {
        string s;
        s = ele[rear];
        rear--;
        return s;
    }
}
int main()
{
    int d_Choice;
    int op_Choice;
    deque<string> d;
    queue<int> q;
    cin>>d_Choice;  
    if(d_Choice==1)
    {
        while(1)
        {
            cin>>op_Choice;
            if(op_Choice==1)
            {
                if(q.isempty())
                cout<<"Queue is empty"<<endl;
                else
                cout<<"Queue is not empty"<<endl;
            }
            else if(op_Choice==2)
            {
                if(q.isfull())
                cout<<"Queue is full"<<endl;
                else
                cout<<"Queue is not full"<<endl;
            }
            else if(op_Choice==3)
            {
                int data;
                cin>>data;
                if(!q.enqueue(data))
                cout<<"Queue full insertion not possible";
            }
            else if(op_Choice==4)
            {
                q.dequeue();
                if(ERR_Flag)
                cout<<"Queue is empty";
            }
            else if(op_Choice==5)
            {
                q.print();
            }
            else if(op_Choice==6)
            {
            break;
            }
        }
    }
    else if(d_Choice==2)
    {
        string s_Data;
        while(1)
        {
            cin>>op_Choice;
            if(op_Choice==1)
            {
                if(d.isempty())
                cout<<"Queue is empty"<<endl;
                else
                cout<<"Queue is not empty"<<endl;
            }
            else if(op_Choice==2)
            {
                if(d.isfull())
                cout<<"Queue is full"<<endl;
                else
                cout<<"Queue is not full"<<endl;
            }
            else if(op_Choice==3)
            {
                cin>>s_Data;
                if(!d.push_Back(s_Data))
                cout<<"Queue full insertion not possible";
            }
            else if(op_Choice==4)
            {
                cin>>s_Data;
                if(!d.push_Front(s_Data))
                cout<<"Queue full insertion not possible";              

            }
            else if(op_Choice==5)
            {
                d.pop_Back();
                if(ERR_Flag)
                cout<<"Queue is empty";
            }
            else if(op_Choice==6)
            {
                d.pop_Front();
                if(ERR_Flag)
                cout<<"Queue is empty";
            }
            else if(op_Choice==7)
            {
                d.print();              
            }
            else if(op_Choice==8)
            {
                break;
            }
        }
    }
}

Error:

/tmp/ccw2hdxf.o: In function `main':
main.cpp:(.text+0x6c5): undefined reference to `queue::isempty()'
main.cpp:(.text+0x719): undefined reference to `queue::isfull()'
main.cpp:(.text+0x8df): undefined reference to `queue::print()'
main.cpp:(.text+0x90d): undefined reference to `queue::~queue()'
main.cpp:(.text+0x962): undefined reference to `queue::~queue()'
/tmp/ccw2hdxf.o: In function `deque<std::string>::deque()':
main.cpp:(.text._ZN5dequeISsEC2Ev[_ZN5dequeISsEC5Ev]+0x14): undefined reference to `queue::queue()'
/tmp/ccw2hdxf.o: In function `deque<std::string>::~deque():
main.cpp:(.text._ZN5dequeISsED2Ev[_ZN5dequeISsED5Ev]+0x14): undefined reference to `queue::~queue()'
collect2: error: ld returned 1 exit status

I can only change the declarations of functions since other things have been given in the question.

EDIT: After defining the member functions for T, I am getting the following errors. And I can't change anything except the declaration for the member functions since the definitions for member functions and the main function is already provided. CODE:

#include<iostream>
using namespace std;
#include<string>
//global error flag for dequeue
bool ERR_Flag = false;
template<class T>
class queue
{
    protected:
    int front;
    int rear;
    int capacity;
    T *ele;
    public:
    //constructor to allocate memory and initialize data members
    queue();
    bool isempty();
    bool isfull();
    //Check if queue is full before insertion
    //if queue is full return false
    // insert element and return true otherwise
    bool enqueue(T data);
    //funtion to remove an element and return
    T dequeue();
    ~queue();
    void print();
};
template<class T>
class deque:public queue<T>
{
    public:
    bool push_Back(T data);
    bool push_Front(T data);
    T pop_Front();
    T pop_Back();
};
template<typename T>
queue<T> :: queue()
{
    front = -1;
    rear = -1;
    capacity = 5;
    T ele[5];
}
template<typename T>
bool queue<T> :: isempty()
{
    if(front == -1 && rear == -1)
    {
        return 1;
    }
    else
    {
        return 0;
    }
}
template<typename T>
bool queue<T> :: isfull()
{
    if(rear == capacity - 1)
    {
        return 1;
    }
    else
    {
        return 0;
    }
}
template<typename T>
bool queue<T> :: enqueue(T data)
{
    if(front == -1 && rear == -1)
    {
        front++;
        rear++;
        ele[rear] = data;
        return 1;
    }
    else if(rear == capacity - 1)
    {
        rear++;
        ele[rear] = data;
        return 1;
    }
    else
    {
        return 0;
    }
}
template<typename T>
T queue<T> :: dequeue()
{
    if(front == -1)
    {
        ERR_Flag = 0;
    }
    else
    {
        T a;
        a = ele[front];
        return a;
        front--;
    }
}
template<typename T>
void queue<T> :: print()
{
    cout<<ele[front];
}
template<typename T>
bool deque<T> :: push_Front(T data)
{
    if(front == -1 && rear == -1)
    {
        front = 0;
        rear = 0;
        ele[front] = data;
        return 1;
    }
    else if(rear == capacity - 1)
    {
        return 0;
    }
    else
    {
        for(int i = rear; i >= 0; i--)
        {
            ele[i+1] = ele[i];
        }
        rear++;
        ele[front] = data;
        return 1;
    }
}
template<typename T>
bool deque<T> :: push_Back(T data)
{
    if(front == -1 && rear == -1)
    {
        front = 0;
        rear = 0;
        ele[0] = data;
        return 1;
    }
    else if(rear == capacity - 1)
    {
        return 0;
    }
    else
    {
        rear++;
        ele[rear] = data;
        return 1;
    }
}
template<typename T>
T deque<T> :: pop_Front()
{
    if(front == -1)
    {
        ERR_Flag = 0;
    }
    else
    {
        T s;
        s = ele[front];
        front++;
        return s;
    }
}
template<typename T>
T deque<T> :: pop_Back()
{
    if(front == -1)
    {
        ERR_Flag = 0;
    }
    else
    {
        T s;
        s = ele[rear];
        rear--;
        return s;
    }
}
int main()
{
    int d_Choice;
    int op_Choice;
    deque<string> d;
    queue<int> q;
    cin>>d_Choice;  
    if(d_Choice==1)
    {
        while(1)
        {
            cin>>op_Choice;
            if(op_Choice==1)
            {
                if(q.isempty())
                cout<<"Queue is empty"<<endl;
                else
                cout<<"Queue is not empty"<<endl;
            }
            else if(op_Choice==2)
            {
                if(q.isfull())
                cout<<"Queue is full"<<endl;
                else
                cout<<"Queue is not full"<<endl;
            }
            else if(op_Choice==3)
            {
                int data;
                cin>>data;
                if(!q.enqueue(data))
                cout<<"Queue full insertion not possible";
            }
            else if(op_Choice==4)
            {
                q.dequeue();
                if(ERR_Flag)
                cout<<"Queue is empty";
            }
            else if(op_Choice==5)
            {
                q.print();
            }
            else if(op_Choice==6)
            {
            break;
            }
        }
    }
    else if(d_Choice==2)
    {
        string s_Data;
        while(1)
        {
            cin>>op_Choice;
            if(op_Choice==1)
            {
                if(d.isempty())
                cout<<"Queue is empty"<<endl;
                else
                cout<<"Queue is not empty"<<endl;
            }
            else if(op_Choice==2)
            {
                if(d.isfull())
                cout<<"Queue is full"<<endl;
                else
                cout<<"Queue is not full"<<endl;
            }
            else if(op_Choice==3)
            {
                cin>>s_Data;
                if(!d.push_Back(s_Data))
                cout<<"Queue full insertion not possible";
            }
            else if(op_Choice==4)
            {
                cin>>s_Data;
                if(!d.push_Front(s_Data))
                cout<<"Queue full insertion not possible";              

            }
            else if(op_Choice==5)
            {
                d.pop_Back();
                if(ERR_Flag)
                cout<<"Queue is empty";
            }
            else if(op_Choice==6)
            {
                d.pop_Front();
                if(ERR_Flag)
                cout<<"Queue is empty";
            }
            else if(op_Choice==7)
            {
                d.print();              
            }
            else if(op_Choice==8)
            {
                break;
            }
        }
    }
}

ERROR:

> main.cpp: In member function ‘bool deque<T>::push_Front(T)’:
> main.cpp:113:8: error: ‘front’ was not declared in this scope
     if(front == -1 && rear == -1)
        ^~~~~
>main.cpp:113:23: error: ‘rear’ was not declared in this scope
     >if(front == -1 && rear == -1)
                       ^~~~
>main.cpp:117:9: error: ‘ele’ was not declared in this scope
         >ele[front] = data;
         ^~~
>main.cpp:120:21: error: ‘capacity’ was not declared in this scope
     >else if(rear == capacity - 1)
                     ^~~~~~~~
>main.cpp:128:13: error: ‘ele’ was not declared in this scope
             >ele[i+1] = ele[i];
             ^~~
>main.cpp:131:9: error: ‘ele’ was not declared in this scope
         >ele[front] = data;
         ^~~
>main.cpp: In member function ‘bool deque<T>::push_Back(T)’:
>main.cpp:138:8: error: ‘front’ was not declared in this scope
     >if(front == -1 && rear == -1)
        ^~~~~
>main.cpp:138:23: error: ‘rear’ was not declared in this scope
     >if(front == -1 && rear == -1)
                       ^~~~
>main.cpp:142:9: error: ‘ele’ was not declared in this scope
         >ele[0] = data;
         ^~~
>main.cpp:145:21: error: ‘capacity’ was not declared in this scope
     >else if(rear == capacity - 1)
                     ^~~~~~~~
>main.cpp:152:9: error: ‘ele’ was not declared in this scope
         >ele[rear] = data;
         ^~~
>main.cpp: In member function ‘T deque<T>::pop_Front()’:
>main.cpp:159:8: error: ‘front’ was not declared in this scope
     >if(front == -1)
        ^~~~~
>main.cpp:166:13: error: ‘ele’ was not declared in this scope
         >s = ele[front];
             ^~~
>main.cpp: In member function ‘T deque<T>::pop_Back()’:
>main.cpp:174:8: error: ‘front’ was not declared in this scope
     >if(front == -1)
        ^~~~~
>main.cpp:181:13: error: ‘ele’ was not declared in this scope
         >s = ele[rear];
             ^~~
>main.cpp:181:17: error: ‘rear’ was not declared in this scope
         >s = ele[rear];
```                 ^~~~

  • This is a linker error. How are you compiling your program? – Vishnu CS Mar 28 '20 at 18:33
  • `using namespace std;` is your big fault. [Why is "using namespace std;" considered bad practice?](https://stackoverflow.com/questions/1452721/why-is-using-namespace-std-considered-bad-practice) – 273K Mar 28 '20 at 18:35
  • @S.M. It seems like the big problem on first view and could easily become one, but it is not the reason for OP's particular errors in this case, see my answer. – walnut Mar 28 '20 at 18:38
  • looks like someone already answered your question but I noticed something when looking at your code. In queue::isfull you write "if(rear = capacity - 1)", but you want == there – Scott M Mar 28 '20 at 18:44
  • 1
    @ScottM The code has multiple more issues. For example some functions that are declared non-`void` do not always return values (e.g. `int queue :: dequeue()`), etc. @OP Compile your program with the `-Wall -Wextra` flags and you will get many warning messages. *Fix all of these!*. – walnut Mar 28 '20 at 18:52
  • Also the whole ERR_FLAG mechinsm is very non-C++. Instead use exceptions. – walnut Mar 28 '20 at 18:54
  • @walnut agreed! lots of things to fix, but I just wanted to point out the one I saw before I stopped looking at the post – Scott M Mar 28 '20 at 18:54
  • @ScottM Thank you, I have changed those silly mistakes. – Karan Ramalingam Mar 29 '20 at 08:01
  • @S.M. We have just started cpp, so I have no idea why it can give an error. Thank you, for providing the link for it. – Karan Ramalingam Mar 29 '20 at 08:03
  • @VishnuCS I don't know what that means. – Karan Ramalingam Mar 29 '20 at 08:05

1 Answers1

2

You are using deque<string> which inherits from queue<string> in main. So when you call e.g. d.isempty(), then you are calling the member function of the queue<string> class.

But you only defined a definition for queue<int>::is_empty(), not for queue<string>::is_empty(), which is what the error message is telling you.

The other error messages have similar reasons.

Why are you using explicit specializations in the first place? Just define your member functions for all types T, e.g.:

template<typename T>
bool queue<T> :: isempty()
{
    if(front == -1 && rear == -1)
    {
        return 1;
    }
    else
    {
        return 0;
    }
}

instead of

template<>
bool queue<int> :: isempty()
{
    if(front == -1 && rear == -1)
    {
        return 1;
    }
    else
    {
        return 0;
    }
}

As mentioned in the question comments, using namespace std; could also easily cause issues here. There are already class templates named queue and deque in the std:: namespace and if they happen to be included, it will become ambigious whether these names refer to your classes or the ones in std::. Don't use using namespace std; and instead import only the names you need with using declarations, e.g.:

using std::cout;
using std::endl;
using std::string;
using std::cin;

and so on.

walnut
  • 21,629
  • 4
  • 23
  • 59
  • Ah, I didn't know how to use templates. I have fixed it now and as I mentioned it above I can't change anything except the declaration of the functions since the function definition and main is already provided, so I can't change using namespace std;. – Karan Ramalingam Mar 29 '20 at 07:52
  • After defining the member functions for T, it seems that class deque is not getting inherited from the class queue. – Karan Ramalingam Mar 29 '20 at 08:00
  • @KaranRamalingam For the new errors you mention in your question, see [Why do I have to access template base class members through the this pointer?](https://stackoverflow.com/questions/4643074/why-do-i-have-to-access-template-base-class-members-through-the-this-pointer), i.e. you have to write `this->front` instead of `front` in a derived class to access members of a dependent base class. – walnut Mar 29 '20 at 16:50