Advertisement
YaMolekula

Untitled

Jan 15th, 2023
822
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 30.27 KB | None | 0 0
  1. #include <cassert>
  2. #include <cstddef>
  3. #include <string>
  4. #include <utility>
  5. #include <iostream>
  6.  
  7. template <typename Type>
  8. class SingleLinkedList {
  9.     // Узел списка
  10.     struct Node {
  11.         Node() = default;
  12.         Node(const Type& val, Node* next)
  13.             : value(val)
  14.             , next_node(next) {
  15.         }
  16.         Type value;
  17.         Node* next_node = nullptr;
  18.     };
  19.     template <typename ValueType>
  20.     class BasicIterator {
  21.         friend class SingleLinkedList;
  22.         explicit BasicIterator(Node* node) {
  23.             // assert(false);
  24.             node_=node;
  25.         }
  26.     public:
  27.         // Категория итератора — forward iterator
  28.         // (итератор, который поддерживает операции инкремента и многократное разыменование)
  29.         using iterator_category = std::forward_iterator_tag;
  30.         using value_type = Type; // Тип элементов, по которым перемещается итератор
  31.         using difference_type = std::ptrdiff_t; // Тип, для хранения смещения меж итераторами
  32.         using pointer = ValueType*; // Тип указателя на итерируемое значение
  33.         using reference = ValueType&; // Тип ссылки на итерируемое значение
  34.        
  35.         BasicIterator() = default;
  36.        
  37.         BasicIterator(const BasicIterator<Type>& other) noexcept
  38.         {
  39.             // assert(false);
  40.             // Реализуйте конструктор самостоятельно
  41.             node_=other.node_;
  42.         }
  43.        
  44.         // Чтобы компилятор не выдавал предупреждение об отсутствии оператора = при наличии
  45.         // пользовательского конструктора копирования, явно объявим оператор = и
  46.         // попросим компилятор сгенерировать его за нас
  47.         BasicIterator& operator=(const BasicIterator& rhs) = default;
  48.        
  49.         // Оператор сравнения итераторов (в роли второго аргумента выступает константный итератор)
  50.         // Два итератора равны, если они ссылаются на один и тот же элемент списка либо на end()
  51.         [[nodiscard]] bool operator==(const BasicIterator<const Type>& rhs) const noexcept {
  52.             // assert(false);
  53.             // Заглушка. Реализуйте оператор самостоятельно
  54.             return node_ == rhs.node_;
  55.         }
  56.        
  57.         // Оператор проверки итераторов на неравенство
  58.         // Противоположен !=
  59.         [[nodiscard]] bool operator!=(const BasicIterator<const Type>& rhs) const noexcept {
  60.             // assert(false);
  61.             // Заглушка. Реализуйте оператор самостоятельно
  62.             return node_ != rhs.node_;
  63.         }
  64.        
  65.         // Оператор сравнения итераторов (в роли второго аргумента итератор)
  66.         // Два итератора равны, если они ссылаются на один и тот же элемент списка либо на end()
  67.         [[nodiscard]] bool operator==(const BasicIterator<Type>& rhs) const noexcept {
  68.             // assert(false);
  69.             // Заглушка. Реализуйте оператор самостоятельно
  70.             return node_ == rhs.node_;
  71.         }
  72.        
  73.         // Оператор проверки итераторов на неравенство
  74.         // Противоположен !=
  75.         [[nodiscard]] bool operator!=(const BasicIterator<Type>& rhs) const noexcept {
  76.             // assert(false);
  77.             // Заглушка. Реализуйте оператор самостоятельно
  78.             return node_ != rhs.node_;
  79.         }
  80.        
  81.         BasicIterator& operator++() noexcept {
  82.             // assert(false);
  83.             // Заглушка. Реализуйте оператор самостоятельно
  84.             if(node_){
  85.                 node_=node_->next_node;
  86.             }
  87.             return *this;
  88.         }
  89.        
  90.         BasicIterator operator++(int) noexcept {
  91.             // assert(false);
  92.             // Заглушка. Реализуйте оператор самостоятельно
  93.             auto old_value(*this);
  94.             ++(*this);
  95.             return old_value;
  96.         }
  97.        
  98.         [[nodiscard]] reference operator*() const noexcept {
  99.             // assert(false);
  100.             // Не реализовано
  101.             // Заглушка. Реализуйте оператор самостоятельно
  102.             return node_->value;
  103.         }
  104.        
  105.         [[nodiscard]] pointer operator->() const noexcept {
  106.             // assert(false);
  107.             // Заглушка. Реализуйте оператор самостоятельно
  108.             return &(node_->value);
  109.         }
  110.    
  111.     private:
  112.         Node* node_ = nullptr;
  113.    
  114.     };
  115.  
  116. public:
  117.     using value_type = Type;
  118.     using reference = value_type&;
  119.     using const_reference = const value_type&;
  120.    
  121.     // Итератор, допускающий изменение элементов списка
  122.     using Iterator = BasicIterator<Type>;
  123.     // Константный итератор, предоставляющий доступ для чтения к элементам списка
  124.     using ConstIterator = BasicIterator<const Type>;
  125.    
  126.     // Возвращает итератор, ссылающийся на первый элемент
  127.     // Если список пустой, возвращённый итератор будет равен end()
  128.     [[nodiscard]] Iterator begin() noexcept {
  129.         //assert(false);
  130.         // Реализуйте самостоятельно
  131.         return Iterator{head_.next_node};
  132.     }
  133.  
  134.     // Возвращает итератор, указывающий на позицию, следующую за последним элементом односвязного списка
  135.     // Разыменовывать этот итератор нельзя — попытка разыменования приведёт к неопределённому поведению
  136.     [[nodiscard]] Iterator end() noexcept {
  137.         //assert(false);
  138.         // Реализуйте самостоятельно
  139.         Node * curr=&head_;
  140.         while(curr){
  141.             curr=curr->next_node;
  142.         }
  143.         return Iterator{curr};
  144.     }
  145.  
  146.     // Возвращает константный итератор, ссылающийся на первый элемент
  147.     // Если список пустой, возвращённый итератор будет равен end()
  148.     // Результат вызова эквивалентен вызову метода cbegin()
  149.     [[nodiscard]] ConstIterator begin() const noexcept {
  150.         // assert(false);
  151.         // Реализуйте самостоятельно
  152.         return Iterator{head_.next_node};
  153.     }
  154.  
  155.     // Возвращает константный итератор, указывающий на позицию, следующую за последним элементом односвязного списка
  156.     // Разыменовывать этот итератор нельзя — попытка разыменования приведёт к неопределённому поведению
  157.     // Результат вызова эквивалентен вызову метода cend()
  158.     [[nodiscard]] ConstIterator end() const noexcept {
  159.         // assert(false);
  160.         // Реализуйте самостоятельно
  161.         BasicIterator<const Type> it;
  162.         while(it.node_){
  163.             ++it;
  164.         }
  165.         return it;
  166.     }
  167.  
  168.     // Возвращает константный итератор, ссылающийся на первый элемент
  169.     // Если список пустой, возвращённый итератор будет равен cend()
  170.     [[nodiscard]] ConstIterator cbegin() const noexcept {
  171.         // assert(false);
  172.         // Реализуйте самостоятельно
  173.         return {head_.next_node};
  174.     }
  175.  
  176.     // Возвращает константный итератор, указывающий на позицию, следующую за последним элементом односвязного списка
  177.     // Разыменовывать этот итератор нельзя — попытка разыменования приведёт к неопределённому поведению
  178.     [[nodiscard]] ConstIterator cend() const noexcept {
  179.         // assert(false);
  180.         // Реализуйте самостоятельно
  181.         BasicIterator<const Type> it;
  182.         while(it.node_){
  183.             ++it;
  184.         }
  185.         return it;
  186.     }
  187.  
  188.     SingleLinkedList() {
  189.         size_=0;
  190.     }
  191.    
  192.     SingleLinkedList(const std::initializer_list<Type>& items)
  193.     {
  194.         size_ = 0;
  195.         SingleLinkedList reversed;
  196.         for(Type item: items) {
  197.             reversed.PushFront(item);
  198.         }
  199.         for(Type item: reversed) {
  200.             PushFront(item);
  201.         }        
  202.     }
  203.    
  204.     SingleLinkedList(const SingleLinkedList& other) {
  205.         if(size_ == 0 && head_.next_node == nullptr) {
  206.             SingleLinkedList tmp;
  207.             SingleLinkedList reversed;
  208.             for(auto item: other) {
  209.                 reversed.PushFront(item);
  210.             }
  211.             for(auto item: reversed) {
  212.                 tmp.PushFront(item);
  213.             }
  214.             swap(tmp);
  215.         }
  216.     }
  217.    
  218.     SingleLinkedList& operator=(const SingleLinkedList& rhs){
  219.         SingleLinkedList rhs_copy(rhs);
  220.         if(this->head_.next_node!=rhs_copy.head_.next_node){
  221.             swap(rhs_copy);
  222.         }
  223.         return *this;
  224.     }
  225.    
  226.     ~SingleLinkedList(){
  227.         Clear();
  228.     }
  229.    
  230.     void PushFront(const Type& value){
  231.         head_.next_node = new Node(value, head_.next_node);
  232.         ++size_;
  233.     }
  234.    
  235.    
  236.     void Clear(){
  237.         while(head_.next_node) {
  238.             Node* next_node_new = head_.next_node->next_node;
  239.             delete head_.next_node;
  240.             head_.next_node = next_node_new;
  241.             --size_;
  242.         }
  243.     }
  244.  
  245.     // Возвращает количество элементов в списке за время O(1)
  246.     [[nodiscard]] size_t GetSize() const noexcept {
  247.         // Заглушка. Реализуйте метод самостоятельно
  248.         //assert(false);
  249.         //return 42;
  250.         return size_;
  251.     }
  252.  
  253.     // Сообщает, пустой ли список за время O(1)
  254.     [[nodiscard]] bool IsEmpty() const noexcept {
  255.         // Заглушка. Реализуйте метод самостоятельно
  256.         //assert(false);
  257.         //return false;
  258.         return size_==0;
  259.     }
  260.    
  261.     [[nodiscard]] bool operator==(const SingleLinkedList<Type>& rhs) const noexcept {
  262.         return std::equal(begin(),end(), rhs.begin());
  263.     }
  264.    
  265.     [[nodiscard]] bool operator!=(const SingleLinkedList<Type>& rhs) const noexcept {
  266.         return !(*this==rhs);
  267.     }
  268.    
  269.     [[nodiscard]] bool operator<(const SingleLinkedList<Type>& rhs) const noexcept {
  270.         return std::lexicographical_compare(
  271.             begin(), end(),
  272.             rhs.begin(), rhs.end()
  273.         );
  274.     }
  275.    
  276.     [[nodiscard]] bool operator<=(const SingleLinkedList<Type>& rhs) const noexcept {
  277.         return (*this<rhs) || (*this==rhs);
  278.     }
  279.    
  280.     [[nodiscard]] bool operator>(const SingleLinkedList<Type>& rhs) const noexcept {
  281.         return (rhs<*this);
  282.     }
  283.    
  284.     [[nodiscard]] bool operator>=(const SingleLinkedList<Type>& rhs) const noexcept {
  285.         return (*this>rhs) || (*this==rhs);
  286.     }
  287.    
  288.     void swap(SingleLinkedList& other) noexcept {
  289.         std::swap(head_.next_node, other.head_.next_node);
  290.         std::swap(size_, other.size_);
  291.     }
  292.    
  293.     void PopFront() noexcept {
  294.         Node* ptr = head_.next_node;
  295.         if(!ptr){
  296.             return;
  297.         }
  298.         head_.next_node = head_.next_node->next_node;
  299.         delete ptr;
  300.     }
  301.  
  302.      void EraseAfter(const BasicIterator<Type>& before) noexcept {
  303.         Node* tmp = before.node_->next_node;
  304.         if(!tmp){
  305.             return;
  306.         }
  307.         before.node_->next_node=before.node_->next_node->next_node;
  308.         delete tmp;
  309.     }
  310.    
  311.     Iterator InsertAfter(
  312.         const BasicIterator<Type>& before,
  313.         Type value
  314.     )
  315.     {
  316.         Node* ptr_new = new Node(
  317.             value,
  318.             before.node_->next_node
  319.         );
  320.         before.node_->next_node = ptr_new;
  321.         return {ptr_new};
  322.     }
  323.    
  324.    
  325.    
  326.     [[nodiscard]] Iterator before_begin() noexcept {
  327.         return {head_};
  328.     }
  329.  
  330.     [[nodiscard]] Iterator cbefore_begin() const noexcept {
  331.         return {head_};
  332.     }
  333.    
  334.    
  335.     [[nodiscard]] ConstIterator before_begin() const noexcept {
  336.         return {head_};
  337.     }
  338. private:
  339.     // Фиктивный узел, используется для вставки "перед первым элементом"
  340.     Node head_;
  341.     size_t size_=0;
  342. };
  343.  
  344. template <typename Type>
  345. void swap(SingleLinkedList<Type>& lhs, SingleLinkedList<Type>& rhs) noexcept {
  346.     lhs.swap(rhs);
  347. }
  348.  
  349. void Test0() {
  350.     using namespace std;
  351.     {
  352.         const SingleLinkedList<int> empty_int_list;
  353.         assert(empty_int_list.GetSize() == 0u);
  354.         assert(empty_int_list.IsEmpty());
  355.     }
  356.  
  357.     {
  358.         const SingleLinkedList<string> empty_string_list;
  359.         assert(empty_string_list.GetSize() == 0u);
  360.         assert(empty_string_list.IsEmpty());
  361.     }
  362. }
  363.  
  364. // Эта функция тестирует работу SingleLinkedList
  365. void Test2() {
  366.     // Итерирование по пустому списку
  367.     {
  368.         SingleLinkedList<int> list;
  369.         // Константная ссылка для доступа к константным версиям begin()/end()
  370.         const auto& const_list = list;
  371.  
  372.         // Итераторы begin и end у пустого диапазона равны друг другу
  373.         assert(list.begin() == list.end());
  374.         assert(const_list.begin() == const_list.end());
  375.         assert(list.cbegin() == list.cend());
  376.         assert(list.cbegin() == const_list.begin());
  377.         assert(list.cend() == const_list.end());
  378.     }
  379.  
  380.     // Итерирование по непустому списку
  381.     {
  382.         SingleLinkedList<int> list;
  383.         const auto& const_list = list;
  384.  
  385.         list.PushFront(1);
  386.         assert(list.GetSize() == 1u);
  387.         assert(!list.IsEmpty());
  388.  
  389.         assert(const_list.begin() != const_list.end());
  390.         assert(const_list.cbegin() != const_list.cend());
  391.         assert(list.begin() != list.end());
  392.  
  393.         assert(const_list.begin() == const_list.cbegin());
  394.  
  395.         assert(*list.cbegin() == 1);
  396.         *list.begin() = -1;
  397.         assert(*list.cbegin() == -1);
  398.  
  399.         const auto old_begin = list.cbegin();
  400.         list.PushFront(2);
  401.         assert(list.GetSize() == 2);
  402.  
  403.         const auto new_begin = list.cbegin();
  404.         assert(new_begin != old_begin);
  405.         // Проверка прединкремента
  406.         {
  407.             auto new_begin_copy(new_begin);
  408.             assert((++(new_begin_copy)) == old_begin);
  409.         }
  410.         // Проверка постинкремента
  411.         {
  412.             auto new_begin_copy(new_begin);
  413.             assert(((new_begin_copy)++) == new_begin);
  414.             assert(new_begin_copy == old_begin);
  415.         }
  416.         // Итератор, указывающий на позицию после последнего элемента, равен итератору end()
  417.         {
  418.             auto old_begin_copy(old_begin);
  419.             assert((++old_begin_copy) == list.end());
  420.         }
  421.     }
  422.     // Преобразование итераторов
  423.     {
  424.         SingleLinkedList<int> list;
  425.         list.PushFront(1);
  426.         // Конструирование ConstIterator из Iterator
  427.         SingleLinkedList<int>::ConstIterator const_it(list.begin());
  428.         assert(const_it == list.cbegin());
  429.         assert(*const_it == *list.cbegin());
  430.  
  431.         SingleLinkedList<int>::ConstIterator const_it1;
  432.         // Присваивание ConstIterator'у значения Iterator
  433.         const_it1 = list.begin();
  434.         assert(const_it1 == const_it);
  435.     }
  436.     // Проверка оператора ->
  437.     {
  438.         using namespace std;
  439.         SingleLinkedList<std::string> string_list;
  440.  
  441.         string_list.PushFront("one"s);
  442.         assert(string_list.cbegin()->length() == 3u);
  443.         string_list.begin()->push_back('!');
  444.         assert(*string_list.begin() == "one!"s);
  445.     }
  446. }
  447.  
  448. // Эта функция проверяет работу класса SingleLinkedList
  449. void Test3() {
  450.     // Проверка списков на равенство и неравенство
  451.     {
  452.         SingleLinkedList<int> list_1;
  453.         list_1.PushFront(1);
  454.         list_1.PushFront(2);
  455.  
  456.         SingleLinkedList<int> list_2;
  457.         list_2.PushFront(1);
  458.         list_2.PushFront(2);
  459.         list_2.PushFront(3);
  460.  
  461.         SingleLinkedList<int> list_1_copy;
  462.         list_1_copy.PushFront(1);
  463.         list_1_copy.PushFront(2);
  464.  
  465.         SingleLinkedList<int> empty_list;
  466.         SingleLinkedList<int> another_empty_list;
  467.  
  468.         // Список равен самому себе
  469.         assert(list_1 == list_1);
  470.         assert(empty_list == empty_list);
  471.  
  472.         // Списки с одинаковым содержимым равны, а с разным - не равны
  473.         assert(list_1 == list_1_copy);
  474.         assert(list_1 != list_2);
  475.         assert(list_2 != list_1);
  476.         assert(empty_list == another_empty_list);
  477.     }
  478.  
  479.     // Обмен содержимого списков
  480.     {
  481.         SingleLinkedList<int> first;
  482.         first.PushFront(1);
  483.         first.PushFront(2);
  484.  
  485.         SingleLinkedList<int> second;
  486.         second.PushFront(10);
  487.         second.PushFront(11);
  488.         second.PushFront(15);
  489.  
  490.         const auto old_first_begin = first.begin();
  491.         const auto old_second_begin = second.begin();
  492.         const auto old_first_size = first.GetSize();
  493.         const auto old_second_size = second.GetSize();
  494.  
  495.         first.swap(second);
  496.  
  497.         assert(second.begin() == old_first_begin);
  498.         assert(first.begin() == old_second_begin);
  499.         assert(second.GetSize() == old_first_size);
  500.         assert(first.GetSize() == old_second_size);
  501.  
  502.         // Обмен при помощи функции swap
  503.         {
  504.             using std::swap;
  505.  
  506.             // В отсутствие пользовательской перегрузки будет вызвана функция std::swap, которая
  507.             // выполнит обмен через создание временной копии
  508.             swap(first, second);
  509.  
  510.             // Убеждаемся, что используется не std::swap, а пользовательская перегрузка
  511.  
  512.             // Если бы обмен был выполнен с созданием временной копии,
  513.             // то итератор first.begin() не будет равен ранее сохранённому значению,
  514.             // так как копия будет хранить свои узлы по иным адресам
  515.             assert(first.begin() == old_first_begin);
  516.             assert(second.begin() == old_second_begin);
  517.             assert(first.GetSize() == old_first_size);
  518.             assert(second.GetSize() == old_second_size);
  519.         }
  520.     }
  521.  
  522.     // Инициализация списка при помощи std::initializer_list
  523.     {
  524.         SingleLinkedList<int> list{1, 2, 3, 4, 5};
  525.         assert(list.GetSize() == 5);
  526.         assert(!list.IsEmpty());
  527.         assert(std::equal(list.begin(), list.end(), std::begin({1, 2, 3, 4, 5})));
  528.     }
  529.  
  530.     // Лексикографическое сравнение списков
  531.     {
  532.         using IntList = SingleLinkedList<int>;
  533.  
  534.         assert((IntList{1, 2, 3} < IntList{1, 2, 3, 1}));
  535.         assert((IntList{1, 2, 3} <= IntList{1, 2, 3}));
  536.         assert((IntList{1, 2, 4} > IntList{1, 2, 3}));
  537.         assert((IntList{1, 2, 3} >= IntList{1, 2, 3}));
  538.     }
  539.  
  540.     // Копирование списков
  541.     {
  542.         const SingleLinkedList<int> empty_list{};
  543.         // Копирование пустого списка
  544.         {
  545.             auto list_copy(empty_list);
  546.             assert(list_copy.IsEmpty());
  547.         }
  548.  
  549.         SingleLinkedList<int> non_empty_list{1, 2, 3, 4};
  550.         // Копирование непустого списка
  551.         {
  552.             auto list_copy(non_empty_list);
  553.  
  554.             assert(non_empty_list.begin() != list_copy.begin());
  555.             assert(list_copy == non_empty_list);
  556.         }
  557.     }
  558.  
  559.     // Присваивание списков
  560.     {
  561.         const SingleLinkedList<int> source_list{1, 2, 3, 4};
  562.  
  563.         SingleLinkedList<int> receiver{5, 4, 3, 2, 1};
  564.         receiver = source_list;
  565.         assert(receiver.begin() != source_list.begin());
  566.         assert(receiver == source_list);
  567.     }
  568.  
  569.     // Вспомогательный класс, бросающий исключение после создания N-копии
  570.     struct ThrowOnCopy {
  571.         ThrowOnCopy() = default;
  572.         explicit ThrowOnCopy(int& copy_counter) noexcept
  573.             : countdown_ptr(&copy_counter) {
  574.         }
  575.         ThrowOnCopy(const ThrowOnCopy& other)
  576.             : countdown_ptr(other.countdown_ptr)  //
  577.         {
  578.             if (countdown_ptr) {
  579.                 if (*countdown_ptr == 0) {
  580.                     throw std::bad_alloc();
  581.                 } else {
  582.                     --(*countdown_ptr);
  583.                 }
  584.             }
  585.         }
  586.         // Присваивание элементов этого типа не требуется
  587.         ThrowOnCopy& operator=(const ThrowOnCopy& rhs) = delete;
  588.         // Адрес счётчика обратного отсчёта. Если не равен nullptr, то уменьшается при каждом копировании.
  589.         // Как только обнулится, конструктор копирования выбросит исключение
  590.         int* countdown_ptr = nullptr;
  591.     };
  592.  
  593.     // Безопасное присваивание списков
  594.     {
  595.         SingleLinkedList<ThrowOnCopy> src_list;
  596.         src_list.PushFront(ThrowOnCopy{});
  597.         src_list.PushFront(ThrowOnCopy{});
  598.         auto thrower = src_list.begin();
  599.         src_list.PushFront(ThrowOnCopy{});
  600.  
  601.         int copy_counter = 0;  // при первом же копировании будет выброшего исключение
  602.         thrower->countdown_ptr = &copy_counter;
  603.  
  604.         SingleLinkedList<ThrowOnCopy> dst_list;
  605.         dst_list.PushFront(ThrowOnCopy{});
  606.         int dst_counter = 10;
  607.         dst_list.begin()->countdown_ptr = &dst_counter;
  608.         dst_list.PushFront(ThrowOnCopy{});
  609.  
  610.         try {
  611.             dst_list = src_list;
  612.             // Ожидается исключение при присваивании
  613.             assert(false);
  614.         } catch (const std::bad_alloc&) {
  615.             // Проверяем, что состояние списка-приёмника не изменилось
  616.             // при выбрасывании исключений
  617.             assert(dst_list.GetSize() == 2);
  618.             auto it = dst_list.begin();
  619.             assert(it != dst_list.end());
  620.             assert(it->countdown_ptr == nullptr);
  621.             ++it;
  622.             assert(it != dst_list.end());
  623.             assert(it->countdown_ptr == &dst_counter);
  624.             assert(dst_counter == 10);
  625.         } catch (...) {
  626.             // Других типов исключений не ожидается
  627.             assert(false);
  628.         }
  629.     }
  630. }
  631.  
  632. // Эта функция проверяет работу класса SingleLinkedList
  633. void Test4() {
  634.     struct DeletionSpy {
  635.         ~DeletionSpy() {
  636.             if (deletion_counter_ptr) {
  637.                 ++(*deletion_counter_ptr);
  638.             }
  639.         }
  640.         int* deletion_counter_ptr = nullptr;
  641.     };
  642.  
  643.     // Проверка PopFront
  644.     {
  645.         SingleLinkedList<int> numbers{3, 14, 15, 92, 6};
  646.         numbers.PopFront();
  647.         assert((numbers == SingleLinkedList<int>{14, 15, 92, 6}));
  648.  
  649.         SingleLinkedList<DeletionSpy> list;
  650.         list.PushFront(DeletionSpy{});
  651.         int deletion_counter = 0;
  652.         list.begin()->deletion_counter_ptr = &deletion_counter;
  653.         assert(deletion_counter == 0);
  654.         list.PopFront();
  655.         assert(deletion_counter == 1);
  656.     }
  657.  
  658.     // Доступ к позиции, предшествующей begin
  659.     {
  660.         SingleLinkedList<int> empty_list;
  661.         const auto& const_empty_list = empty_list;
  662.         assert(empty_list.before_begin() == empty_list.cbefore_begin());
  663.         assert(++empty_list.before_begin() == empty_list.begin());
  664.         assert(++empty_list.cbefore_begin() == const_empty_list.begin());
  665.  
  666.         SingleLinkedList<int> numbers{1, 2, 3, 4};
  667.         const auto& const_numbers = numbers;
  668.         assert(numbers.before_begin() == numbers.cbefore_begin());
  669.         assert(++numbers.before_begin() == numbers.begin());
  670.         assert(++numbers.cbefore_begin() == const_numbers.begin());
  671.     }
  672.  
  673.     // Вставка элемента после указанной позиции
  674.     {  // Вставка в пустой список
  675.         {
  676.             SingleLinkedList<int> lst;
  677.             const auto inserted_item_pos = lst.InsertAfter(lst.before_begin(), 123);
  678.             assert((lst == SingleLinkedList<int>{123}));
  679.             assert(inserted_item_pos == lst.begin());
  680.             assert(*inserted_item_pos == 123);
  681.         }
  682.  
  683.         // Вставка в непустой список
  684.         {
  685.             SingleLinkedList<int> lst{1, 2, 3};
  686.             auto inserted_item_pos = lst.InsertAfter(lst.before_begin(), 123);
  687.  
  688.             assert(inserted_item_pos == lst.begin());
  689.             assert(inserted_item_pos != lst.end());
  690.             assert(*inserted_item_pos == 123);
  691.             assert((lst == SingleLinkedList<int>{123, 1, 2, 3}));
  692.  
  693.             inserted_item_pos = lst.InsertAfter(lst.begin(), 555);
  694.             assert(++SingleLinkedList<int>::Iterator(lst.begin()) == inserted_item_pos);
  695.             assert(*inserted_item_pos == 555);
  696.             assert((lst == SingleLinkedList<int>{123, 555, 1, 2, 3}));
  697.         };
  698.     }
  699.  
  700.     // Вспомогательный класс, бросающий исключение после создания N-копии
  701.     struct ThrowOnCopy {
  702.         ThrowOnCopy() = default;
  703.         explicit ThrowOnCopy(int& copy_counter) noexcept
  704.             : countdown_ptr(&copy_counter) {
  705.         }
  706.         ThrowOnCopy(const ThrowOnCopy& other)
  707.             : countdown_ptr(other.countdown_ptr)  //
  708.         {
  709.             if (countdown_ptr) {
  710.                 if (*countdown_ptr == 0) {
  711.                     throw std::bad_alloc();
  712.                 } else {
  713.                     --(*countdown_ptr);
  714.                 }
  715.             }
  716.         }
  717.         // Присваивание элементов этого типа не требуется
  718.         ThrowOnCopy& operator=(const ThrowOnCopy& rhs) = delete;
  719.         // Адрес счётчика обратного отсчёта. Если не равен nullptr, то уменьшается при каждом копировании.
  720.         // Как только обнулится, конструктор копирования выбросит исключение
  721.         int* countdown_ptr = nullptr;
  722.     };
  723.  
  724.     // Проверка обеспечения строгой гарантии безопасности исключений
  725.     {
  726.         bool exception_was_thrown = false;
  727.         for (int max_copy_counter = 10; max_copy_counter >= 0; --max_copy_counter) {
  728.             SingleLinkedList<ThrowOnCopy> list{ThrowOnCopy{}, ThrowOnCopy{}, ThrowOnCopy{}};
  729.             try {
  730.                 int copy_counter = max_copy_counter;
  731.                 list.InsertAfter(list.cbegin(), ThrowOnCopy(copy_counter));
  732.                 assert(list.GetSize() == 4u);
  733.             } catch (const std::bad_alloc&) {
  734.                 exception_was_thrown = true;
  735.                 assert(list.GetSize() == 3u);
  736.                 break;
  737.             }
  738.         }
  739.         assert(exception_was_thrown);
  740.     }
  741.  
  742.     // Удаление элементов после указанной позиции
  743.     {
  744.         {
  745.             SingleLinkedList<int> lst{1, 2, 3, 4};
  746.             const auto& const_lst = lst;
  747.             const auto item_after_erased = lst.EraseAfter(const_lst.cbefore_begin());
  748.             assert((lst == SingleLinkedList<int>{2, 3, 4}));
  749.             assert(item_after_erased == lst.begin());
  750.         }
  751.         {
  752.             SingleLinkedList<int> lst{1, 2, 3, 4};
  753.             const auto item_after_erased = lst.EraseAfter(lst.cbegin());
  754.             assert((lst == SingleLinkedList<int>{1, 3, 4}));
  755.             assert(item_after_erased == (++lst.begin()));
  756.         }
  757.         {
  758.             SingleLinkedList<int> lst{1, 2, 3, 4};
  759.             const auto item_after_erased = lst.EraseAfter(++(++lst.cbegin()));
  760.             assert((lst == SingleLinkedList<int>{1, 2, 3}));
  761.             assert(item_after_erased == lst.end());
  762.         }
  763.         {
  764.             SingleLinkedList<DeletionSpy> list{DeletionSpy{}, DeletionSpy{}, DeletionSpy{}};
  765.             auto after_begin = ++list.begin();
  766.             int deletion_counter = 0;
  767.             after_begin->deletion_counter_ptr = &deletion_counter;
  768.             assert(deletion_counter == 0u);
  769.             list.EraseAfter(list.cbegin());
  770.             assert(deletion_counter == 1u);
  771.         }
  772.     }
  773. }
  774.  
  775. int main() {
  776.     Test4();
  777. }
  778.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement