#pragma once #include #include namespace List { template struct Node { T value; std::unique_ptr> next; Node(T const & _value) : value(_value), next(nullptr) {} }; template class List { private: std::unique_ptr> root; Node * tailPtr; std::size_t size; public: void Append(T const & value) { if(size == 0) { root = std::make_unique>(value); tailPtr = root.get(); ++size; return; } tailPtr->next = std::make_unique>(value); tailPtr = tailPtr->next.get(); ++size; } void Prepend(T const & value) { if(size == 0) { root = std::make_unique>(value); tailPtr = root.get(); ++size; return; } auto newRoot = std::make_unique>(value); newRoot->next.swap(root); root.swap(newRoot); ++size; } void Insert(T const & value, std::size_t const index) { if(index >= size) { throw std::out_of_range("Index is greater or equal to size."); } if(index == 0u) { Prepend(value); return; } ++size; Node * prevPtr = root.get(); Node * curPtr = root->next.get(); std::size_t currentIndex = 1u; while(currentIndex < index) { prevPtr = curPtr; curPtr = curPtr->next.get(); ++currentIndex; } auto newNode = std::make_unique>(value); newNode->next.swap(prevPtr->next); prevPtr->next.swap(newNode); } void Delete(std::size_t const index) { if(index >= size) { throw std::out_of_range("Index is greater or equal to size."); } --size; if(index == 0u) { if(size == 0u) { root.release(); tailPtr = nullptr; } else { root = std::move(root->next); } return; } // Is index last element? Note that we subtracted 1 from size above if(index == size) { Node * curPtr = root.get(); while(curPtr->next.get() != tailPtr) { curPtr = curPtr->next.get(); } tailPtr = curPtr; tailPtr->next.release(); return; } Node * prevPtr = root.get(); Node * curPtr = prevPtr->next.get(); std::size_t currentIndex = 1u; while(currentIndex < index) { ++currentIndex; prevPtr = curPtr; curPtr = curPtr->next.get(); } prevPtr->next = std::move(curPtr->next); } T & Front() { if(size == 0u) { throw std::out_of_range("List is empty."); } return root->value; } T & Back() { if(size == 0u) { throw std::out_of_range("List is empty."); } return tailPtr->value; } T & operator[](std::size_t const index) { if(index >= size) { throw std::out_of_range("Index is greater or equal to size."); } Node * currentNode = root.get(); std::size_t currentIndex = 0u; while(currentIndex < index) { currentNode = currentNode->next.get(); ++currentIndex; } return currentNode->value; } std::size_t GetSize() const { return size; } List() : root(nullptr), tailPtr(nullptr), size(0) {} }; }