shushus

Спринт 14. Реализация метода EmplaceBack.

May 5th, 2023
468
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 19.43 KB | None | 0 0
  1. -----------------------------------------------------------------------
  2. vector.h
  3. -----------------------------------------------------------------------
  4. #pragma once
  5. #include <cassert>
  6. #include <memory>
  7. #include <algorithm>
  8. #include <cstdlib>
  9. #include <new>
  10. #include <utility>
  11.  
  12. template <typename T>
  13. class RawMemory {
  14. public:
  15.     RawMemory() = default;
  16.  
  17.     explicit RawMemory(size_t capacity) : buffer_(Allocate(capacity))
  18.                                         , capacity_(capacity) {}
  19.  
  20.     ~RawMemory() {Deallocate(buffer_);}
  21.    
  22.     RawMemory(const RawMemory&) = delete;
  23.     RawMemory& operator=(const RawMemory& rhs) = delete;
  24.    
  25.     RawMemory(RawMemory&& other) noexcept : buffer_(std::exchange(other.buffer_, nullptr))
  26.                                           , capacity_(std::exchange(other.capacity_, 0)) {}
  27.  
  28.     RawMemory& operator=(RawMemory&& rhs) noexcept {
  29.        
  30.         if (this != &rhs) {
  31.             buffer_ = std::move(rhs.buffer_);
  32.             capacity_ = std::move(rhs.capacity_);
  33.             rhs.buffer_ = nullptr;
  34.             rhs.capacity_ = 0;
  35.         }
  36.        
  37.         return *this;
  38.     }
  39.  
  40.     T* operator+(size_t offset) noexcept {assert(offset <= capacity_); return buffer_ + offset;}
  41.     const T* operator+(size_t offset) const noexcept {return const_cast<RawMemory&>(*this) + offset;}
  42.  
  43.     const T& operator[](size_t index) const noexcept {return const_cast<RawMemory&>(*this)[index];}
  44.     T& operator[](size_t index) noexcept {assert(index < capacity_); return buffer_[index];}
  45.  
  46.     void Swap(RawMemory& other) noexcept {std::swap(buffer_, other.buffer_); std::swap(capacity_, other.capacity_);}
  47.  
  48.     const T* GetAddress() const noexcept {return buffer_;}
  49.     T* GetAddress() noexcept {return buffer_;}
  50.     size_t Capacity() const {return capacity_;}
  51.  
  52. private:
  53.     T* buffer_ = nullptr;
  54.     size_t capacity_ = 0;
  55.    
  56.     static T* Allocate(size_t n) {return n != 0 ? static_cast<T*>(operator new(n * sizeof(T))) : nullptr;}
  57.     static void Deallocate(T* buf) noexcept {operator delete(buf);}
  58. };
  59.  
  60. template <typename T>
  61. class Vector {
  62. public:
  63.    
  64.     Vector() = default;
  65.  
  66.     explicit Vector(size_t size) : data_(size)
  67.                                  , size_(size) {std::uninitialized_value_construct_n(data_.GetAddress(), size);}
  68.    
  69.     Vector(const Vector& other) : data_(other.size_)
  70.                                 , size_(other.size_) {std::uninitialized_copy_n(other.data_.GetAddress(), size_, data_.GetAddress());}
  71.    
  72.     Vector(Vector&& other) noexcept : data_(std::move(other.data_))
  73.                                     , size_(std::exchange(other.size_, 0)) {}
  74.    
  75.     ~Vector() {std::destroy_n(data_.GetAddress(), size_);}
  76.    
  77.     size_t Size() const noexcept {return size_;}
  78.     size_t Capacity() const noexcept {return data_.Capacity();}
  79.     void Swap(Vector& other) noexcept {data_.Swap(other.data_), std::swap(size_, other.size_);}
  80.    
  81.     void Reserve(size_t new_capacity) {
  82.        
  83.         if (new_capacity <= data_.Capacity()) {
  84.             return;
  85.         }
  86.        
  87.         RawMemory<T> new_data(new_capacity);
  88.        
  89.         if constexpr (std::is_nothrow_move_constructible_v<T> || !std::is_copy_constructible_v<T>) {
  90.             std::uninitialized_move_n(data_.GetAddress(), size_, new_data.GetAddress());
  91.         } else {
  92.             std::uninitialized_copy_n(data_.GetAddress(), size_, new_data.GetAddress());
  93.         }
  94.        
  95.         std::destroy_n(data_.GetAddress(), size_);
  96.         data_.Swap(new_data);
  97.     }
  98.  
  99.     void Resize(size_t new_size) {
  100.        
  101.         if (new_size < size_) {
  102.             std::destroy_n(data_.GetAddress() + new_size, size_ - new_size);
  103.            
  104.         } else {
  105.            
  106.             if (new_size > data_.Capacity()) {
  107.                 const size_t new_capacity = std::max(data_.Capacity() * 2, new_size);
  108.                
  109.                 Reserve(new_capacity);
  110.             }
  111.            
  112.             std::uninitialized_value_construct_n(data_.GetAddress() + size_, new_size - size_);
  113.         }
  114.        
  115.         size_ = new_size;
  116.     }
  117.    
  118.     template <typename Type>
  119.     void PushBack(Type&& value);
  120.    
  121.     template <typename... Args>
  122.     T& EmplaceBack(Args&&... args);
  123.  
  124.     void PopBack() {
  125.         assert(size_);
  126.         std::destroy_at(data_.GetAddress() + size_ - 1);
  127.         --size_;
  128.     }
  129.    
  130.     Vector& operator=(const Vector& other) {
  131.        
  132.         if (this != &other) {
  133.            
  134.             if (other.size_ <= data_.Capacity()) {
  135.                
  136.                 if (size_ <= other.size_) {
  137.                    
  138.                     std::copy(other.data_.GetAddress(),
  139.                               other.data_.GetAddress() + size_,
  140.                               data_.GetAddress());
  141.                    
  142.                     std::uninitialized_copy_n(other.data_.GetAddress() + size_,
  143.                                               other.size_ - size_,
  144.                                               data_.GetAddress() + size_);
  145.                 } else {
  146.                    
  147.                     std::copy(other.data_.GetAddress(),
  148.                               other.data_.GetAddress() + other.size_,
  149.                               data_.GetAddress());
  150.                    
  151.                     std::destroy_n(data_.GetAddress() + other.size_,
  152.                                    size_ - other.size_);
  153.                 }
  154.                
  155.                 size_ = other.size_;
  156.                
  157.             } else {              
  158.                 Vector other_copy(other);
  159.                 Swap(other_copy);
  160.             }
  161.         }
  162.        
  163.         return *this;
  164.     }
  165.  
  166.     Vector& operator=(Vector&& other) noexcept {Swap(other); return *this;}
  167.    
  168.     const T& operator[](size_t index) const noexcept {return const_cast<Vector&>(*this)[index];}
  169.     T& operator[](size_t index) noexcept {assert(index < size_); return data_[index];}
  170.  
  171. private:
  172.     RawMemory<T> data_;
  173.     size_t size_ = 0;
  174. };
  175.  
  176. template <typename T>
  177. template <typename Type>
  178. void Vector<T>::PushBack(Type&& value) {
  179.  
  180.     if (data_.Capacity() <= size_) {
  181.    
  182.         RawMemory<T> new_data(size_ == 0 ? 1 : size_ * 2);
  183.        
  184.         new (new_data.GetAddress() + size_) T(std::forward<Type>(value));
  185.        
  186.         if constexpr (std::is_nothrow_move_constructible_v<T> || !std::is_copy_constructible_v<T>) {
  187.             std::uninitialized_move_n(data_.GetAddress(), size_, new_data.GetAddress());
  188.         } else {
  189.             std::uninitialized_copy_n(data_.GetAddress(), size_, new_data.GetAddress());
  190.         }
  191.        
  192.         std::destroy_n(data_.GetAddress(), size_);
  193.         data_.Swap(new_data);
  194.        
  195.     } else {
  196.         new (data_.GetAddress() + size_) T(std::forward<Type>(value));
  197.     }
  198.    
  199.     size_++;
  200. }
  201.  
  202. template <typename T>
  203. template <typename... Args>
  204. T& Vector<T>::EmplaceBack(Args&&... args) {
  205.  
  206.     if (data_.Capacity() <= size_) {
  207.  
  208.         RawMemory<T> new_data(size_ == 0 ? 1 : size_ * 2);
  209.  
  210.         new (new_data.GetAddress() + size_) T(std::forward<Args>(args)...);
  211.  
  212.         if constexpr (std::is_nothrow_move_constructible_v<T> || !std::is_copy_constructible_v<T>) {
  213.             std::uninitialized_move_n(data_.GetAddress(), size_, new_data.GetAddress());
  214.         } else {
  215.             std::uninitialized_copy_n(data_.GetAddress(), size_, new_data.GetAddress());
  216.         }
  217.  
  218.         std::destroy_n(data_.GetAddress(), size_);
  219.         data_.Swap(new_data);
  220.  
  221.     } else {
  222.         new (data_.GetAddress() + size_) T(std::forward<Args>(args)...);
  223.     }
  224.  
  225.     return data_[size_++];
  226. }
  227. -----------------------------------------------------------------------
  228. main.cpp
  229. -----------------------------------------------------------------------
  230. #include "vector.h"
  231.  
  232. #include <iostream>
  233. #include <stdexcept>
  234. #include <string>
  235.  
  236. namespace {
  237.  
  238. inline const uint32_t DEFAULT_COOKIE = 0xdeadbeef;
  239.  
  240. struct TestObj {
  241.    
  242.     TestObj() = default;
  243.     TestObj(const TestObj& other) = default;
  244.     TestObj& operator=(const TestObj& other) = default;
  245.     TestObj(TestObj&& other) = default;
  246.     TestObj& operator=(TestObj&& other) = default;
  247.    
  248.     ~TestObj() {cookie = 0;}
  249.    
  250.     [[nodiscard]] bool IsAlive() const noexcept {return cookie == DEFAULT_COOKIE;}
  251.    
  252.     uint32_t cookie = DEFAULT_COOKIE;
  253. };
  254.  
  255. struct Obj {
  256.    
  257.     Obj() {
  258.        
  259.         if (default_construction_throw_countdown > 0) {
  260.            
  261.             if (--default_construction_throw_countdown == 0) {
  262.                 throw std::runtime_error("Oops");
  263.             }
  264.         }
  265.        
  266.         ++num_default_constructed;
  267.     }
  268.  
  269.     explicit Obj(int id) : id(id) {++num_constructed_with_id;}
  270.  
  271.     Obj(int id, std::string name) : id(id)
  272.                                   , name(std::move(name)) {++num_constructed_with_id_and_name;}
  273.  
  274.     Obj(const Obj& other) : id(other.id) {
  275.        
  276.         if (other.throw_on_copy) {
  277.             throw std::runtime_error("Oops");
  278.         }
  279.        
  280.         ++num_copied;
  281.     }
  282.  
  283.     Obj(Obj&& other) noexcept : id(other.id) {++num_moved;}
  284.  
  285.     Obj& operator=(const Obj& other) = default;
  286.     Obj& operator=(Obj&& other) = default;
  287.  
  288.     ~Obj() {++num_destroyed; id = 0;}
  289.  
  290.     static int GetAliveObjectCount() {
  291.        
  292.         return num_default_constructed
  293.                + num_copied
  294.                + num_moved
  295.                + num_constructed_with_id
  296.                + num_constructed_with_id_and_name
  297.                - num_destroyed;
  298.     }
  299.  
  300.     static void ResetCounters() {
  301.         default_construction_throw_countdown = 0;
  302.         num_default_constructed = 0;
  303.         num_copied = 0;
  304.         num_moved = 0;
  305.         num_destroyed = 0;
  306.         num_constructed_with_id = 0;
  307.         num_constructed_with_id_and_name = 0;
  308.     }
  309.  
  310.     bool throw_on_copy = false;
  311.     int id = 0;
  312.     std::string name;
  313.  
  314.     static inline int default_construction_throw_countdown = 0;
  315.     static inline int num_default_constructed = 0;
  316.     static inline int num_constructed_with_id = 0;
  317.     static inline int num_constructed_with_id_and_name = 0;
  318.     static inline int num_copied = 0;
  319.     static inline int num_moved = 0;
  320.     static inline int num_destroyed = 0;
  321. };
  322.  
  323. }//end namespace
  324.  
  325. void Test1() {
  326.    
  327.     Obj::ResetCounters();
  328.    
  329.     const size_t SIZE = 100500;
  330.     const size_t INDEX = 10;
  331.     const int MAGIC = 42;
  332.    
  333.     {
  334.         Vector<int> v;
  335.        
  336.         assert(v.Capacity() == 0);
  337.         assert(v.Size() == 0);
  338.  
  339.         v.Reserve(SIZE);
  340.        
  341.         assert(v.Capacity() == SIZE);
  342.         assert(v.Size() == 0);
  343.     }
  344.    
  345.     {
  346.         Vector<int> v(SIZE);
  347.        
  348.         const auto& cv(v);
  349.         assert(v.Capacity() == SIZE);
  350.         assert(v.Size() == SIZE);
  351.         assert(v[0] == 0);
  352.         assert(&v[0] == &cv[0]);
  353.        
  354.         v[INDEX] = MAGIC;
  355.        
  356.         assert(v[INDEX] == MAGIC);
  357.         assert(&v[100] - &v[0] == 100);
  358.  
  359.         v.Reserve(SIZE * 2);
  360.        
  361.         assert(v.Size() == SIZE);
  362.         assert(v.Capacity() == SIZE * 2);
  363.         assert(v[INDEX] == MAGIC);
  364.     }
  365.    
  366.     {
  367.         Vector<int> v(SIZE);
  368.        
  369.         v[INDEX] = MAGIC;
  370.        
  371.         const auto v_copy(v);
  372.         assert(&v[INDEX] != &v_copy[INDEX]);
  373.         assert(v[INDEX] == v_copy[INDEX]);
  374.     }
  375.    
  376.     {
  377.         Vector<Obj> v;
  378.        
  379.         v.Reserve(SIZE);
  380.        
  381.         assert(Obj::GetAliveObjectCount() == 0);
  382.     }
  383.    
  384.     {
  385.         Vector<Obj> v(SIZE);
  386.        
  387.         assert(Obj::GetAliveObjectCount() == SIZE);
  388.        
  389.         const int old_copy_count = Obj::num_copied;
  390.         const int old_move_count = Obj::num_moved;
  391.        
  392.         v.Reserve(SIZE * 2);
  393.        
  394.         assert(Obj::GetAliveObjectCount() == SIZE);
  395.         assert(Obj::num_copied == old_copy_count);
  396.         assert(Obj::num_moved == old_move_count + static_cast<int>(SIZE));
  397.     }
  398.    
  399.     assert(Obj::GetAliveObjectCount() == 0);
  400. }
  401.  
  402. void Test2() {
  403.     const size_t SIZE = 100;
  404.    
  405.     Obj::ResetCounters();
  406.    
  407.     {
  408.         Obj::default_construction_throw_countdown = SIZE / 2;
  409.         try {
  410.             Vector<Obj> v(SIZE);
  411.             assert(false && "Exception is expected");
  412.            
  413.         } catch (const std::runtime_error&) {
  414.            
  415.         } catch (...) {
  416.             assert(false && "Unexpected exception");
  417.         }
  418.        
  419.         assert(Obj::num_default_constructed == SIZE / 2 - 1);
  420.         assert(Obj::GetAliveObjectCount() == 0);
  421.     }
  422.    
  423.     Obj::ResetCounters();
  424.    
  425.     {
  426.         Vector<Obj> v(SIZE);
  427.        
  428.         try {
  429.             v[SIZE / 2].throw_on_copy = true;
  430.             Vector<Obj> v_copy(v);
  431.             assert(false && "Exception is expected");
  432.            
  433.         } catch (const std::runtime_error&) {
  434.             assert(Obj::num_copied == SIZE / 2);
  435.            
  436.         } catch (...) {
  437.             assert(false && "Unexpected exception");
  438.         }
  439.        
  440.         assert(Obj::GetAliveObjectCount() == SIZE);
  441.     }
  442.    
  443.     Obj::ResetCounters();
  444.    
  445.     {
  446.         Vector<Obj> v(SIZE);
  447.        
  448.         try {
  449.             v[SIZE - 1].throw_on_copy = true;
  450.             v.Reserve(SIZE * 2);
  451.            
  452.         } catch (...) {
  453.             assert(false && "Unexpected exception");
  454.         }
  455.        
  456.         assert(v.Capacity() == SIZE * 2);
  457.         assert(v.Size() == SIZE);
  458.         assert(Obj::GetAliveObjectCount() == SIZE);
  459.     }
  460. }
  461.  
  462. void Test3() {
  463.     const size_t MEDIUM_SIZE = 100;
  464.     const size_t LARGE_SIZE = 250;
  465.     const int ID = 42;
  466.    
  467.     {
  468.         Obj::ResetCounters();
  469.        
  470.         Vector<int> v(MEDIUM_SIZE);
  471.        
  472.         {
  473.             auto v_copy(std::move(v));
  474.  
  475.             assert(v_copy.Size() == MEDIUM_SIZE);
  476.             assert(v_copy.Capacity() == MEDIUM_SIZE);
  477.         }
  478.        
  479.         assert(Obj::GetAliveObjectCount() == 0);
  480.     }
  481.    
  482.     {
  483.         Obj::ResetCounters();
  484.        
  485.         {
  486.             Vector<Obj> v(MEDIUM_SIZE);
  487.            
  488.             v[MEDIUM_SIZE / 2].id = ID;
  489.            
  490.             assert(Obj::num_default_constructed == MEDIUM_SIZE);
  491.            
  492.             Vector<Obj> moved_from_v(std::move(v));
  493.            
  494.             assert(moved_from_v.Size() == MEDIUM_SIZE);
  495.             assert(moved_from_v[MEDIUM_SIZE / 2].id == ID);
  496.         }
  497.        
  498.         assert(Obj::GetAliveObjectCount() == 0);
  499.  
  500.         assert(Obj::num_moved == 0);
  501.         assert(Obj::num_copied == 0);
  502.         assert(Obj::num_default_constructed == MEDIUM_SIZE);
  503.     }
  504.    
  505.     {
  506.         Obj::ResetCounters();
  507.        
  508.         Vector<Obj> v_medium(MEDIUM_SIZE);
  509.        
  510.         v_medium[MEDIUM_SIZE / 2].id = ID;
  511.        
  512.         Vector<Obj> v_large(LARGE_SIZE);
  513.        
  514.         v_large = v_medium;
  515.        
  516.         assert(v_large.Size() == MEDIUM_SIZE);
  517.         assert(v_large.Capacity() == LARGE_SIZE);
  518.         assert(v_large[MEDIUM_SIZE / 2].id == ID);
  519.         assert(Obj::GetAliveObjectCount() == MEDIUM_SIZE + MEDIUM_SIZE);
  520.     }
  521.    
  522.     {
  523.         Obj::ResetCounters();
  524.        
  525.         Vector<Obj> v(MEDIUM_SIZE);
  526.        
  527.         {
  528.             Vector<Obj> v_large(LARGE_SIZE);
  529.            
  530.             v_large[LARGE_SIZE - 1].id = ID;
  531.             v = v_large;
  532.            
  533.             assert(v.Size() == LARGE_SIZE);
  534.             assert(v_large.Capacity() == LARGE_SIZE);
  535.             assert(v_large[LARGE_SIZE - 1].id == ID);
  536.             assert(Obj::GetAliveObjectCount() == LARGE_SIZE + LARGE_SIZE);
  537.         }
  538.        
  539.         assert(Obj::GetAliveObjectCount() == LARGE_SIZE);
  540.     }
  541.    
  542.     assert(Obj::GetAliveObjectCount() == 0);
  543.    
  544.     {
  545.         Obj::ResetCounters();
  546.        
  547.         Vector<Obj> v(MEDIUM_SIZE);
  548.        
  549.         v[MEDIUM_SIZE - 1].id = ID;
  550.        
  551.         Vector<Obj> v_small(MEDIUM_SIZE / 2);
  552.         v_small.Reserve(MEDIUM_SIZE + 1);
  553.        
  554.         const size_t num_copies = Obj::num_copied;
  555.         v_small = v;
  556.        
  557.         assert(v_small.Size() == v.Size());
  558.         assert(v_small.Capacity() == MEDIUM_SIZE + 1);
  559.        
  560.         v_small[MEDIUM_SIZE - 1].id = ID;
  561.        
  562.         assert(Obj::num_copied - num_copies == MEDIUM_SIZE - (MEDIUM_SIZE / 2));
  563.     }
  564. }
  565.  
  566. void Test4() {
  567.     const size_t ID = 42;
  568.     const size_t SIZE = 100'500;
  569.    
  570.    {
  571.        Obj::ResetCounters();
  572.        
  573.        Vector<Obj> v;
  574.        
  575.        v.Resize(SIZE);
  576.        
  577.        assert(v.Size() == SIZE);
  578.        assert(v.Capacity() == SIZE);
  579.        assert(Obj::num_default_constructed == SIZE);
  580.    }
  581.    
  582.    assert(Obj::GetAliveObjectCount() == 0);
  583.  
  584.    {
  585.        const size_t NEW_SIZE = 10'000;
  586.        
  587.         Obj::ResetCounters();
  588.        
  589.         Vector<Obj> v(SIZE);
  590.        
  591.         v.Resize(NEW_SIZE);
  592.        
  593.         assert(v.Size() == NEW_SIZE);
  594.         assert(v.Capacity() == SIZE);
  595.         assert(Obj::num_destroyed == SIZE - NEW_SIZE);
  596.     }
  597.    
  598.     assert(Obj::GetAliveObjectCount() == 0);
  599.    
  600.     {
  601.         Obj::ResetCounters();
  602.        
  603.         Vector<Obj> v(SIZE);
  604.        
  605.         Obj o{ID};
  606.        
  607.         v.PushBack(o);
  608.        
  609.         assert(v.Size() == SIZE + 1);
  610.         assert(v.Capacity() == SIZE * 2);
  611.         assert(v[SIZE].id == ID);
  612.         assert(Obj::num_default_constructed == SIZE);
  613.         assert(Obj::num_copied == 1);
  614.         assert(Obj::num_constructed_with_id == 1);
  615.         assert(Obj::num_moved == SIZE);
  616.     }
  617.    
  618.     assert(Obj::GetAliveObjectCount() == 0);
  619.    
  620.     {
  621.         Obj::ResetCounters();
  622.        
  623.         Vector<Obj> v(SIZE);
  624.        
  625.         v.PushBack(Obj{ID});
  626.        
  627.         assert(v.Size() == SIZE + 1);
  628.         assert(v.Capacity() == SIZE * 2);
  629.         assert(v[SIZE].id == ID);
  630.         assert(Obj::num_default_constructed == SIZE);
  631.         assert(Obj::num_copied == 0);
  632.         assert(Obj::num_constructed_with_id == 1);
  633.         assert(Obj::num_moved == SIZE + 1);
  634.     }
  635.    
  636.     {
  637.         Obj::ResetCounters();
  638.        
  639.         Vector<Obj> v;
  640.        
  641.         v.PushBack(Obj{ID});
  642.        
  643.         v.PopBack();
  644.        
  645.         assert(v.Size() == 0);
  646.         assert(v.Capacity() == 1);
  647.         assert(Obj::GetAliveObjectCount() == 0);
  648.     }
  649.  
  650.     {
  651.         Vector<TestObj> v(1);
  652.        
  653.         assert(v.Size() == v.Capacity());
  654.  
  655.         v.PushBack(v[0]);
  656.         assert(v[0].IsAlive());
  657.         assert(v[1].IsAlive());
  658.     }
  659.     {
  660.         Vector<TestObj> v(1);
  661.        
  662.         assert(v.Size() == v.Capacity());
  663.  
  664.         v.PushBack(std::move(v[0]));
  665.         assert(v[0].IsAlive());
  666.         assert(v[1].IsAlive());
  667.     }
  668. }
  669.  
  670. void Test5() {
  671.     const int ID = 42;
  672.     using namespace std::literals;
  673.    
  674.     {
  675.         Obj::ResetCounters();
  676.        
  677.         Vector<Obj> v;
  678.        
  679.         auto& elem = v.EmplaceBack(ID, "Ivan"s);
  680.        
  681.         assert(v.Capacity() == 1);
  682.         assert(v.Size() == 1);
  683.         assert(&elem == &v[0]);
  684.         assert(v[0].id == ID);
  685.         assert(v[0].name == "Ivan"s);
  686.         assert(Obj::num_constructed_with_id_and_name == 1);
  687.         assert(Obj::GetAliveObjectCount() == 1);
  688.     }
  689.    
  690.     assert(Obj::GetAliveObjectCount() == 0);
  691.    
  692.     {
  693.         Vector<TestObj> v(1);
  694.        
  695.         assert(v.Size() == v.Capacity());
  696.  
  697.         v.EmplaceBack(v[0]);
  698.         assert(v[0].IsAlive());
  699.         assert(v[1].IsAlive());
  700.     }
  701. }
  702.  
  703. int main() {
  704.     try {
  705.         Test1();
  706.         Test2();
  707.         Test3();
  708.         Test4();
  709.         Test5();
  710.        
  711.     } catch (const std::exception& e) {
  712.         std::cerr << e.what() << std::endl;
  713.     }
  714. }
Advertisement
Add Comment
Please, Sign In to add comment