I have recently learned concepts like Lvalue & Rvalue references, Universal References, Perfect Forwarding, std::move(), std::forward() etc.
I tried to implement templatized version of Stack (Using Linked List) and was wondering how can I use the above mentioned concepts in my program correctly & efficiently.
I wish to take advantage of move semantics !
Note : I did try to do so myself but it didn't seem to work out correctly! I commented //possible use in my code where I think I can and tried to use the above concepts myself !
I won't be mentioning my version of messy code because I felt it was too wrong. Instead I would appreciate if someone can guide or help me in my original code. Any feedback is appreciated !
#include <iostream>
using namespace std;
template <class U>
struct Stack_Node
{
U data;
Stack_Node *next;
Stack_Node(U val) // possible use
: data(val), next(nullptr)
{
cout << "\nNew Stack_Node Created!\n";
}
};
template <class T>
class Stack
{
private:
Stack_Node<T> *head;
public:
Stack() : head(nullptr) { cout << "\nNew Stack Created!\n"; }
~Stack()
{
while (head != nullptr)
{
Stack_Node<T> *ptr = head;
head = head->next;
delete ptr;
}
}
bool empty() { return head == nullptr; }
size_t size()
{
size_t count = 0;
Stack_Node<T> *ptr = head;
while (ptr != nullptr)
{
++count;
ptr = ptr->next;
}
return count;
}
T &top() { return head->data; }
void push(T val) // possible use
{
Stack_Node<T> *ptr = new Stack_Node<T>(val); // possible use
ptr->next = head;
head = ptr;
}
void pop()
{
if (empty())
return;
Stack_Node<T> *ptr = head;
head = head->next;
delete ptr;
}
};
template <class T>
void print(Stack<T> &s)
{
Stack_Node<T> *ptr = s.head;
while (ptr != nullptr)
{
cout << ptr->data << " ";
ptr = ptr->next;
}
}
int main()
{
}
Edit : 1. I could use Rvalue reference like this :-
void push(T &&val) // HERE !!!
{
Stack_Node<T> *ptr = new Stack_Node<T>(val); // possible use
ptr->next = head;
head = ptr;
}
But then I would have to use std::move()
when calling the push()
function if I wish to pass Lvalues but instead I want my Stack
class to remain a blackbox so that the user don't have to be concerned about using the move semantics...and my class should still work in the most efficient way possible by taking some advantage of move semantics .