Advertisement
Petrovi4

SingleLinkedList::BasicIterator

Jul 14th, 2022 (edited)
883
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 13.38 KB | None | 0 0
  1. #include <cassert>
  2. #include <cstddef>
  3. #include <string>
  4. #include <utility>
  5. #include <iterator>
  6. #include <iostream>
  7. #include <algorithm>
  8.  
  9. template <typename Type>
  10. class SingleLinkedList {
  11.    
  12.     struct Node {
  13.         Node() = default;
  14.  
  15.         Node(const Type& val, Node* next)
  16.             : value(val)
  17.             , next_node(next) {
  18.         }
  19.         Type value;
  20.         Node* next_node = nullptr;
  21.     };
  22.  
  23.     template <typename ValueType>
  24.     class BasicIterator {        
  25.         friend class SingleLinkedList;
  26.        
  27.         explicit BasicIterator(Node* node) :
  28.             node_(node)
  29.         {
  30.         }
  31.  
  32.     public:
  33.        
  34.         using iterator_category = std::forward_iterator_tag;
  35.         using value_type = Type;        
  36.         using difference_type = std::ptrdiff_t;      
  37.         using pointer = ValueType*;
  38.         using reference = ValueType&;
  39.  
  40.         BasicIterator() = default;
  41.  
  42.         BasicIterator(const BasicIterator<Type>& other) noexcept {
  43.             node_ = other.node_;
  44.         }
  45.  
  46.         BasicIterator& operator=(const BasicIterator& rhs) = default;
  47.  
  48.         [[nodiscard]] bool operator==(const BasicIterator<const Type>& rhs) const noexcept {
  49.             return node_ == rhs.node_;
  50.         }
  51.  
  52.         [[nodiscard]] bool operator!=(const BasicIterator<const Type>& rhs) const noexcept {
  53.             return !(node_ == rhs.node_);
  54.         }
  55.        
  56.         [[nodiscard]] bool operator==(const BasicIterator<Type>& rhs) const noexcept {
  57.             return node_ == rhs.node_;
  58.         }
  59.  
  60.         [[nodiscard]] bool operator!=(const BasicIterator<Type>& rhs) const noexcept {
  61.             return !(node_ == rhs.node_);
  62.         }
  63.  
  64.         BasicIterator& operator++() noexcept {
  65.             if (node_ != nullptr) {
  66.                 node_ = node_->next_node;
  67.             }
  68.             return *this;
  69.         }
  70.  
  71.         BasicIterator operator++(int) noexcept {
  72.             auto old_value(*this);
  73.             ++(*this);
  74.             return old_value;
  75.         }
  76.  
  77.         [[nodiscard]] reference operator*() const noexcept {
  78.             return node_->value;
  79.         }
  80.  
  81.         [[nodiscard]] pointer operator->() const noexcept {
  82.             return &node_->value;
  83.         }
  84.  
  85.     private:
  86.         Node* node_ = nullptr;
  87.     };
  88.  
  89. public:
  90.  
  91.     SingleLinkedList() :
  92.         head_(Node()), size_(0)
  93.     {
  94.     }
  95.  
  96.     SingleLinkedList(std::initializer_list<Type> values) {
  97.         Assign(values.begin(), values.end());
  98.     }
  99.  
  100.     SingleLinkedList(const SingleLinkedList& other) {
  101.         Assign(other.begin(), other.end());
  102.     }
  103.  
  104.  
  105.     SingleLinkedList& operator=(const SingleLinkedList& rhs) {
  106.         if (this != &rhs) {
  107.             auto rhs_copy(rhs);
  108.             swap(rhs_copy);
  109.         }
  110.         return *this;
  111.     }
  112.    
  113.     void swap(SingleLinkedList& other) noexcept {
  114.         std::swap(head_.next_node, other.head_.next_node);
  115.         std::swap(size_ , other.size_);
  116.     }
  117.  
  118.     using value_type = Type;
  119.     using reference = value_type&;
  120.     using const_reference = const value_type&;
  121.     using Iterator = BasicIterator<Type>;
  122.     using ConstIterator = BasicIterator<const Type>;
  123.  
  124.     [[nodiscard]] Iterator begin() noexcept {
  125.         if (IsEmpty()) {
  126.             return Iterator(nullptr);
  127.         }
  128.  
  129.         return Iterator(head_.next_node);
  130.     }
  131.  
  132.     [[nodiscard]] Iterator end() noexcept {
  133.         return Iterator(nullptr);
  134.     }
  135.  
  136.     [[nodiscard]] ConstIterator begin() const noexcept {
  137.         if (IsEmpty()) {
  138.             return Iterator(nullptr);
  139.         }
  140.         return ConstIterator(head_.next_node);
  141.     }
  142.  
  143.     [[nodiscard]] ConstIterator end() const noexcept {
  144.         return ConstIterator(nullptr);
  145.     }
  146.  
  147.     [[nodiscard]] ConstIterator cbegin() const noexcept {
  148.         if (IsEmpty()) {
  149.             return Iterator(nullptr);
  150.         }
  151.         return ConstIterator(head_.next_node);
  152.     }
  153.  
  154.     [[nodiscard]] ConstIterator cend() const noexcept {
  155.         return ConstIterator(nullptr);
  156.     }
  157.    
  158.     [[nodiscard]] Iterator before_begin() noexcept {        
  159.         return Iterator(head_ptr_);
  160.     }
  161.  
  162.     [[nodiscard]] ConstIterator cbefore_begin() const noexcept {        
  163.         return ConstIterator(head_ptr_);;
  164.     }
  165.  
  166.     [[nodiscard]] ConstIterator before_begin() const noexcept {        
  167.         return ConstIterator(head_ptr_);
  168.     }
  169.        
  170.     [[nodiscard]] size_t GetSize() const noexcept {
  171.         return size_;
  172.     }
  173.  
  174.     [[nodiscard]] bool IsEmpty() const noexcept {
  175.         bool result;
  176.         size_ == 0 ? result = true : result = false;
  177.         return result;
  178.     }
  179.    
  180.     void PushFront(const Type& value) {
  181.         head_.next_node = new Node(value, head_.next_node);
  182.         ++size_;
  183.     }
  184.    
  185.     void Clear() noexcept {
  186.         if (IsEmpty()) {
  187.             return;
  188.         }
  189.         while (head_.next_node != nullptr) {
  190.             Node* temp = head_.next_node->next_node;
  191.             delete head_.next_node;
  192.             head_.next_node = temp;
  193.         }
  194.         size_ = 0;
  195.     }
  196.    
  197.     Iterator InsertAfter(ConstIterator pos, const Type& value) {
  198.         auto &prev_node = pos.node_;
  199.         prev_node->next_node = new Node(value, prev_node->next_node);
  200.         ++size_;
  201.         return Iterator (prev_node->next_node);  
  202.     }
  203.  
  204.     void PopFront() noexcept {
  205.         if (IsEmpty()) {
  206.             return;
  207.         }
  208.         Node* temp = head_.next_node->next_node;
  209.         delete head_.next_node;
  210.         head_.next_node = temp;
  211.         --size_;
  212.     }
  213.  
  214.     Iterator EraseAfter(ConstIterator pos) noexcept {
  215.         if (IsEmpty()) {
  216.             return Iterator(nullptr);
  217.         }
  218.         Node *const node_to_erase = pos.node_->next_node;
  219.         --size_;
  220.        
  221.         Node *const node_after_erased= node_to_erase->next_node;
  222.         delete node_to_erase;
  223.         pos.node_->next_node = node_after_erased;
  224.  
  225.         return Iterator (node_after_erased);
  226.     }
  227.    
  228.     ~SingleLinkedList() {
  229.         Clear();
  230.     }
  231.  
  232. private:
  233.     Node head_;
  234.     size_t size_=0;
  235.     Node* head_ptr_  = &head_;
  236.     template <typename It>
  237.     void Assign(It from, It to) {
  238.         SingleLinkedList<Type> tmp;
  239.         Node** node_ptr = &tmp.head_.next_node;
  240.        
  241.         while (from != to) {
  242.             *node_ptr = new Node(*from, nullptr);
  243.             ++tmp.size_;
  244.             node_ptr = &((*node_ptr)->next_node);
  245.             ++from;
  246.         }
  247.        
  248.         swap(tmp);
  249.     }
  250. };
  251.  
  252. template <typename Type>
  253. void swap(SingleLinkedList<Type>& lhs, SingleLinkedList<Type>& rhs) noexcept {
  254.     lhs.swap(rhs);
  255. }
  256.  
  257. template <typename Type>
  258. bool operator==(const SingleLinkedList<Type>& lhs, const SingleLinkedList<Type>& rhs) {
  259.     return std::equal(lhs.begin(), lhs.end(), rhs.begin());
  260. }
  261.  
  262. template <typename Type>
  263. bool operator!=(const SingleLinkedList<Type>& lhs, const SingleLinkedList<Type>& rhs) {
  264.     return !(lhs == rhs);
  265. }
  266.  
  267. template <typename Type>
  268. bool operator<(const SingleLinkedList<Type>& lhs, const SingleLinkedList<Type>& rhs) {
  269.     return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
  270. }
  271.  
  272. template <typename Type>
  273. bool operator<=(const SingleLinkedList<Type>& lhs, const SingleLinkedList<Type>& rhs) {
  274.     return (lhs == rhs) || (lhs < rhs);
  275. }
  276.  
  277. template <typename Type>
  278. bool operator>(const SingleLinkedList<Type>& lhs, const SingleLinkedList<Type>& rhs) {
  279.     return rhs < lhs;
  280. }
  281.  
  282. template <typename Type>
  283. bool operator>=(const SingleLinkedList<Type>& lhs, const SingleLinkedList<Type>& rhs) {
  284.     return (lhs == rhs) || (rhs < lhs);
  285. }
  286.  
  287. void Test4() {
  288.     struct DeletionSpy {
  289.         ~DeletionSpy() {
  290.             if (deletion_counter_ptr) {
  291.                 ++(*deletion_counter_ptr);
  292.             }
  293.         }
  294.         int* deletion_counter_ptr = nullptr;
  295.     };
  296.  
  297.     // Проверка PopFront
  298.     {
  299.         SingleLinkedList<int> numbers{3, 14, 15, 92, 6};
  300.         numbers.PopFront();
  301.         assert((numbers == SingleLinkedList<int>{14, 15, 92, 6}));
  302.  
  303.         SingleLinkedList<DeletionSpy> list;
  304.         list.PushFront(DeletionSpy{});
  305.         int deletion_counter = 0;
  306.         list.begin()->deletion_counter_ptr = &deletion_counter;
  307.         assert(deletion_counter == 0);
  308.         list.PopFront();
  309.         assert(deletion_counter == 1);
  310.     }
  311.  
  312.     // Доступ к позиции, предшествующей begin
  313.     {
  314.         SingleLinkedList<int> empty_list;
  315.         const auto& const_empty_list = empty_list;
  316.         assert(empty_list.before_begin() == empty_list.cbefore_begin());
  317.         assert(++empty_list.before_begin() == empty_list.begin());
  318.         assert(++empty_list.cbefore_begin() == const_empty_list.begin());
  319.  
  320.         SingleLinkedList<int> numbers{1, 2, 3, 4};
  321.         const auto& const_numbers = numbers;
  322.         assert(numbers.before_begin() == numbers.cbefore_begin());
  323.         assert(++numbers.before_begin() == numbers.begin());
  324.         assert(++numbers.cbefore_begin() == const_numbers.begin());
  325.     }
  326.  
  327.     // Вставка элемента после указанной позиции
  328.     {  // Вставка в пустой список
  329.         {
  330.             SingleLinkedList<int> lst;
  331.             const auto inserted_item_pos = lst.InsertAfter(lst.before_begin(), 123);
  332.             assert((lst == SingleLinkedList<int>{123}));
  333.             assert(inserted_item_pos == lst.begin());
  334.             assert(*inserted_item_pos == 123);
  335.         }
  336.  
  337.         // Вставка в непустой список
  338.         {
  339.             SingleLinkedList<int> lst{1, 2, 3};
  340.             auto inserted_item_pos = lst.InsertAfter(lst.before_begin(), 123);
  341.  
  342.             assert(inserted_item_pos == lst.begin());
  343.             assert(inserted_item_pos != lst.end());
  344.             assert(*inserted_item_pos == 123);
  345.             assert((lst == SingleLinkedList<int>{123, 1, 2, 3}));
  346.  
  347.             inserted_item_pos = lst.InsertAfter(lst.begin(), 555);
  348.             assert(++SingleLinkedList<int>::Iterator(lst.begin()) == inserted_item_pos);
  349.             assert(*inserted_item_pos == 555);
  350.             assert((lst == SingleLinkedList<int>{123, 555, 1, 2, 3}));
  351.         };
  352.     }
  353.  
  354.     // Вспомогательный класс, бросающий исключение после создания N-копии
  355.     struct ThrowOnCopy {
  356.         ThrowOnCopy() = default;
  357.         explicit ThrowOnCopy(int& copy_counter) noexcept
  358.             : countdown_ptr(&copy_counter) {
  359.         }
  360.         ThrowOnCopy(const ThrowOnCopy& other)
  361.             : countdown_ptr(other.countdown_ptr)  //
  362.         {
  363.             if (countdown_ptr) {
  364.                 if (*countdown_ptr == 0) {
  365.                     throw std::bad_alloc();
  366.                 } else {
  367.                     --(*countdown_ptr);
  368.                 }
  369.             }
  370.         }
  371.         // Присваивание элементов этого типа не требуется
  372.         ThrowOnCopy& operator=(const ThrowOnCopy& rhs) = delete;
  373.         // Адрес счётчика обратного отсчёта. Если не равен nullptr, то уменьшается при каждом копировании.
  374.         // Как только обнулится, конструктор копирования выбросит исключение
  375.         int* countdown_ptr = nullptr;
  376.     };
  377.  
  378.     // Проверка обеспечения строгой гарантии безопасности исключений
  379.     {
  380.         bool exception_was_thrown = false;
  381.         for (int max_copy_counter = 10; max_copy_counter >= 0; --max_copy_counter) {
  382.             SingleLinkedList<ThrowOnCopy> list{ThrowOnCopy{}, ThrowOnCopy{}, ThrowOnCopy{}};
  383.             try {
  384.                 int copy_counter = max_copy_counter;
  385.                 list.InsertAfter(list.cbegin(), ThrowOnCopy(copy_counter));
  386.                 assert(list.GetSize() == 4u);
  387.             } catch (const std::bad_alloc&) {
  388.                 exception_was_thrown = true;
  389.                 assert(list.GetSize() == 3u);
  390.                 break;
  391.             }
  392.         }
  393.         assert(exception_was_thrown);
  394.     }
  395.  
  396.     // Удаление элементов после указанной позиции
  397.     {
  398.         {
  399.             SingleLinkedList<int> lst{1, 2, 3, 4};
  400.             const auto& const_lst = lst;
  401.             const auto item_after_erased = lst.EraseAfter(const_lst.cbefore_begin());
  402.             assert((lst == SingleLinkedList<int>{2, 3, 4}));
  403.             assert(item_after_erased == lst.begin());
  404.         }
  405.         {
  406.             SingleLinkedList<int> lst{1, 2, 3, 4};
  407.             const auto item_after_erased = lst.EraseAfter(lst.cbegin());
  408.             assert((lst == SingleLinkedList<int>{1, 3, 4}));
  409.             assert(item_after_erased == (++lst.begin()));
  410.         }
  411.         {
  412.             SingleLinkedList<int> lst{1, 2, 3, 4};
  413.             const auto item_after_erased = lst.EraseAfter(++(++lst.cbegin()));
  414.             assert((lst == SingleLinkedList<int>{1, 2, 3}));
  415.             assert(item_after_erased == lst.end());
  416.         }
  417.         {
  418.             SingleLinkedList<DeletionSpy> list{DeletionSpy{}, DeletionSpy{}, DeletionSpy{}};
  419.             auto after_begin = ++list.begin();
  420.             int deletion_counter = 0;
  421.             after_begin->deletion_counter_ptr = &deletion_counter;
  422.             assert(deletion_counter == 0u);
  423.             list.EraseAfter(list.cbegin());
  424.             assert(deletion_counter == 1u);
  425.         }
  426.     }
  427. }
  428.  
  429. int main() {
  430.     Test4();
  431. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement