Advertisement
kutuzzzov

Урок 12 реализация методов...

Jul 20th, 2023
1,590
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 9.52 KB | None | 0 0
  1. /* Разместите здесь код класса Vector*/
  2. #pragma once
  3. #include <cassert>
  4. #include <cstdlib>
  5. #include <new>
  6. #include <utility>
  7. #include <memory>
  8. #include <algorithm>
  9.  
  10. template <typename T>
  11. class RawMemory {
  12. public:
  13.     RawMemory() = default;
  14.  
  15.     explicit RawMemory(size_t capacity)
  16.         : buffer_(Allocate(capacity))
  17.         , capacity_(capacity) {
  18.     }
  19.  
  20.     RawMemory(const RawMemory&) = delete;
  21.     RawMemory& operator=(const RawMemory& rhs) = delete;
  22.  
  23.     RawMemory(RawMemory&& other) noexcept
  24.         : buffer_(other.buffer_)
  25.         , capacity_(other.capacity_) {
  26.         other.buffer_ = nullptr;
  27.         other.capacity_ = 0;
  28.     }
  29.  
  30.     RawMemory& operator=(RawMemory&& rhs) noexcept {
  31.         if (this != &rhs) {
  32.             Swap(rhs);
  33.             rhs.Deallocate(rhs.buffer_);
  34.             rhs.buffer_ = nullptr;
  35.             rhs.capacity_ = 0;
  36.         }
  37.         return *this;
  38.     }
  39.  
  40.     ~RawMemory() {
  41.         Deallocate(buffer_);
  42.     }
  43.  
  44.     T* operator+(size_t offset) noexcept {
  45.         assert(offset <= capacity_);
  46.         return buffer_ + offset;
  47.     }
  48.  
  49.     const T* operator+(size_t offset) const noexcept {
  50.         return const_cast<RawMemory&>(*this) + offset;
  51.     }
  52.  
  53.     const T& operator[](size_t index) const noexcept {
  54.         return const_cast<RawMemory&>(*this)[index];
  55.     }
  56.  
  57.     T& operator[](size_t index) noexcept {
  58.         assert(index < capacity_);
  59.         return buffer_[index];
  60.     }
  61.  
  62.     void Swap(RawMemory& other) noexcept {
  63.         std::swap(buffer_, other.buffer_);
  64.         std::swap(capacity_, other.capacity_);
  65.     }
  66.  
  67.     const T* GetAddress() const noexcept {
  68.         return buffer_;
  69.     }
  70.  
  71.     T* GetAddress() noexcept {
  72.         return buffer_;
  73.     }
  74.  
  75.     size_t Capacity() const {
  76.         return capacity_;
  77.     }
  78.  
  79. private:
  80.     static T* Allocate(size_t n) {
  81.         return n != 0 ? static_cast<T*>(operator new(n * sizeof(T))) : nullptr;
  82.     }
  83.  
  84.     static void Deallocate(T* buf) noexcept {
  85.         operator delete(buf);
  86.     }
  87.  
  88.     T* buffer_ = nullptr;
  89.     size_t capacity_ = 0;
  90. };
  91.  
  92. template <typename T>
  93. class Vector {
  94. public:
  95.     using iterator = T*;
  96.     using const_iterator = const T*;
  97.    
  98.     Vector() = default;
  99.  
  100.     explicit Vector(size_t size)
  101.         : data_(size)
  102.         , size_(size)
  103.     {
  104.         std::uninitialized_value_construct_n(data_.GetAddress(), size);
  105.     }
  106.  
  107.     Vector(const Vector& other)
  108.         : data_(other.size_)
  109.         , size_(other.size_)
  110.     {
  111.         std::uninitialized_copy_n(other.data_.GetAddress(), size_, data_.GetAddress());
  112.     }
  113.  
  114.     Vector(Vector&& other) noexcept {
  115.         Swap(other);
  116.     }
  117.  
  118.     Vector& operator=(const Vector& rhs) {
  119.         if (this != &rhs) {
  120.             if (data_.Capacity() < rhs.size_) {
  121.                 Vector rhs_copy(rhs);
  122.                 Swap(rhs_copy);
  123.             }
  124.             else {
  125.                 if (rhs.size_ < size_) {
  126.                     std::copy(rhs.data_.GetAddress(), rhs.data_.GetAddress() + rhs.size_, data_.GetAddress());
  127.                     std::destroy_n(data_.GetAddress() + rhs.size_, size_ - rhs.size_);
  128.                 }
  129.                 else {
  130.                     std::copy(rhs.data_.GetAddress(), rhs.data_.GetAddress() + size_, data_.GetAddress());
  131.                     std::uninitialized_copy_n(rhs.data_.GetAddress() + size_, rhs.size_ - size_, data_.GetAddress() + size_);
  132.                 }
  133.                 size_ = rhs.size_;
  134.  
  135.             }
  136.         }
  137.         return *this;
  138.     }
  139.  
  140.     Vector& operator=(Vector&& rhs) noexcept {
  141.         if (this != &rhs) {
  142.             Swap(rhs);
  143.         }
  144.         return *this;
  145.     }
  146.  
  147.     void Swap(Vector& other) noexcept {
  148.         data_.Swap(other.data_);
  149.         std::swap(size_, other.size_);
  150.     }
  151.  
  152.     ~Vector() {
  153.         std::destroy_n(data_.GetAddress(), size_);
  154.     }
  155.    
  156.     iterator begin() noexcept {
  157.         return data_.GetAddress();
  158.     }
  159.     iterator end() noexcept {
  160.         return data_.GetAddress() + size_;
  161.     }
  162.     const_iterator begin() const noexcept {
  163.         return const_iterator(data_.GetAddress());
  164.     }
  165.     const_iterator end() const noexcept {
  166.         return const_iterator(data_.GetAddress() + size_);
  167.     }
  168.     const_iterator cbegin() const noexcept {
  169.         return begin();
  170.     }
  171.     const_iterator cend() const noexcept {
  172.         return end();
  173.     }
  174.  
  175.     size_t Size() const noexcept {
  176.         return size_;
  177.     }
  178.  
  179.     size_t Capacity() const noexcept {
  180.         return data_.Capacity();
  181.     }
  182.  
  183.     void Reserve(size_t new_capacity) {
  184.         if (new_capacity <= data_.Capacity()) {
  185.             return;
  186.         }
  187.         RawMemory<T> new_data(new_capacity);
  188.  
  189.         if constexpr (std::is_nothrow_move_constructible_v<T> || !std::is_copy_constructible_v<T>) {
  190.             std::uninitialized_move_n(data_.GetAddress(), size_, new_data.GetAddress());
  191.         }
  192.         else {
  193.             std::uninitialized_copy_n(data_.GetAddress(), size_, new_data.GetAddress());
  194.         }
  195.         std::destroy_n(data_.GetAddress(), size_);
  196.         data_.Swap(new_data);
  197.     }
  198.  
  199.     const T& operator[](size_t index) const noexcept {
  200.         return const_cast<Vector&>(*this)[index];
  201.     }
  202.  
  203.     T& operator[](size_t index) noexcept {
  204.         assert(index < size_);
  205.         return data_[index];
  206.     }
  207.  
  208.     void Resize(size_t new_size) {
  209.         if (new_size < size_) {
  210.             std::destroy_n(data_.GetAddress() + new_size, size_ - new_size);
  211.             size_ = new_size;
  212.         }
  213.         else {
  214.             Reserve(new_size);
  215.             std::uninitialized_value_construct_n(data_.GetAddress() + size_, new_size - size_);
  216.             size_ = new_size;
  217.         }
  218.     }
  219.  
  220.     void PushBack(const T& value) {
  221.         EmplaceBack(std::forward<const T&>(value));
  222.     }
  223.  
  224.     void PushBack(T&& value) {
  225.         EmplaceBack(std::forward<T&&>(value));
  226.     }
  227.  
  228.     void PopBack() noexcept {
  229.         assert(size_);
  230.         std::destroy_at(data_.GetAddress() + size_ - 1);
  231.         --size_;
  232.     }
  233.  
  234.     template <typename... Args>
  235.     T& EmplaceBack(Args&&... args) {
  236.         T* result = nullptr;
  237.         if (size_ == Capacity()) {
  238.             RawMemory<T> new_data(size_ == 0 ? 1 : size_ * 2);
  239.             result = new (new_data + size_) T(std::forward<Args>(args)...);
  240.             if constexpr (std::is_nothrow_move_constructible_v<T> || !std::is_copy_constructible_v<T>) {
  241.                 std::uninitialized_move_n(data_.GetAddress(), size_, new_data.GetAddress());
  242.             }
  243.             else {
  244.                 try {
  245.                     std::uninitialized_copy_n(data_.GetAddress(), size_, new_data.GetAddress());
  246.                 }
  247.                 catch (...) {
  248.                     std::destroy_n(new_data.GetAddress() + size_, 1);
  249.                     throw;
  250.                 }
  251.             }
  252.             std::destroy_n(data_.GetAddress(), size_);
  253.             data_.Swap(new_data);
  254.         }
  255.         else {
  256.             result = new (data_ + size_) T(std::forward<Args>(args)...);
  257.         }
  258.         ++size_;
  259.         return *result;
  260.     }
  261.  
  262.     template <typename... Args>
  263.     iterator Emplace(const_iterator pos, Args&&... args) {
  264.         assert(pos >= begin() && pos <= end());
  265.         size_t shift = pos - begin();
  266.         iterator result = nullptr;
  267.         if (size_ == Capacity()) {
  268.             RawMemory<T> new_data(size_ == 0 ? 1 : size_ * 2);
  269.             result = new (new_data + shift) T(std::forward<Args>(args)...);
  270.             if constexpr (std::is_nothrow_move_constructible_v<T> || !std::is_copy_constructible_v<T>) {
  271.                 std::uninitialized_move_n(data_.GetAddress(), shift, new_data.GetAddress());
  272.                 std::uninitialized_move_n(data_.GetAddress() + shift, size_ - shift, new_data.GetAddress() + shift + 1);
  273.             }
  274.             else {
  275.                 try {
  276.                     std::uninitialized_copy_n(data_.GetAddress(), shift, new_data.GetAddress());
  277.                     std::uninitialized_copy_n(data_.GetAddress() + shift, size_ - shift, new_data.GetAddress() + shift + 1);
  278.                 }
  279.                 catch (...) {
  280.                     std::destroy_n(new_data.GetAddress() + shift, 1);
  281.                     throw;
  282.                 }
  283.             }
  284.             std::destroy_n(begin(), size_);
  285.             data_.Swap(new_data);
  286.         }
  287.         else {
  288.             if (size_ != 0) {
  289.                 new (data_ + size_) T(std::move(*(data_.GetAddress() + size_ - 1)));
  290.                 try {
  291.                     std::move_backward(begin() + shift,
  292.                         data_.GetAddress() + size_,
  293.                         data_.GetAddress() + size_ + 1);
  294.                 }
  295.                 catch (...) {
  296.                     std::destroy_n(data_.GetAddress() + size_, 1);
  297.                     throw;
  298.                 }
  299.                 std::destroy_at(begin() + shift);
  300.             }
  301.             result = new (data_ + shift) T(std::forward<Args>(args)...);
  302.         }
  303.         ++size_;
  304.         return result;
  305.     }
  306.  
  307.     iterator Erase(const_iterator pos) noexcept(std::is_nothrow_move_assignable_v<T>) {
  308.         assert(pos >= begin() && pos < end());
  309.         size_t shift = pos - begin();
  310.         std::move(begin() + shift + 1, end(), begin() + shift);
  311.         PopBack();
  312.         return begin() + shift;
  313.     }
  314.  
  315.     iterator Insert(const_iterator pos, const T& value) {
  316.         return Emplace(pos, value);
  317.     }
  318.  
  319.     iterator Insert(const_iterator pos, T&& value) {
  320.         return Emplace(pos, std::move(value));
  321.     }
  322.  
  323. private:
  324.     RawMemory<T> data_;
  325.     size_t size_ = 0;
  326. };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement