Overloading comparison operators for stacks - c++

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.

Related

How can I overload [] operator in C++ for a function of two args?

I have a class Priority Queue with method push() which takes two args: value and priority.
#include <vector>
#include <iostream>
class PriorityQueue
{
private:
std::vector<std::pair<int, int>> _queue;
public:
int top();
int pop();
void push(int, int);
int size();
PriorityQueue();
PriorityQueue(int, int);
friend std::ostream& operator<<(std::ostream&, PriorityQueue&);
};
How can I overload [] operator for it to work like this:
queue[priority]=value;
should mean
queue.push(priority, value);
?
You have to return type which will do the push on operator=, something like:
class PriorityQueue
{
private:
std::vector<std::pair<int, int>> _queue;
struct Proxy
{
PriorityQueue* queue;
int priority;
Proxy& operator=(int value) { queue->push(priority, value); return *this; }
};
public:
// ...
Proxy operator[](int priority) { return {this, priority}; }
};
How can I overload [] operator in C++ for a function of two args?
The subscript operator is always a binary operator i.e. it always has two operands. If you define the subscript as a member operator, then the left hand operand will be *this and as such you can only have one more operand.
How can I overload [] operator for it to work like this:
queue[priority]=value;
In the subscript operator overload, return an object that points to *this and has an overloaded assignment operator that calls queue.push(priority, value).

Implement a generic stack container as an adaptor class template

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.

Creating a set of classes

I'm trying to create a set that can be filled with instances of a class. I thought that a requirement for a set is that elements can be compared, and thus in this case I need to tell my class how they can be compared. I created the following class:
class Myclass
{
public:
Myclass(int i):storedval(i) {}
int getval(){return storedval;}
friend bool operator> (Myclass &first, Myclass &second)
{
return first.getval()>second.getval();
}
friend bool operator< (Myclass &first, Myclass &second)
{
return first.getval()<second.getval();
}
private:
int storedval;
};
But when I try to add instances to a set like this:
Myclass a(50);
set<Myclass> Bunchofclasses;
Bunchofclasses.insert(a);
It gives me a bunch of error text that I think tells me it doesn't understand the > and < operators. How should this be done properly?
You need to pass const references to the comparison function because it should not be allowed to modify the items being compared:
friend bool operator< (const Myclass& first, const Myclass& second)
{ // ^^^^^ ^^^^^
return first.getval() < second.getval();
}
This will require that you make getVal() const as well. This makes it callable on const instances or via const references:
int getval() const {return storedval;}
// ^^^^^
Note that you do not need operator> for the set to work. Less-than is enough.
Strictly speaking, you do not need a friend function here, since you are calling public member functions. The only thing that friend brings here is to allow you to declare a non-member function inside of the class definition.
Elements of a set are immutable, so the set needs to be able to compare const values. So the comparison needs to be:
friend bool operator< (Myclass const &first, Myclass const &second)
// ^^^^^ ^^^^^
(You should probably also do this with operator> and any other non-mutating operations you provide; but set only needs operator<).
Also, in order to access the value of a const object, the accessor also needs to be const:
int getval() const
// ^^^^^

C++ directed graph node with template implementation

I am writing program which has a multitude of Directed Graph helper functions in order to gain a deeper understanding of C++. One of the central objects is called a Node which has member functions to help with calculating travel distance between nodes. I am trying to gain a better understanding of using C++ templates in OOP design.
Here is a quick snapshot of the Node class
class Node {
friend void swap(Node & first, Node & second) {
using std::swap;
swap(first.name, second.name);
}
public:
Node(std::string val);
Node(const Node & copy);
Node & operator = (Node copy) {
swap(*this, copy);
return *this;
}
bool operator < (Node & rhs) const {
return (size < rhs.size);
}
bool operator > (Node & rhs) const {
return (size > rhs.size);
}
bool insertEdge(Node * dest, int distToNode);
// I'd like for this return type to not be tied to an int
// Especially if weights were represented as floats or doubles
int findTravelDistance(Node * const & toNode) const;
int findTravelDistance(std::queue<Node *> * const & nodeRoute) const;
// Mutators
void setNodeName(const std::string nameToSet);
std::string getNodeName() const;
void setNodeSize(const int size);
int getNodeSize() const;
// Misc
void toString() const;
// Constants
static const bool ALLOW_CIRCULAR;
~Node();
protected:
private:
int size;
std::string name;
// Here int represents the weight of the edge. I would like it to be able to be
// declared as an int, float, long, or double etc...
std::map<Node *, int> * travelEdges;
}; // end class
} // end namespace
As I build this class to include more functionality, I find myself struggling with how to make my functions more adaptable. For instance, look at the findTravelDistance functions.
What I would like to do is have the return type representing weight be type agnostic and the ordered map data structure's value to be type agnostic. As it is currently implemented, a user can only declare a type int for the weight. I realize I could embark upon function overloading. But, I feel this would be too redundant and an obvious violation of the DRY principle. If I were to have to change how this function works, I would have to change it for every overload. So my gut instinct tells me I should use C++ templates. Since I am new to templates, I am struggling with where to declare it. If I make my find functions template functions and just return the generic type..
template<class T>
T findTravelDistance(std::queue<Node *> * const & nodeRoute) const;
That will solve my problem there. But, it doesn't fix the issue where the underlying map data structure representing edges can only hold ints. My next thought was to declared a class template..
template<class T>
class Node { ... }
But this also seemed odd to me. This would mean declaration and initialization would look something like
Node<float> * n = new Node<float>("N");
If I were a user of my program, I would not immediately associate Node with the float type representing edge weights.
So what is the best or appropriate usage of a template in this case? Or is using a template even the correct path here? It is possible my class design is flawed to begin with and not very C++'esk. Any feedback here is much appreciated.
This is very clean code :). Welcome to C++!
I believe what you want to do is use a template variable to hold your edge weights. How about something like the following:
using std::swap;
template<class Distance>
class Node {
friend void swap(Node & first, Node & second) {
swap(first.name, second.name);
}
public:
Node(std::string val);
Node(const Node & copy);
Node & operator = (Node copy) {
swap(*this, copy);
return *this;
}
bool operator < (Node & rhs) const {
return (size < rhs.size);
}
bool operator > (Node & rhs) const {
return (size > rhs.size);
}
bool insertEdge(Node * dest, Distance distToNode);
// I'd like for this return type to not be tied to an int
// Especially if weights were represented as floats or doubles
Distance findTravelDistance(Node * const & toNode) const;
Distance findTravelDistance(std::queue<Node *> * const & nodeRoute) const;
// Mutators
void setNodeName(const std::string nameToSet);
std::string getNodeName() const;
void setNodeSize(const Distance size);
int getNodeSize() const;
// Misc
void toString() const;
// Constants
static const bool ALLOW_CIRCULAR;
~Node();
private:
int size;
std::string name;
std::map<Node *, Distance> * travelEdges;
}; // end class
As a bonus, I've moved your using declarations to the top of the class. Generally these go at the top of the file. You also might benefit from taking a look at the holy scripture that is the Parashift C++ FAQ, particularly the section on const correctness. Your comparator methods, for example, should have const Node& parameters.

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)