Advertisement
Guest User

Untitled

a guest
Oct 22nd, 2019
79
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.46 KB | None | 0 0
  1. template <typename Ty, class Al = std::allocator<Ty>>
  2. class better_vector {
  3. public:
  4.     using Alty_traits = std::allocator_traits<Al>;
  5.     using value_type = Ty;
  6.     using reference = Ty&;
  7.     using iterator = Ty*;
  8.     using const_iterator = const Ty*;
  9.     using pointer = Ty*;
  10. private:
  11.     Al alloc;
  12.     size_t cap = 0, sz = 0;
  13.     pointer strg = nullptr;
  14.     template <typename ...Args>
  15.     void construct_arg(pointer pr_beg, pointer ptr_end, Args&& ...args) {
  16.         std::for_each(pr_beg, ptr_end, [&](reference val) {
  17.             Alty_traits::construct(alloc, &val, std::forward<Args>(args)...);
  18.         });
  19.     }
  20.     constexpr void try_construct_def(pointer ptr_beg, pointer ptr_end) {
  21.         if constexpr (std::is_default_constructible<Ty>())
  22.             std::for_each(ptr_beg, ptr_end, [&](reference val) {
  23.                 Alty_traits::construct(alloc, &val);
  24.             });
  25.     }
  26.     constexpr void construct_def(pointer ptr_beg, pointer ptr_end) {
  27.         std::for_each(ptr_beg, ptr_end, [&](reference val) {
  28.             Alty_traits::construct(alloc, &val);
  29.         });
  30.     }
  31.     constexpr void try_construct_def(Ty& val) {
  32.         if constexpr (std::is_default_constructible<Ty>()) {
  33.             Alty_traits::construct(alloc, &val);
  34.         }
  35.     }
  36.     void construct_def(reference val) {
  37.         Alty_traits::construct(alloc, &val);
  38.     }
  39.     void realloc() {
  40.         pointer temp = alloc.allocate(cap * 2);
  41.         std::uninitialized_copy(strg, strg + sz, temp);
  42.         alloc.deallocate(strg, cap);
  43.         cap *= 2;
  44.         strg = temp;
  45.     }
  46.     void realloc_exactly(const size_t sz) {
  47.         assert(sz > 0);
  48.         pointer temp = alloc.allocate(sz);
  49.         std::uninitialized_copy(strg, strg + sz, temp);
  50.         alloc.deallocate(strg, cap);
  51.         cap = sz;
  52.         strg = temp;
  53.     }
  54. public:
  55.     ~better_vector() {
  56.         if (*this) {
  57.             std::for_each(strg, strg + sz, [&](reference elem) {
  58.                 Alty_traits::destroy(alloc, &elem);
  59.             });
  60.             alloc.deallocate(strg, cap);
  61.         }
  62.     }
  63.     better_vector() = default;
  64.     better_vector(const better_vector& other) noexcept {
  65.         this->sz = other.size();
  66.         this->cap = other.capacity();
  67.         this->strg = alloc.allocate(cap);
  68.         std::uninitialized_copy(other.strg, other.strg + other.sz, strg[0]);
  69.     }
  70.     better_vector& operator =(const better_vector& other) noexcept {
  71.         this->sz = other.size();
  72.         this->cap = other.capacity();
  73.         this->strg = alloc.allocate(cap);
  74.         std::uninitialized_copy(other.strg, other.strg + other.sz, strg[0]);
  75.         return *this;
  76.     }
  77.     better_vector(better_vector&& other) noexcept {
  78.         std::swap(sz, other.sz);
  79.         std::swap(cap, other.cap);
  80.         std::swap(strg, other.strg);
  81.         std::swap(alloc, other.alloc);
  82.     }
  83.     better_vector& operator =(better_vector&& other) noexcept {
  84.         std::swap(sz, other.sz);
  85.         std::swap(cap, other.cap);
  86.         std::swap(strg, other.strg);
  87.         std::swap(alloc, other.alloc);
  88.         return *this;
  89.     }
  90.     better_vector(const size_t sz) {
  91.         strg = alloc.allocate(sz);
  92.         construct_def(strg, strg + sz);
  93.         this->sz = cap = sz;
  94.     }
  95.     better_vector(const std::initializer_list<Ty>& ls) {
  96.         sz = cap = ls.size();
  97.         strg = alloc.allocate(sz);
  98.         for (auto idx = 0u; idx < sz; ++idx)
  99.             Alty_traits::construct(alloc, strg + idx, ls.begin()[idx]);
  100.     }
  101.     auto get_alloc() { return alloc; }
  102.     size_t capacity() const { return cap; }
  103.     size_t size() const { return sz; }
  104.     template <typename ...Ts>
  105.     void emplace_back(Ts&& ...args) {
  106.         if (strg == nullptr) {
  107.             strg = alloc.allocate(++cap);
  108.             Alty_traits::construct(alloc, &strg[sz++], std::forward<Ts>(args)...);
  109.             return;
  110.         }
  111.         if (sz < cap)
  112.             Alty_traits::construct(alloc, &strg[sz++], std::forward<Ts>(args)...);
  113.         else
  114.             realloc(), Alty_traits::construct(alloc, &strg[sz++], std::forward<Ts>(args)...);
  115.     }
  116.     decltype(auto) emplace_back() {
  117.         if (strg == nullptr) {
  118.             strg = alloc.allocate(++cap);
  119.             construct_def(strg[sz++]);
  120.             return strg[0];
  121.         }
  122.         if (sz < cap) {
  123.             construct_def(strg[sz++]);
  124.             return strg[sz - 1];
  125.         }
  126.         realloc();
  127.         construct_def(strg[sz++]);
  128.         return strg[sz - 1];
  129.     }
  130.     void push_back(Ty&& obj) {
  131.         this->emplace_back(std::move(obj));
  132.     }
  133.     void push_back(const reference obj) {
  134.         this->emplace_back(obj);
  135.     }
  136.     void reserve(const size_t new_cap) {
  137.         if (new_cap == cap)
  138.             return;
  139.         cap = new_cap > cap ? realloc_exactly(new_cap), new_cap : new_cap;
  140.     }
  141.     void resize(const size_t new_size) {
  142.         if (new_size == sz)
  143.             return;
  144.         if (new_size < cap) {
  145.             if (new_size < sz)
  146.                 std::for_each(strg + new_size, strg + sz, [&](const reference ty) {
  147.                     Alty_traits::destroy(alloc, &ty);
  148.                 });
  149.             else
  150.                 try_construct_def(strg + sz, strg + new_size);
  151.         } else {
  152.             realloc_exactly(new_size);
  153.             try_construct_def(strg + sz, strg + new_size);
  154.         }
  155.         sz = new_size;
  156.     }
  157.     void clear() {
  158.         std::for_each(strg, strg + sz, [&](reference elem) {
  159.             Alty_traits::destroy(alloc, &elem);
  160.         });
  161.         alloc.deallocate(strg, cap);
  162.         strg = nullptr;
  163.         cap = sz = 0;
  164.     }
  165.     void resize(const size_t new_size, const reference val) {
  166.         if (new_size == sz)
  167.             return;
  168.         if (new_size < cap) {
  169.             if (new_size < sz)
  170.                 std::for_each(strg + new_size, strg + sz, [&](const reference ty) {
  171.                     Alty_traits::destroy(alloc, &ty);
  172.                 });
  173.             else
  174.                 construct_arg(strg + sz, strg + new_size, val);
  175.         } else {
  176.             realloc_exactly(new_size);
  177.             construct_arg(strg + sz, strg + new_size, val);
  178.         }
  179.         sz = new_size;
  180.     }
  181.     reference operator [](const size_t idx) {
  182.         assert(idx <= sz);
  183.         return strg[idx];
  184.     }
  185.     reference at(const size_t idx) {
  186.         return (*this)[idx];
  187.     }
  188.     void pop_back() {
  189.         assert(sz > 0);
  190.         Alty_traits::destroy(alloc, --sz + strg);
  191.     }
  192.     bool empty() const {
  193.         return sz == 0;
  194.     }
  195.     void shrink_to_fit() {
  196.         if (empty())
  197.             return;
  198.         if (cap > sz) {
  199.             realloc_exactly(sz);
  200.         }
  201.     }
  202.     void removeat(const size_t idx) {
  203.         assert(sz > 0);
  204.         for (auto i = idx; i < sz - 1; ++i)
  205.             strg[i] = strg[i + 1];
  206.         pop_back();
  207.     }
  208.     void insert(const size_t where, const reference val) {
  209.         if (sz < cap) {
  210.             for (auto i = sz; i > where; --i)
  211.                 strg[i] = strg[i - 1];
  212.             strg[where] = val;
  213.             ++sz;
  214.         } else {
  215.             realloc_exactly(sz + 2);
  216.             insert(where, val);
  217.         }
  218.     }
  219.     explicit operator bool() const {
  220.         return strg == nullptr;
  221.     }
  222.     void fill(const reference elem) {
  223.         std::fill(begin(), end(), elem);
  224.     }
  225.     friend std::ostream& operator <<(std::ostream& os, const better_vector<Ty>& vc) {
  226.         if (vc.empty())
  227.             return os << "[]";
  228.         os << "[";
  229.         std::copy(vc.cbegin(), vc.cend() - 1, std::ostream_iterator<Ty>(os, ", "));
  230.         os << vc.cend()[-1] << "]";
  231.         return os;
  232.     }
  233.     iterator begin() { return strg; }
  234.     const_iterator cbegin() const { return strg; }
  235.     iterator end() { return strg + sz; }
  236.     const_iterator cend() const { return strg + sz; }
  237. };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement