What can be simplified, altered, or implemented differently? 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_