Exception Safe Code for Generic Stack Class - c++

I am trying to write a exception safe generic stack. This is what I have done so far.
#include <iostream>
#include <memory>
#include <exception>
class stk_exception:public exception
{
virtual const char* what() const throw()
{
return "stack underflow";
}
} stk_ex;
template <class T>
struct node
{
T data;
node<T> *next;
};
template <class T>
class stack_generic
{
public:
stack_generic() : _head(nullptr) {
}
void push(T x) {
node<T> *temp(new node<T>());
temp->data = x;
temp->next = _head;
_head = temp;
}
void pop() {
if (_head == nullptr) {
throw stk_ex;
} else {
node<T> *temp = _head;
_head = _head->next;
delete temp;
return;
}
}
T top() {
T x = T();
if (_head == nullptr) {
throw stk_ex;
} else {
return _head->data;
}
}
private:
node<T> *_head;
};
int main()
{
stack_generic<int> s;
s.push(1);
s.push(2);
std::cout << s.top();
s.pop();
std::cout << s.top();
s.pop();
}
I could have used STL list/vector for RAII, but I want to work with raw pointers. So, when I wrap the head pointer in stack with unique_ptr, it throws a compilation error "no matching function for call unique_ptr, default_delete. What's wrong here? Can anyone suggest what should I do to make this class exception safe? Thanks!
EDIT:
Added exception handling for underflow.
defined seperate top and pop methods

The following implementation should be (almost) exception-safe:
void push(T x) {
head = new node<T>{std::move(x), head};
}
T pop(void) {
if (head) {
T result{std::move(head->data)};
auto old = head;
head = head->next;
delete old;
return result;
} else {
cout << "underflow!";
return T{};
}
}
The only problem of this code is the return result. In general, this operation might throw an exception, and in this case, the caller sees an exception, but the stack was nevertheless changed.
You can avoid this problem by separating the function into two functions. The first function returns the top element, and the second function removes it.

Best practice is to use the std::shared_ptr. You could implement the class like this:
#include <iostream>
#include <memory>
#include <exception>
template <class T>
class node
{
public:
node(T data, std::shared_ptr<node<T>> next)
: _data(data), _next(next)
{
}
T data() const
{
return _data;
}
std::shared_ptr<node<T>> next() const
{
return _next;
}
private:
T _data;
std::shared_ptr<node<T>> _next;
};
template <class T>
class stack_generic
{
public:
stack_generic()
: _head(nullptr)
{
}
void push(T x)
{
_head = std::make_shared<node<T>>(x, _head);
}
T pop()
{
if (_head == nullptr) {
throw std::underflow_error("underflow");
} else {
std::shared_ptr<node<T>> temp = _head;
_head = _head->next();
return temp->data();
}
}
private:
std::shared_ptr<node<T>> _head;
};
int main()
{
stack_generic<int> s;
s.push(1);
s.push(2);
std::cout << s.pop();
std::cout << s.pop();
}
Note the following things:
Using of using namespace std; is bad practice.
Use nullptr instead of NULL for modern C++ programs.
Use an exception for the underflow to create a defined behaviour.
Use accessor methods on the node to create a read-only object.
Use a constructor for the node.
Using for example std::shared_ptr to automatically free data.

Related

How to use template for implementing STACK using LINKEDLIST in cpp

So i am trying to create a c++ file which implements stack and all its functions(push,pop,getTop,etc). I want to use Template so that i can make this Stack class for multiple datatypes. I am using linked list to store the data. Here is some example of stack i have implemented using linked list.
#include<iostream>
using namespace std;
template <class T>
class Node{
public:
T data;
Node *next;
Node()
{
next = NULL;
}
};
class Stack
{
Node *top;
public:
Stack();
int isEmpty();
int isFull();
void push(T data);
T pop();
void display();
};
Stack :: Stack()
{
top = NULL;
}
int Stack :: isEmpty()
{
if(top == NULL)
{
return 1;
}
else
{
return 0;
}
}
int Stack :: isFull()
{
int temp;
Node *t = new Node;
if(t==NULL)
{
temp = 1;
}
else
{
temp = 0;
}
delete t;
return temp;
}
void Stack :: push(T data)
{
Node *n;
if(isFull())
{
cout<<"\nStack overflow";
}
else
{
n = new Node;
n->data = data;
n->next = top;
top = n;
}
}
int Stack :: pop()
{
Node *t;
T temp;
if(isEmpty())
{
return temp;
}
else
{
t = top;
top = top->next;
temp = t->data;
delete t;
return temp;
}
}
void Stack :: display()
{
Node *p = top;
while(p != NULL)
{
cout<<"\n"<<p->data;
p = p->next;
}
}
So this is a preview of what i am trying to do, but i don't want to create different node and stack class for different data types. How can i achieve that using Templates. I tried it myself but i am getting lots of error and cant seem to understand why.
Thanks.
I suggest making the Node into an inner class of Stack. There's no need for users to be able to see it.
#include<iostream>
#include<utility>
template<class T>
class Stack {
struct Node { // inner class
T data;
Node *next;
};
Node* top = nullptr;
size_t m_size = 0;
public:
Stack() = default;
// rule of five - no copying, only moving allowed
Stack(const Stack&) = delete;
Stack(Stack&& rhs) noexcept :
top(std::exchange(rhs.top, nullptr)), m_size(rhs.m_size)
{}
Stack& operator=(const Stack&) = delete;
Stack& operator=(Stack&& rhs) noexcept {
std::swap(top, rhs.top);
m_size = rhs.m_size;
return *this;
}
~Stack() {
while(top) {
delete std::exchange(top, top->next);
}
}
bool empty() const { return m_size == 0; }
size_t size() const { return m_size; }
void push(const T& data) {
top = new Node{data, top};
++m_size;
}
T pop() {
T rv = std::move(top->data);
delete std::exchange(top, top->next);
--m_size;
return rv;
}
};
Demo
You can implement like bellow:
#include<iostream>
using namespace std;
template <typename Type>
class Node
{
public:
Type data;
Node<Type> *next;
};
template <typename Type>
class Stack
{
public:
Node<Type> *top;
void push(Type data);
Type pop();
};
int main()
{
}
Implementing a stack with a linked list requires simply storing a linked list privately, and constraining it with the stack's interface. The constraining is the key. The template parameter is the type you are storing in your stack.
The simplest* way is to take the time implement a linked list well, so that you only have to worry about constraining it in your stack class and not writing a linked list to behave like a stack in your stack class. The principle at play here is called Separation of Concerns.
Here's a quick example using std::list for simplicity's sake:
template <typename T>
class Stack {
public:
Stack() = default;
Stack(T val) : m_stack(val) {}
void push(T val) { m_stack.push_front(val); }
T& top() { return m_stack.front(); }
void pop() {
if (!m_stack.empty()) m_stack.pop_front();
}
bool empty() const { return m_stack.empty(); }
private:
std::list<T> m_stack{};
};
The if statement might not be necessary in the pop() function if you want the exception to be thrown in your stack.
Here's a main() that tests the stack:
int main() {
Stack<int> s1;
for (int i = 1; i < 11; ++i) s1.push(i);
while (!s1.empty()) {
std::cout << s1.top() << ' ';
s1.pop();
}
std::cout << '\n';
Stack<char> s2('A');
for (char l = 'B'; l != 'K'; ++l) s2.push(l);
while (!s2.empty()) {
std::cout << s2.top() << ' ';
s2.pop();
}
std::cout << '\n';
}
My only includes are <iostream> and <list>. The output:
10 9 8 7 6 5 4 3 2 1
J I H G F E D C B
I am able to avoid a lot of unnecessary work like the Rule of 5 because std::list handles it all for me. So I am fine with compiler-provided copy and move constructors and the destructor.
* This is much easier said than done. I keep a simple linked list around for those specific questions, and it is still ~130 lines of code, and does not have all the functionality necessary to be properly constrained to behave like a stack like I demonstrate with std::list.
If you've written a linked list already, the stack should be very simple as successfully writing a linked list requires demonstrating an extremely wide range of C++ knowledge and programming principles.

Linked list consist of a class throws exception 0xC0000005

So i have a Linked list implementation of my own and it can successfully keep integers and call them when needed with overloaded [] operator but when it comes to storing a class in my linked list, it seems that i can't call the class appropriately (using the same [] operator).
Called functions and members of my Linked List;
#include <iostream>
#include <assert.h>
template<typename T>
struct node {
T data;
node<T>* next;
};
template<typename T>
class Vectem {
private:
node<T>* head;
node<T>* last;
int lenght;
public:
void insert(T value) {
last->next = new node<T>;
last = last->next;
last->data = value;
last->next = NULL;
if (isEmpty()) {
head = last;
}
lenght++;
}
node<T>* search(int indx) {
node<T>* current;
current = head;
int count=0;
while (current != NULL) {
if (count == indx) {
break;
}
current = current->next;
count++;
}
return current;
}
T& operator [](int indx) {
assert(indx >= lenght - 1);
T result;
result = search(indx)->data;
return result;
}
};
And here is the main function and the class that i try to store;
#include <iostream>
#include <fstream>
#include <string>
#include "VectemLibrary.h"
class word {
public:
std::string value;
int count;
word(std::string value, int count): value(value),count(count) {
}
word() {
value = "NOT ASSIGNED";
count = 0;
}
word(const word& w1) {
value = w1.value;
count = w1.count;
}
~word() {
std::cout << "Word Destroyed" << std::endl;
}
};
int main()
{
Vectem<word> wordContainer;
word newWord("hello", 1);
wordContainer.insert(newWord);
std::cout << wordContainer[0].value;
}
Visual studio gave me the expection with this message at the last line where i call the first member of linked list with [];
Exception thrown at 0x7A0CF3BE (ucrtbased.dll) in Top 10 words.exe: 0xC0000005: Access violation reading location 0xCCCCCCCC.
I think that my lack of experience with pointers may have caused the problem but if you see something that i can't, Please enlighten me.
There are other problems with the code you posted as well (e.g. isEmpty() is not declared or defined), but I'll focus on the issue you explicitly mentioned.
In your operator:
T& operator [](int indx) {
assert(indx >= lenght - 1);
// You declare this variable on the stack
T result;
result = search(indx)->data;
// And then you return this variable by reference; this is not okay
return result;
}
As mentioned in my code comments (and by #Johnny Mopp in his comment to your post), you shouldn't (can't) return a reference or pointer to a variable declared within the returning function and constructed on the stack. Anything on the stack will be destroyed once the function call ends, so any returned pointers or references to such variables will be dangling references; using said pointers or references will result in undefined behavior.
So you don't want to return a reference to a stack-allocated variable like result; you want to return a reference to the data within the node itself (which is allocated on the heap by insert()), as it will still be a valid reference after the function returns:
return search(indx)->data;
There are several problems with your code, but the most important is that you are not initializing the head, last, or lenght members of Vectem at all. An Access Violation error at address 0xCCCCCCCC is a good indication that uninitialized memory is being accessed, as some compilers/setups fill uninitialized memory with 0xCC bytes, thus head and last are initially 0xCCCCCCCC in your case.
You need to add appropriate constructors to Vectem (as well as a destructor, a copy constructor, and a copy assignment operator, per the Rule of 3), eg:
template<typename T>
class Vectem {
private:
node<T>* head;
node<T>* last;
int lenght;
public:
Vectem() : head(NULL), last(NULL), lenght(0) {}
Vectem(const Vectem &src) : head(NULL), last(NULL), lenght(0)
{
// copy src's data to *this as needed ...
}
~Vectem()
{
// cleanup *this as needed ...
}
Vectem& operator=(const Vectem &rhs)
{
if (&rhs != this) {
// clear *this, and copy rhs's data to *this, as needed ...
}
return *this;
}
...
};
Or, in C++11 and later, you can initialize the members directly in their declarations (also, be sure to add a move constructor and a move assignment operator, per the Rule of 5), eg:
template<typename T>
class Vectem {
private:
node<T>* head = nullptr;
node<T>* last = nullptr;
int lenght = 0;
public:
Vectem() = default;
Vectem(const Vectem &src)
{
// copy src's data to *this as needed ...
}
Vectem(Vectem &&src) : head(src.head), last(src.last), lenght(src.lenght)
{
src.head = nullptr;
src.last = nullptr;
src.lenght = 0;
}
~Vectem()
{
// cleanup *this as needed ...
}
Vectem& operator=(const Vectem &rhs)
{
if (&rhs != this) {
// clear *this, and copy rhs's data to *this, as needed ...
}
return *this;
}
Vectem& operator=(Vectem &&rhs)
{
// clear *this as needed...
head = rhs.head; rhs.head = nullptr;
last = rhs.last; rhs.last = nullptr;
lenght = rhs.lenght; rhs.lenght = 0;
return *this;
}
...
};
That being said, insert() is also buggy, as it is dereferencing last before checking that last is actually pointing at a valid node. Try something more like this instead:
void insert(T value) {
node<T> *n = new node<T>{value, NULL};
if (!head) head = n;
if (last) last->next = n;
last = n;
++lenght;
}
Alternatively:
void insert(T value) {
node<T> **p = (last) ? &(last->next) : &head;
*p = new node<T>{value, NULL};
last = *p;
++lenght;
}

"Function" is not a type C++

I want to make a template class and pass it a compare function. I found a great answer on this link
Unfortunately when I made a template class called "WaitingQueue" and passed the compare function in the constructor of the class(in class foo), the code does not compile and throws error: "'compare' is not a type".
I cannot understand the error here. The code in the link above runs without error. Can anyone please tell me what I have done wrong here? Thanks in advance
#include <stdint.h>
#include <stddef.h>
#include <string.h>
enum { OK, ERROR };
template <class T>
class WaitingQueue
{
struct QueueElement
{
public:
T data;
QueueElement *next;
QueueElement(T *pdata): next(0)
{
memcpy(&data, pdata, sizeof(T));
}
};
QueueElement *head, tail;
public:
bool (*comparefunc)(uint16_t, T*);
WaitingQueue (bool (*compareFunction)(uint16_t, T*)) :comparefunc(compareFunction), head(0), tail(0) { }
int search(int16_t id, T *ret_data)
{
QueueElement *temp = head;
QueueElement *prev = 0;
if (temp != NULL)
{
if (comparefunc(id, &temp->data) == true)
{
if (prev)
{
prev->next = temp->next;
}
else
{
head = head->next;
}
memcpy(ret_data, &temp->data, sizeof(temp->data));
delete temp;
return OK;
}
prev = temp;
temp = temp->next;
}
return ERROR;
}
};
typedef struct _cmd
{
uint8_t flags;
uint16_t id;
} cmd;
bool compare(uint16_t id, cmd *cmd)
{
return (cmd->id == id);
}
class foo
{
WaitingQueue<cmd> queue(compare);
};
This is the usual vexing parse. WorkingQueue<cmd> queue(compare); is understood by the compiler as the declaration of a method named queue returning a WorkingQueue<cmd> and taking an object of the nonexistant type compare. You can make it understand that you mean to declare a field initialized with the compare function by using braces initialization:
WaitingQueue<cmd> queue{compare};

code line is killing my program

i made this linked list class in c++ and it works fine except after i run it the program goes unresponsive. i have located the line that's causing the problem but i have no idea why. Even when i type it differently it still does the same thing.
Here's my list class:
#include <string>
template<class T>
class List : public Object{
private:
Node<T>* first;
Node<T>* last;
int length;
public:
List() : Object(new std::string("List")) {
first = NULL;
last = NULL;
length = 0;
}
~List() {
delete first;
delete last;
}
void Add(T value) {
if(first==NULL)
first = new Node<T>(NULL, value);
else if(last==NULL)
---->last = new Node<T>(first, value);<-----
else
last = new Node<T>(last, value);
length++;
}
T Remove(T value) {
Node<T>* temp = first;
while(temp!=NULL) {
if(temp->GetValue()==value) {
temp->GetPrev()->SetNext(temp->GetNext());
temp->GetNext()->SetPrev(temp->GetPrev());
delete temp;
length--;
return value;
}
temp = temp->GetNext();
}
return 0;
}
T Get(int index) {
Node<T>* temp = first;
int i = 0;
while(temp!=NULL) {
if(i==index)
return temp->GetValue();
i++;
temp = temp->GetNext();
}
return 0;
}
};
when i remove the marked line above the program go unresponsive. This is my Node constructor:
#include <string>
template<class T>
class Node : public Object{
private:
Node* next;
Node* prev;
T value;
public:
Node(Node* prev, T value) : Object(new std::string("Node")){
if(prev!=NULL) {
prev->next = this;
this->prev = next;
}
next = NULL;
this->value = value;
}
~Node() {
delete next;
}
T GetValue() {
return value;
}
Node* GetNext() {
return next;
}
Node* GetPrev() {
return next;
}
};
my object class:
#include <string>
class Object {
private:
std::string* type;
public:
Object() {
type = new std::string("Object");
}
Object(std::string* type) {
this->type = type;
}
~Object() {
delete type;
}
std::string* GetType() {
return type;
}
};
my Test.cpp
#include <iostream>
#include <string>
#include "Object.h"
#include "Node.h"
#include "List.h"
using namespace std;
int main () {
List<int> l;
l.Add(5);
l.Add(93);
l.Add(17);
l.Add(7789);
l.Add(60);
cout << "node 4 is:" << l.Get(3) << endl;
return 0;
}
error image http://i50.tinypic.com/2mw5phi.png
thanks for reading and please help as soon as you can, comment if you need me to supply more info.
Edit: There are many problems with your program, but what might be causing your crash: Your Add-function does not work correctly. It should be something like this:
if(first==NULL) {
first = new Node<T>(NULL, value);
last = first;
} else {
last = new Node<T>(last, value);
}
length++;
Otherwise, it will not correctly insert the second element. Why? With your original code, after the first add, your last is still NULL because of the else. So on the second add, you set last to new Node<T>(NULL, value). Therefore, it will not assign the first element's next pointer. And your list will be inconsistent.
Apart from that, there are double-frees, unnecessary heap-allocation of the string field in your Object class, ownership issues etc. To give you just one more example: Your List destructor will cause a heap corruption due to a double free. Calling delete first will delete all nodes due to the delete next in Node's destructor, as long as the list is consistent. Then you call delete last, but that object was already freed. This will corrupt your program's memory management and can also cause a crash at program exit.
Does this function seem correct to you??
It says GetPrev, but its actually getting next.
Node* GetPrev() {
return next;
}
I found that if I comment out this line in the Node constructor the code compiles:
if (next != NULL) {
// next->next = this;
prev = next;
}
Edit 1:
I also realized that you were doing this in your Node class:
private:
Node* next;
Node* prev;
T value;
Since these objects are declared in the Node class, they are at this time incomplete types. I managed to replicate that problem down to a simple one like this:
template <class T>
struct S {
S* s = new S();
~S() { delete s; }
};
int main() {
S<int> s; // Segmentation fault (core dumped) ./test > .stdout
}
This causes a crash because S is an incomplete type within itself.
I'm getting the same segementation fault as I got in your code. I'm pretty sure it's because the pointers in the Node class are built upon incomplete types; and accessing the data from them is looking into memory that isn't yours, hence the crash.

How do we include a struct in a c++ implementation file?

So I am trying to create my own implementation file which contains instructions for a Queue. I decided to use a linked list to implement the Queue class, meaning that I need to use my own Node struct. Unfortunately, I am stuck and don't know how to properly include this within the file.
This is what I have so far:
#include <string>
#ifndef NODE
template <class DataType>
struct Node
{
DataType data;
Node *next;
};
#endif
template <class DataType>
class Queue
{
public:
Queue();
bool isEmpty() const;
void push(const DataType& parameter);
bool peek(DataType& parameter) const;
bool pop(DataType& parameter);
void makeEmpty();
private:
Node<DataType>* front;
Node<DataType>* end;
};
template <class DataType>
Queue<DataType>::Queue()
: front(0), end(0)
{
}
template <class DataType>
bool Queue<DataType>::isEmpty() const {return 0 == front;}
template <class DataType>
void Queue<DataType>::push(const DataType& parameter)
{
Node<DataType>* node = new Node<DataType>;
node->data = parameter;
node->next = 0;
if (end) end->next = node;
else front = node;
end = node;
}
template <class DataType>
bool Queue<DataType>::peek(DataType& parameter) const
{
if (0 == front) return false; // failed
parameter = front->data;
return true; // success
}
template <class DataType>
bool Queue<DataType>::pop(DataType& parameter)
{
if (0 == front) return false; // failed
parameter = front->data;
Node<DataType>* p = front->next;
delete front;
front = p;
if (front == 0) end = 0;
return true; // success
}
template <class DataType>
void Queue<DataType>::makeEmpty()
{
end = 0;
Node<DataType>* p;
while (front)
{
p = front->next;
delete front;
front = p;
}
}
I'm not sure if I am enclosing the struct by the #ifndef correctly (i'm not even sure if this is the route I should be taking :/), should I be doing something similar to this or should I be doing something else with the code for the struct?
You can just drop the #ifdef/#endif entirely
This is a class template and it may occur many times in several tranlation units, as long as all the occurrences are identical (One Definition Rule)
Alternative
Since Node<> is purely a private concern, I'd make it a nested struct.
Here's a little demo making this more 'modern C++' style.
Edit Thanks to #R.MartinhoFernandes for showing a few more improvements and for reviewing this.
#include <memory>
template <typename T>
struct Queue {
Queue() : front(), end(/*nullptr*/) {}
// Copy-And-Swap idiom
// see http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Copy-and-swap
// or http://stackoverflow.com/questions/3279543/what-is-the-copy-and-swap-idiom
void swap(Queue& q) noexcept {
using std::swap;
swap(q.front, front);
swap(q.end, end);
}
Queue(Queue const& q) : front(), end() {
for(auto it=q.front.get(); it; it=it->next.get())
push(it->data);
}
Queue& operator=(Queue q) {
std::swap(*this, q);
return *this;
}
// end Copy-and-swap
// prevent stack overflows in ~Node if the list grows large (say >1k elements)
~Queue() { clear(); }
bool isEmpty() const {
return !front;
}
void push(T const& data) {
Ptr node(new Node(data));
if (end)
end->next = std::move(node);
else
front = std::move(node);
end = node.get();
}
bool peek(T& data) const {
if(front) data = front->data;
return front.get();
}
bool pop(T& data) {
if(!front) return false;
data = front->data;
front = std::move(front->next);
if(!front) end = nullptr;
return true;
}
void clear() {
end = nullptr;
while(front) front = std::move(front->next);
}
private:
struct Node;
typedef std::unique_ptr<struct Node> Ptr;
struct Node {
Node(T data) : data(std::move(data)), next() {}
T data;
Ptr next;
};
Ptr front;
Node* end;
};
#include <iostream>
int main(int argc, const char *argv[]) {
Queue<int> test;
test.push(1);
test.push(2);
test.push(3);
test.push(5);
test.clear();
test.push(32028);
test.push(10842);
test.push(1839);
test.push(23493);
test.push(9857);
int x;
test.peek(x);
while(test.pop(x)) {
std::cout << x << '\n';
}
}
Note: Perhaps the code in push has been golfed a bit too far, but hey, it shows you how modern C++ requires much less handholding (even without std::make_unique).
Note how I think Clang correctly handles the following version (i.e. with implicit std::move):
void push(const DataType& parameter) {
end = ((end? end->next : front) = Ptr(new Node(parameter))).get();
}
I'm not quite sure why gcc rejects it.