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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With