Implement a generic stack container as an adaptor class template - c++

I'm having some trouble in my Data Structures (cop 4530) class. I need to "Implement a generic Stack container as an adaptor class template". My template and the implementation are in two different files stack.h and stack.hpp (this is required). I wanted to do this Stack set up as an Array, but it seems as though my teacher set it us up to do it as a linked list if I'm not wrong?? I'm just confused on how to get started setting up the stack as an Array if someone could explain it to me (we have a very useless book). And all I really need is someone to explain to me just a few of the functions from ".hpp" where I implement my Stack code. Particularly the copy / move functions. (If it's better or easier for me to do it a different way than I'm trying then please share)
Here's Stack.h; These are all interfaces of the "Stack class Template" we needed to include
#include <iostream>
#define MAX_SIZE 100
namespace cop4530{
template<typename T>
class Stack{
private:
int A[MAX_SIZE];
int top;
public:
Stack();
~Stack();
Stack (const Stack<T>&);
Stack(Stack<T> &&);
Stack<T>& operator= (const Stack <T>&);
Stack<T> & operator=(Stack<T> &&);
bool empty() const;
void clear();
void push(const T& x);
void push(T && x);
void pop();
T& top();
const T& top() const;
int size() const;
void print(std::ostream& os, char ofc = ' ') const;
}
//non-member global functions
std::ostream& operator<< (std::ostream& os, const Stack<T>& a);
bool operator== (const Stack<T>&, const Stack <T>&);
bool operator!= (const Stack<T>&, const Stack <T>&);
bool operator< (const Stack<T>& a, const Stack <T>& b);
#include "Stack.hpp"
}
#endif
And here's the separate "Stack.hpp" file that holds the implementation of some of them.
#include "stack.h"
#include <iostream>
namespace cop4530{
template<typename T>
Stack<T>::Stack(){
//zero argument constructor
}
template<typename T>
Stack<T>::~Stack(){ //destructor
clear();
}
template<typename T>
Stack<T>::Stack(const Stack<T>&){ //copy constructor
}
template<typename T>
Stack<T>::Stack(Stack<T> &&){ //move constructor
}
template<typename T>
Stack<T>::Stack<T> & Stack<T>::operator=(const Stack<T> &){
//copy assignment operator=
}
template<typename T>
Stack<T>::Stack<T> & Stack<T>::operator=(Stack<T> &&){
//move assignment operator=
}
/*does this look right? I don't think so...*/
template<typename T>
void Stack<T>::push(const T& x){ //adds x to the stack, copy version
insert(begin(), x);
}
template<typename T>
void Stack<T>::push(T && x){ // adds x to the stack, move version
insert(begin(), std::move(val));
}

To implement the Stack as a adapter class for array you should really start from the basic functionality of a stack. Let's consider a few basics:
constructor- created an empty stack
isFull/isEmpty - return true/false depending on how much space is available in your stack.
push - adds one element at the top of the queue
pop - removes the first element from the top of the queue
Let's start with the constructor: you could say that your stack is empty when top == -1. Since your array is statically allocated (you can consider to dynamically allocate memory for the array in the constructor), all you need to do is top =-1 and you have yourself an empty stack.
isFull/isEmpty now become obvious:
isEmpty: return top == -1
isFull: return top == MAX_SIZE
PUSH: adds one elements to the top of the stack:
if (!isFull)
{
top++;
A[top] = new_element;
}
I'll let you figure out the rest; the idea is to update the stack pointer top and always keep an eye on how much space you have available.

Related

How to check which type of subscript operator is called, lvalue or rvalue? [duplicate]

This question already has answers here:
c++ two versions of overloading subscript operator
(4 answers)
Closed 3 years ago.
I wrote a Vector wrapper class. And I want to overload the subscript operator for this class.
If a user want to set a value to an index which is bigger than the size. I will resize the vector size to index*2.
But if a user want to get a value from an index which is bigger than the size. I will throw an exception.
So, How can check these two situations in the overloaded operator method ?
Vector.h:
#include <iostream>
#include <vector>
using namespace std;
template <class T>
class Vector {
vector<T> v;
public:
T& operator[] (const int index);
T getmax ();
int add (T val);
int size();
int capacity();
};
Vector.cpp
#include "Vector.h"
template <class T>
T Vector<T>::getmax (){
T retval;
return retval;
}
template <class T>
T& Vector<T>::operator[] (const int index){
//How to check that which is called => v[5]=10(setting) or cout<<v[5]/getting)?
if(index>v.size()-1){
v.resize(index*2);
return v[index];
}
else{
return v[index];
}
}
template <class T>
int Vector<T>::add (T val){ //return index
v.push_back(val);
}
template <class T>
int Vector<T>::size (){
return v.size();
}
template <class T>
int Vector<T>::capacity (){
return v.capacity();
}
main.cpp
#include "Vector.cpp"
#include <iostream>
int main () {
Vector<int> myobject;
myobject.add(67);
myobject[2]=99;
cout <<"myobject[0]:"<<myobject[0]<<endl;
cout <<"myobject[1]:"<<myobject[1]<<endl;
cout <<"myobject[2]:"<<myobject[2]<<endl;
cout <<"myobject[3]:"<<myobject[3]<<endl;
return 0;
}
You can overload operator [] for const and non-const objects.
T& operator[] (const int index);
T const& operator[] (const int index) const;
However, if you have a non-const object, the first overload will be called even if your intention is to get and not set. If you want to implement different behavior between get and set, it will be better to have two such functions.
T const& get(int index) const;
void set(int index, T const&);
It's not possible for operator[] to know whether the user intends to get or set. However, there is a workaround. You can make your operator[] return some type, let's call it VectorSubscriptResult<T>, that holds a reference to the vector and to the index that was requested. This type VectorSubscriptResult<T> would have an operator T&, which would be invoked if someone wanted to get the value, and an operator=, which would be invoked if someone wanted to set it. (I'll leave it as an exercise for the reader how to handle the case of operator[]() const.)

Implementing swap/copy functions: is there a better way?

These are how I implemented the swap and copy functions for my queue.
Is there a better way?
template <class T>
void Queue<T>::copy(Queue<T> const & other)
{
if(this == &other)
return;
if(m_size != 0)
this->clear();
this->m_cap = other.m_cap;
this->enqueue(other);
}
template <class T>
void Queue<T>::swap(Queue<T> const & other)
{
if(this == &other)
return;
std::swap(this->m_front, other.m_front);
std::swap(this->m_back, other.m_back);
std::swap(this->m_size, other.m_size);
std::swap(this->m_cap, other.m_cap);
}
Thank you:)
Instead of a copy method, you should instead implement a copy constructor. It would be strange for the copy constructor to be passed an instance of itself. If you insist on checking, you can use an assertion.
template <class T>
Queue<T>::Queue(Queue<T> const & other)
: m_cap(other.m_cap), m_size(0), m_front(), m_back()
{
assert(&other != this);
enqueue(other);
}
Your copy method is actually an assignment. It is more natural to implement an assignment operator. This can be accomplished by following the copy-swap idiom.
template <class T>
Queue<T> & Queue<T>::operator = (Queue<T> other)
{
swap(*this, other);
return *this;
}
There is also an idiomatic way to implement swap (taught to me by Mooing Duck a long time ago):
template <class T>
class Queue {
//...
friend void swap(Queue &a, Queue &b) {
using std::swap;
swap(a.m_front, b.m_front);
swap(a.m_back, b.m_back);
swap(a.m_size, b.m_size);
swap(a.m_cap, b.m_cap);
}
};
This way, you can use argument dependent lookup (ADL) to pick the type specific swap implementation if available. And now Queue itself has such an implementation, which is used by the assignment operator. But it can also be used in the case Queue is put inside an object that wants to implement swap for itself.

Overloading comparison operators for stacks

I need some help here: I'm asked to do some overloading to comparison operators of 2 stacks. I have the syntax figured out, I'm just having trouble writing the definition. So please help me.
At least to one operator overload and then I will do it for the rest.
struct linklist
{
int no;
struct linklist *next;
};
class Stack
{
private:
linklist *list,*head;
public://constructor and destructor
Stack();
~Stack();
public:// main functions
void push();
void show();
void pop();
public://overloaded operations
friend bool operator == (const Stack &stack1, const Stack &stack2);
friend bool operator != (const Stack &stack1, const Stack &stack2);
friend bool operator < (const Stack &stack1, const Stack &stack2);
friend bool operator > (const Stack &stack1, const Stack &stack2);
};
It really depends on what you actually want to compare. Is it identity of stacks or just number of elements on stacks? Since you want to define smaller and greater operators, I assume you want to compare the number of elements in the stacks.
The equal operator would be like this:
bool operator==( const Stack &stack1, const Stack &stack2)
{
return stack1.list->no == stack2.list->no;
}
Of course you need to consider cases where the list member of a Stack object is NULL.

ostream problems

So I have two classes inside the same file; ArrayLinkedList and ArrayLinkedListRow
Inside the first mentioned one I have a method
template<class T> friend ostream& operator <<(ostream& s, ArrayLinkedList<T>& ll){
//Extra code for giving s content
return s;
}
as well as having
template<class T> friend ostream& operator <<(ostream& s, ArrayLinkedListRow<T>& ll){
//Extra code for giving s content
return s;
}
inside of ArrayLinkedListRow.
I get the following error
Error 1 error C2995: 'std::ostream &operator <<(std::ostream
&,ArrayLinkedList &)' : function template has already been
defined
and it's driving me nuts not knowing how to fix it. I have done my research, but still I cannot figure out what to do. I strongly believe that the two classes might be related in the problem, despite of the error just pointing out to one line.
Extra Info:
This is the class ArrayLinkedList header for those who feel confused with my short explanation.
template<class DT>
class ArrayLinkedList {
private:
DT* _info[MAX_SIZE]; // store data
int _next[MAX_SIZE]; // next node
int _nextEmpty[MAX_SIZE]; //next empty slot
ArrayClass< ArrayLinkedListRow<DT> >* _rows;
int _head; // head of the list
int _firstEmpty; // first empty slot
int _size;
void copy(const ArrayLinkedList<DT>& ll);//copy from another list
// add a new node with next as it's next node and returns the index of new node
int newNode( DT& newObject, int next);
public:
ArrayLinkedList(); // empty and copy constructors
ArrayLinkedList(const ArrayLinkedList<DT>& ll);
//copy constructors linked list object to an existing object. This is a deep copy.
~ArrayLinkedList(); // destructor
ArrayLinkedList(DT& newObject); // Constructor that create a list with newObject as the head
ArrayLinkedList(int capacity); // Constructor with a give capacity
ArrayLinkedList(DT& newObject,int capacity);// Constructor with newObject as the head and capacity
bool isEmpty(); // is the list empty?
int size(); // return the number of nodes stored
void add(DT& newObject); // add an object to the tail
void insertAt(DT& newObject, int position); // insert an object at the position specified
DT remove(); // remove the head
DT removeAt(int position); // remove an object at the position specified
int find(DT key); // find the object that matches key, index of the object
void operator=(const ArrayLinkedList<DT>& ll); // = operator
// overloading [] operator, return a reference to object at the
// Add a new data element to the start of a linked list.
DT& operator[] (const int position); // position in the linked list
// ostream operator
template<class T> friend ostream& operator <<(ostream& s, ArrayLinkedList<T>& ll){
return s;
}
void displayRaw(); // display raw data of the data members
};
Try to remove the template<class T> part:
friend ostream& operator <<(ostream& s, ArrayLinkedList& ll){
//Extra code for giving s content
return s;
}
// and analogically with ArrayLinkedListRow
The reason why this works is stated here:
If you declare a variable ArrayLinkedList<int>, then and only then the operator << is created with the template-parameter T and DT (which is unused). If you compile this, everything works fine.
If you add a variable of type ArrayLinkedList<float>, then the operator gets defined a second time and this creates the error.
Working only with DT makes it work as expected.

Vector, proxy class and dot operator in C++

A question related to a custom Vector class in C++.
template <typename T>
class Vector
{ ...
private:
T * mData; int mSize;
public:
proxy_element operator[](const size_type index) { return proxy_element(*this, index); }
const T& operator[](const size_type index) const { return mData[index]; }
};
template <typename T>
class proxy_element
{ ...
proxy_element(Vector<T>& m_parent, const size_type index);
proxy_elem& operator=(const T& rhs); // modifies data so invalidate on other memories
bool operator==(const proxy_elem& rhs) // only read, just copy data back.
...
}
The reason for using proxy_element class is to distinguish and optimize read and writes operations, considering that the vector data can reside in GPU device memories as well. So any read operation require only to copy latest data back (if any) but a readwrite/write operation require invalidating data in device memories.
This design work well when the element type is primitive. However for more complex element types, there is one issue:
struct person{ int age; double salary; };
int main()
{
Vector<person> v1(10);
v[1].age = 10; // gives error as operator[] returns proxy_element for which "." operator has no meaning
}
AFAIK, the "." operator cannot be overload in C++. One obvious solution is to not use proxy_elem and just return regular reference (T &), assuming that each access is a write access, but that will be inefficient for obvious reasons.
Is there any other work around which gives me "." operator working while retaining ability to distinguish between read and write operations?
One option is to make such data types immutable (private member variables, initialised by a constructor, and the only setter is the class's assignment operator). This way, the only means to change anything is to assign to an entire instance of the class, which can be channeled through a proxy_element.
Marcelo Cantos's answer is, of course, the proper way to do things. However, there is the complicated and crazy workaround of specialization. (Not recommended.)
//if it's a class, inherit from it to get public members
template<class T>
class proxy_element : public T {
...
proxy_element(Vector<T>& m_parent, const size_type index);
proxy_elem& operator=(const T& rhs); // modifies data so invalidate on other memories
bool operator==(const proxy_elem& rhs) // only read, just copy data back.
...
};
//pretend to be a pointer
template<>
class proxy_element<T*> {
...
proxy_element(Vector<T>& m_parent, const size_type index);
proxy_elem& operator=(const T& rhs); // modifies data so invalidate on other memories
bool operator==(const proxy_elem& rhs) // only read, just copy data back.
...
};
//otherwise, pretend to be primitive
#define primitive_proxy(T) \
template<> class proxy_element {
...
proxy_element(Vector<T>& m_parent, const size_type index);
proxy_elem& operator=(const T& rhs); // modifies data so invalidate on other memories
bool operator==(const proxy_elem& rhs) // only read, just copy data back.
...
};
primitive_proxy(char)
primitive_proxy(unsigned char)
primitive_proxy(signed char) //this is distinct from char remember
primitive_proxy(short)
primitive_proxy(unsigned short)
primitive_proxy(int)
primitive_proxy(unsigned int)
primitive_proxy(long)
primitive_proxy(unsigned long)
primitive_proxy(long long)
primitive_proxy(unsigned long long)
primitive_proxy(char16_t) //if GCC
primitive_proxy(char32_t) //if GCC
primitive_proxy(wchar_t)
primitive_proxy(float)
primitive_proxy(double)
primitive_proxy(long double)