Advertisement
pavel_777

simple_vector-2.h

Oct 31st, 2023
469
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 12.46 KB | None | 0 0
  1. #pragma once
  2.  
  3. #include <algorithm>
  4. #include <cassert>
  5. #include <initializer_list>
  6. #include <iostream>
  7.  
  8. #include "array_ptr.h"
  9.  
  10. class ReserveProxyObj {
  11. public:
  12.     explicit ReserveProxyObj(size_t capacity_to_reserve) :capacity_(capacity_to_reserve) {}
  13.     size_t GetCapacity() {return capacity_;}
  14. private:
  15.     size_t capacity_;
  16. };
  17.  
  18. ReserveProxyObj Reserve(size_t capacity_to_reserve) {
  19.     return ReserveProxyObj(capacity_to_reserve);
  20. }
  21.  
  22. template <typename Type>
  23. class SimpleVector
  24. {
  25. public:
  26.     using Iterator = Type *;
  27.     using ConstIterator = const Type *;
  28.  
  29.     SimpleVector() noexcept = default;
  30.  
  31.     // Создаёт вектор из size элементов, инициализированных значением по умолчанию
  32.     explicit SimpleVector(size_t size) : SimpleVector(size, std::move(Type())) {}
  33.  
  34.     SimpleVector(size_t size, const Type& value)
  35.     : items_(size), size_(size), capacity_(size) {
  36.         std::fill(begin(), end(), value);
  37.     }
  38.  
  39.     SimpleVector(size_t size, Type &&value)
  40.     : items_(size), size_(size), capacity_(size) {
  41.         // Я понял что он неправильный, но без него ошибка (не знаю как его удалить):
  42.         // error: use of deleted function ‘X& X::operator=(const X&)’
  43.         for (size_t i = 0; i < size_; ++i) {
  44.             items_[i] = std::move(value);
  45.         }
  46.     }
  47.  
  48.     // Создаёт вектор из std::initializer_list
  49.     SimpleVector(std::initializer_list<Type> init)
  50.     : items_(init.size()), size_(init.size()), capacity_(init.size()) {
  51.         std::copy(init.begin(), init.end(), begin());
  52.     }
  53.  
  54.     SimpleVector(const SimpleVector &other)
  55.     : items_(other.capacity_), size_(other.size_),capacity_(other.capacity_) {
  56.         std::copy(other.begin(), other.end(), begin());
  57.     }
  58.  
  59.     SimpleVector(SimpleVector &&other) {
  60.         items_ = std::move(other.items_);
  61.         std::swap(size_, other.size_);
  62.         std::swap(capacity_, other.capacity_);
  63.         other.size_ = 0;
  64.         other.capacity_ = 0;
  65.     }
  66.  
  67.     SimpleVector &operator=(const SimpleVector &rhs) {
  68.         if (this != &rhs) {
  69.             SimpleVector<Type> new_vec(rhs);
  70.             swap(new_vec);
  71.         }
  72.         return *this;
  73.     }
  74.  
  75.     SimpleVector &operator=(SimpleVector &&rhs) {
  76.         if (this != &rhs) {
  77.             items_ = std::move(rhs.items_);
  78.             std::swap(size_, rhs.size_);
  79.             std::swap(capacity_, rhs.capacity_);
  80.             rhs.size_ = 0;
  81.             rhs.capacity_ = 0;
  82.         }
  83.         return *this;
  84.     }
  85.  
  86.     SimpleVector(ReserveProxyObj capacity_to_reserve) {
  87.         Reserve(capacity_to_reserve.GetCapacity());
  88.     }
  89.  
  90.     void Reserve(size_t new_capacity)
  91.     {
  92.         if (new_capacity > capacity_) {
  93.             ArrayPtr<Type> new_items(new_capacity);
  94.             std::copy(std::make_move_iterator(begin()), std::make_move_iterator(end()), new_items.Get());
  95.             items_.swap(new_items);
  96.             capacity_ = new_capacity;
  97.         }
  98.     }    
  99.  
  100.     // Возвращает количество элементов в массиве
  101.     size_t GetSize() const noexcept {return size_;}
  102.  
  103.     // Возвращает вместимость массива
  104.     size_t GetCapacity() const noexcept {return capacity_;}
  105.  
  106.     // Сообщает, пустой ли массив
  107.     bool IsEmpty() const noexcept {return size_ == 0;}
  108.  
  109.     // Возвращает ссылку на элемент с индексом index
  110.     Type &operator[](size_t index) noexcept {
  111.         assert(index < size_);
  112.         return items_[index];
  113.     }
  114.  
  115.     // Возвращает константную ссылку на элемент с индексом index
  116.     const Type &operator[](size_t index) const noexcept {
  117.         assert(index < size_);
  118.         return items_[index];
  119.     }
  120.  
  121.     // Возвращает константную ссылку на элемент с индексом index
  122.     // Выбрасывает исключение std::out_of_range, если index >= size
  123.     Type &At(size_t index) {
  124.         if (index >= size_) {
  125.             throw std::out_of_range("out of range");
  126.         }
  127.         return items_[index];
  128.     }
  129.  
  130.     // Возвращает константную ссылку на элемент с индексом index
  131.     // Выбрасывает исключение std::out_of_range, если index >= size
  132.     const Type &At(size_t index) const {
  133.         if (index >= size_) {
  134.             throw std::out_of_range("out of range");
  135.         }
  136.         return items_[index];
  137.     }
  138.  
  139.     // Обнуляет размер массива, не изменяя его вместимость
  140.     void Clear() noexcept {size_ = 0;}
  141.  
  142.     // Изменяет размер массива.
  143.     // При увеличении размера новые элементы получают значение по умолчанию для типа Type
  144.     void Resize(size_t new_size) {
  145.         if (new_size <= size_) {
  146.             size_ = new_size;
  147.             return;
  148.         }
  149.         if (new_size <= capacity_) {
  150.             for (size_t i = size_; i < new_size; ++i) {
  151.                 items_[i] = Type();
  152.             }
  153.             size_ = new_size;
  154.             return;
  155.         }
  156.         size_t new_capacity = std::max(new_size, capacity_ * 2);
  157.         ArrayPtr<Type> new_items(new_capacity);
  158.  
  159.         std::copy(std::make_move_iterator(begin()), std::make_move_iterator(end()), new_items.Get());
  160.         for (size_t i = size_; i < new_size; ++i) {
  161.             new_items[i] = Type();
  162.         }
  163.  
  164.         items_.swap(new_items);
  165.         capacity_ = new_capacity;
  166.         size_ = new_size;
  167.     }
  168.  
  169.     // Возвращает итератор на начало массива
  170.     // Для пустого массива может быть равен (или не равен) nullptr
  171.     Iterator begin() noexcept {
  172.         return Iterator(items_.Get());
  173.     }
  174.  
  175.     // Возвращает итератор на элемент, следующий за последним
  176.     // Для пустого массива может быть равен (или не равен) nullptr
  177.     Iterator end() noexcept {
  178.         return Iterator(items_.Get() + size_);
  179.     }
  180.  
  181.     // Возвращает константный итератор на начало массива
  182.     // Для пустого массива может быть равен (или не равен) nullptr
  183.     ConstIterator begin() const noexcept {
  184.         return ConstIterator(items_.Get());
  185.     }
  186.  
  187.     // Возвращает итератор на элемент, следующий за последним
  188.     // Для пустого массива может быть равен (или не равен) nullptr
  189.     ConstIterator end() const noexcept {
  190.         return ConstIterator(items_.Get() + size_);
  191.     }
  192.  
  193.     // Возвращает константный итератор на начало массива
  194.     // Для пустого массива может быть равен (или не равен) nullptr
  195.     ConstIterator cbegin() const noexcept {
  196.         return ConstIterator(items_.Get());
  197.     }
  198.  
  199.     // Возвращает итератор на элемент, следующий за последним
  200.     // Для пустого массива может быть равен (или не равен) nullptr
  201.     ConstIterator cend() const noexcept {
  202.         return ConstIterator(items_.Get() + size_);
  203.     }
  204.  
  205.     // Добавляет элемент в конец вектора
  206.     // При нехватке места увеличивает вдвое вместимость вектора
  207.     void PushBack(const Type &item)
  208.     {
  209.         const auto pos = size_;
  210.         if (size_ == capacity_) {
  211.             Resize(capacity_ + 1);
  212.         }
  213.         else {
  214.             ++size_;
  215.         }
  216.         items_[pos] = item;
  217.     }
  218.  
  219.     void PushBack(Type &&item) {
  220.         const auto pos = size_;
  221.         if (size_ == capacity_) {
  222.             Resize(capacity_ + 1);
  223.         }
  224.         else {
  225.             ++size_;
  226.         }
  227.         items_[pos] = std::move(item);
  228.     }
  229.    
  230.     // Вставляет значение value в позицию pos.
  231.     // Возвращает итератор на вставленное значение
  232.     // Если перед вставкой значения вектор был заполнен полностью,
  233.     // вместимость вектора должна увеличиться вдвое, а для вектора вместимостью 0 стать равной 1
  234.     Iterator Insert(ConstIterator pos, const Type &value)
  235.     {
  236.         assert(begin() <= pos && pos <= end());
  237.         auto n = std::distance(begin(), Iterator(pos));
  238.         if (capacity_ == 0) {
  239.             PushBack(value);
  240.             return begin();
  241.         }
  242.         if (size_ < capacity_) {
  243.             for (int i = size_; i > n; --i) {
  244.                 items_[i] = std::move(items_[i - 1]);
  245.             }
  246.             items_[n] = value;
  247.             ++size_;
  248.             return begin() + n;
  249.         }
  250.         else {
  251.             SimpleVector<Type> temp(capacity_ * 2);
  252.             std::copy(begin(), begin() + n, temp.begin());
  253.             std::copy(begin() + n, end(), temp.begin() + n + 1);
  254.             *(temp.begin() + n) = value;
  255.             auto old_size = size_;
  256.             swap(temp);
  257.             size_ = old_size + 1;
  258.             return begin() + n;
  259.         }
  260.     }
  261.  
  262.     Iterator Insert(ConstIterator pos, Type &&value)
  263.     {
  264.         assert(begin() <= pos && pos <= end());
  265.         auto n = std::distance(begin(), Iterator(pos));
  266.         if (capacity_ == 0) {
  267.             PushBack(std::move(value));
  268.             return begin();
  269.         }
  270.         if (size_ < capacity_) {
  271.             for (int i = size_; i > n; --i) {
  272.                 items_[i] = std::move(items_[i - 1]);
  273.             }
  274.             items_[n] = std::move(value);
  275.  
  276.             ++size_;
  277.             return begin() + n;
  278.         }
  279.         else
  280.         {
  281.             SimpleVector<Type> temp(capacity_ * 2);
  282.             std::copy(std::make_move_iterator(begin()), std::make_move_iterator(begin() + n), temp.begin());
  283.             std::copy(std::make_move_iterator(begin() + n), std::make_move_iterator(end()), temp.begin() + n + 1);
  284.             *(temp.begin() + n) = std::move(value);
  285.             auto old_size = size_;
  286.             swap(temp);
  287.             size_ = old_size + 1;
  288.             return begin() + n;
  289.         }
  290.     }
  291.  
  292.     // "Удаляет" последний элемент вектора.
  293.     // Вектор не должен быть пустым
  294.     void PopBack() noexcept {
  295.         assert(size_ > 0);
  296.         --size_;
  297.     }
  298.  
  299.     // Удаляет элемент вектора в указанной позиции
  300.     Iterator Erase(ConstIterator pos) {
  301.         assert(begin() <= pos && pos < end());
  302.         auto n = std::distance(begin(), Iterator(pos));
  303.         std::copy(std::make_move_iterator(begin() + n + 1), std::make_move_iterator(end()), begin() + n);
  304.         --size_;
  305.         return begin() + n;
  306.     }
  307.  
  308.     // Обменивает значение с другим вектором
  309.     void swap(SimpleVector &other) noexcept {
  310.         items_.swap(other.items_);
  311.         std::swap(this->capacity_, other.capacity_);
  312.         std::swap(this->size_, other.size_);
  313.     }
  314.  
  315. private:
  316.     ArrayPtr<Type> items_;
  317.     size_t size_ = 0;
  318.     size_t capacity_ = 0;
  319. };
  320.  
  321. template <typename Type>
  322. inline bool operator==(const SimpleVector<Type>& lhs, const SimpleVector<Type>& rhs) {
  323.     return lhs.GetSize() == rhs.GetSize()
  324.         && std::equal(lhs.begin(), lhs.end(), rhs.begin());
  325. }
  326.  
  327. template <typename Type>
  328. inline bool operator!=(const SimpleVector<Type>& lhs, const SimpleVector<Type>& rhs) {
  329.     return !(lhs==rhs);
  330. }
  331.  
  332. template <typename Type>
  333. inline bool operator<(const SimpleVector<Type>& lhs, const SimpleVector<Type>& rhs) {
  334.     return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
  335. }
  336.  
  337. template <typename Type>
  338. inline bool operator<=(const SimpleVector<Type>& lhs, const SimpleVector<Type>& rhs) {
  339.     return lhs<rhs || lhs==rhs;
  340. }
  341.  
  342. template <typename Type>
  343. inline bool operator>(const SimpleVector<Type>& lhs, const SimpleVector<Type>& rhs) {
  344.     return !(lhs<=rhs);
  345. }
  346.  
  347. template <typename Type>
  348. inline bool operator>=(const SimpleVector<Type>& lhs, const SimpleVector<Type>& rhs) {
  349.     return !(lhs<rhs);
  350. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement