Advertisement
oster_man

SimpleVector

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