Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- template <typename Ty, class Al = std::allocator<Ty>>
- class better_vector {
- public:
- using Alty_traits = std::allocator_traits<Al>;
- using value_type = Ty;
- using reference = Ty&;
- using iterator = Ty*;
- using const_iterator = const Ty*;
- using pointer = Ty*;
- private:
- Al alloc;
- size_t cap = 0, sz = 0;
- pointer strg = nullptr;
- template <typename ...Args>
- void construct_arg(pointer pr_beg, pointer ptr_end, Args&& ...args) {
- std::for_each(pr_beg, ptr_end, [&](reference val) {
- Alty_traits::construct(alloc, &val, std::forward<Args>(args)...);
- });
- }
- constexpr void try_construct_def(pointer ptr_beg, pointer ptr_end) {
- if constexpr (std::is_default_constructible<Ty>())
- std::for_each(ptr_beg, ptr_end, [&](reference val) {
- Alty_traits::construct(alloc, &val);
- });
- }
- constexpr void construct_def(pointer ptr_beg, pointer ptr_end) {
- std::for_each(ptr_beg, ptr_end, [&](reference val) {
- Alty_traits::construct(alloc, &val);
- });
- }
- constexpr void try_construct_def(Ty& val) {
- if constexpr (std::is_default_constructible<Ty>()) {
- Alty_traits::construct(alloc, &val);
- }
- }
- void construct_def(reference val) {
- Alty_traits::construct(alloc, &val);
- }
- void realloc() {
- pointer temp = alloc.allocate(cap * 2);
- std::uninitialized_copy(strg, strg + sz, temp);
- alloc.deallocate(strg, cap);
- cap *= 2;
- strg = temp;
- }
- void realloc_exactly(const size_t sz) {
- assert(sz > 0);
- pointer temp = alloc.allocate(sz);
- std::uninitialized_copy(strg, strg + sz, temp);
- alloc.deallocate(strg, cap);
- cap = sz;
- strg = temp;
- }
- public:
- ~better_vector() {
- if (*this) {
- std::for_each(strg, strg + sz, [&](reference elem) {
- Alty_traits::destroy(alloc, &elem);
- });
- alloc.deallocate(strg, cap);
- }
- }
- better_vector() = default;
- better_vector(const better_vector& other) noexcept {
- this->sz = other.size();
- this->cap = other.capacity();
- this->strg = alloc.allocate(cap);
- std::uninitialized_copy(other.strg, other.strg + other.sz, strg[0]);
- }
- better_vector& operator =(const better_vector& other) noexcept {
- this->sz = other.size();
- this->cap = other.capacity();
- this->strg = alloc.allocate(cap);
- std::uninitialized_copy(other.strg, other.strg + other.sz, strg[0]);
- return *this;
- }
- better_vector(better_vector&& other) noexcept {
- std::swap(sz, other.sz);
- std::swap(cap, other.cap);
- std::swap(strg, other.strg);
- std::swap(alloc, other.alloc);
- }
- better_vector& operator =(better_vector&& other) noexcept {
- std::swap(sz, other.sz);
- std::swap(cap, other.cap);
- std::swap(strg, other.strg);
- std::swap(alloc, other.alloc);
- return *this;
- }
- better_vector(const size_t sz) {
- strg = alloc.allocate(sz);
- construct_def(strg, strg + sz);
- this->sz = cap = sz;
- }
- better_vector(const std::initializer_list<Ty>& ls) {
- sz = cap = ls.size();
- strg = alloc.allocate(sz);
- for (auto idx = 0u; idx < sz; ++idx)
- Alty_traits::construct(alloc, strg + idx, ls.begin()[idx]);
- }
- auto get_alloc() { return alloc; }
- size_t capacity() const { return cap; }
- size_t size() const { return sz; }
- template <typename ...Ts>
- void emplace_back(Ts&& ...args) {
- if (strg == nullptr) {
- strg = alloc.allocate(++cap);
- Alty_traits::construct(alloc, &strg[sz++], std::forward<Ts>(args)...);
- return;
- }
- if (sz < cap)
- Alty_traits::construct(alloc, &strg[sz++], std::forward<Ts>(args)...);
- else
- realloc(), Alty_traits::construct(alloc, &strg[sz++], std::forward<Ts>(args)...);
- }
- decltype(auto) emplace_back() {
- if (strg == nullptr) {
- strg = alloc.allocate(++cap);
- construct_def(strg[sz++]);
- return strg[0];
- }
- if (sz < cap) {
- construct_def(strg[sz++]);
- return strg[sz - 1];
- }
- realloc();
- construct_def(strg[sz++]);
- return strg[sz - 1];
- }
- void push_back(Ty&& obj) {
- this->emplace_back(std::move(obj));
- }
- void push_back(const reference obj) {
- this->emplace_back(obj);
- }
- void reserve(const size_t new_cap) {
- if (new_cap == cap)
- return;
- cap = new_cap > cap ? realloc_exactly(new_cap), new_cap : new_cap;
- }
- void resize(const size_t new_size) {
- if (new_size == sz)
- return;
- if (new_size < cap) {
- if (new_size < sz)
- std::for_each(strg + new_size, strg + sz, [&](const reference ty) {
- Alty_traits::destroy(alloc, &ty);
- });
- else
- try_construct_def(strg + sz, strg + new_size);
- } else {
- realloc_exactly(new_size);
- try_construct_def(strg + sz, strg + new_size);
- }
- sz = new_size;
- }
- void clear() {
- std::for_each(strg, strg + sz, [&](reference elem) {
- Alty_traits::destroy(alloc, &elem);
- });
- alloc.deallocate(strg, cap);
- strg = nullptr;
- cap = sz = 0;
- }
- void resize(const size_t new_size, const reference val) {
- if (new_size == sz)
- return;
- if (new_size < cap) {
- if (new_size < sz)
- std::for_each(strg + new_size, strg + sz, [&](const reference ty) {
- Alty_traits::destroy(alloc, &ty);
- });
- else
- construct_arg(strg + sz, strg + new_size, val);
- } else {
- realloc_exactly(new_size);
- construct_arg(strg + sz, strg + new_size, val);
- }
- sz = new_size;
- }
- reference operator [](const size_t idx) {
- assert(idx <= sz);
- return strg[idx];
- }
- reference at(const size_t idx) {
- return (*this)[idx];
- }
- void pop_back() {
- assert(sz > 0);
- Alty_traits::destroy(alloc, --sz + strg);
- }
- bool empty() const {
- return sz == 0;
- }
- void shrink_to_fit() {
- if (empty())
- return;
- if (cap > sz) {
- realloc_exactly(sz);
- }
- }
- void removeat(const size_t idx) {
- assert(sz > 0);
- for (auto i = idx; i < sz - 1; ++i)
- strg[i] = strg[i + 1];
- pop_back();
- }
- void insert(const size_t where, const reference val) {
- if (sz < cap) {
- for (auto i = sz; i > where; --i)
- strg[i] = strg[i - 1];
- strg[where] = val;
- ++sz;
- } else {
- realloc_exactly(sz + 2);
- insert(where, val);
- }
- }
- explicit operator bool() const {
- return strg == nullptr;
- }
- void fill(const reference elem) {
- std::fill(begin(), end(), elem);
- }
- friend std::ostream& operator <<(std::ostream& os, const better_vector<Ty>& vc) {
- if (vc.empty())
- return os << "[]";
- os << "[";
- std::copy(vc.cbegin(), vc.cend() - 1, std::ostream_iterator<Ty>(os, ", "));
- os << vc.cend()[-1] << "]";
- return os;
- }
- iterator begin() { return strg; }
- const_iterator cbegin() const { return strg; }
- iterator end() { return strg + sz; }
- const_iterator cend() const { return strg + sz; }
- };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement