I would like to hear the advice. What can be simplified, altered, or implemented differently. I will be very grateful.I would like to know if there's a way to further improve this code.
#ifndef _DEQUE_H_
#define _DEQUE_H_
//-------------------------------------------------------------------------
template <typename Type>
class Deque
{
private:
struct Node
{
Type element = {};
Node* prev = nullptr;
Node* next = nullptr;
};
size_t count;
Node* head;
Node* tail;
public:
//Member functions
Deque();
Deque(const Deque & deq);
Deque(Deque && deq);
Deque & operator = (const Deque & deq);
Deque & operator = (Deque && deq);
~Deque();
//Element access
//const Type & at(Deque pos) const; Not implemented
//template <typename Type>
//const Type & operator[](size_type pos) const; Not implemented
const Type & front() const;
const Type & back() const;
//Iterators
//TODO: Implement in the near future
//Capacity
bool empty() const;
size_t size() const;
//size_t max_size() const noexcept; Not implemented
//Modifiers
void push_front(const Type & tp);
void push_back(const Type & tp);
//void emplace_front(); Not implemented
//void emplace_back(); Not implemented
void pop_front();
void pop_back();
void clear() noexcept;
void swap(Deque & deq) noexcept;
};
//--------------------------------------------------------------------------
template <typename Type>
Deque<Type>::Deque() : count(0), head(nullptr), tail(nullptr)
{
//Body of the constructor class
}
//--------------------------------------------------------------------------
template <typename Type>
Deque<Type>::Deque(const Deque & deq) : count(deq.count), head(nullptr), tail(nullptr)
{
for (const Node* n_ptr = deq.head; n_ptr != nullptr; n_ptr = n_ptr->next)
{
Node* n_ptr_new = new Node;
n_ptr_new->element = n_ptr->element;
if (head == nullptr && tail == nullptr)
{
head = n_ptr_new;
tail = head;
}
else
{
tail->next = n_ptr_new;
n_ptr_new->prev = tail;
n_ptr_new->next = nullptr;
tail = n_ptr_new;
}
}
}
//--------------------------------------------------------------------------
template <typename Type>
Deque<Type>::Deque(Deque && deq) : count(deq.count), head(deq.head), tail(deq.tail)
{
deq.count = 0;
deq.head = nullptr;
deq.tail = nullptr;
}
//--------------------------------------------------------------------------
template <typename Type>
Deque<Type> & Deque<Type>::operator = (const Deque & deq)
{
if (this == &deq)
{
return *this;
}
Deque tmp(deq);
std::swap(count, tmp.count);
std::swap(head, tmp.head);
std::swap(tail, tmp.tail);
return *this;
}
//--------------------------------------------------------------------------
template <typename Type>
Deque<Type> & Deque<Type>::operator = (Deque && deq)
{
if (this == &deq)
{
return *this;
}
std::swap(count, deq.count);
std::swap(head, deq.head);
std::swap(tail, deq.tail);
return *this;
}
//--------------------------------------------------------------------------
template <typename Type>
Deque<Type>::~Deque()
{
while (head)
{
Node* n_ptr_del = head;
head = head->next;
delete n_ptr_del;
}
count = 0;
}
//--------------------------------------------------------------------------
template <typename Type>
void Deque<Type>::push_front(const Type & tp)
{
Node* n_ptr_new = new Node;
n_ptr_new->element = tp;
if (head == nullptr && tail == nullptr)
{
head = n_ptr_new;
tail = head;
}
else
{
n_ptr_new->next = head;
n_ptr_new->prev = nullptr;
head->prev = n_ptr_new;
head = n_ptr_new;
}
++count;
}
//--------------------------------------------------------------------------
template <typename Type>
void Deque<Type>::push_back(const Type & tp)
{
Node* n_ptr_new = new Node;
n_ptr_new->element = tp;
if (head == nullptr && tail == nullptr)
{
head = n_ptr_new;
tail = head;
}
else
{
tail->next = n_ptr_new;
n_ptr_new->prev = tail;
n_ptr_new->next = nullptr;
tail = n_ptr_new;
}
++count;
}
//--------------------------------------------------------------------------
template <typename Type>
void Deque<Type>::pop_front()
{
if (empty())
{
throw std::out_of_range("Can't pop from empty list");
}
if (head == tail)
{
delete head;
--count;
head = nullptr;
tail = nullptr;
return;
}
Node* n_ptr_del = head;
head = head->next;
head->prev = nullptr;
--count;
delete n_ptr_del;
}
//--------------------------------------------------------------------------
template <typename Type>
void Deque<Type>::pop_back()
{
if (empty())
{
throw std::out_of_range("Can't pop from empty list");
}
if (head == tail)
{
delete head;
--count;
head = nullptr;
tail = nullptr;
return;
}
Node* n_ptr_del = tail;
tail = tail->prev;
tail->next = nullptr;
--count;
delete n_ptr_del;
}
//--------------------------------------------------------------------------
template <typename Type>
bool Deque<Type>::empty() const
{
return head == nullptr;
}
//--------------------------------------------------------------------------
template <typename Type>
const Type & Deque<Type>::front() const
{
if (empty())
{
throw std::out_of_range("List<Type>::top: empty stack");
}
return head->element;
}
//-------------------------------------------------------------------------------------------------
template <typename Type>
const Type & Deque<Type>::back() const
{
if (empty())
{
throw std::out_of_range("List<Type>::top: empty stack");
}
return tail->element;
}
//--------------------------------------------------------------------------
template <typename Type>
size_t Deque<Type>::size() const
{
return count;
}
//--------------------------------------------------------------------------
template <typename Type>
void Deque<Type>::clear() noexcept
{
while (count)
{
pop_back();
}
}
//--------------------------------------------------------------------------
template <typename Type>
void Deque<Type>::swap(Deque & deq) noexcept
{
Deque temp(deq);
deq = std::move(*this);
*this = std::move(temp);
}
//--------------------------------------------------------------------------
#endif // _DEQUE_H_