getting crazy at 4:30 AM

Home   »   getting crazy at 4:30 AM

template >
class vectorish_array
    {
    public:
        using value_type = T;
        using pointer = T*;
        using reference = T&;
        using iterator = pointer;
        using reverse_iterator = std::reverse_iterator;


        vectorish_array() : arr{std::allocator_traits::allocate(allocator, Capacity)} {}

        vectorish_array(const vectorish_array& copy) : 
            allocator{std::allocator_traits::select_on_container_copy_construction(copy.allocator)},
            arr{std::allocator_traits::allocate(allocator, Capacity)}
            {
            clear();
            _size = copy._size;
            for (size_t i = 0; i < _size; i++)
                {
                std::allocator_traits::construct(allocator, arr + i, copy[i]);
                }
            }
        vectorish_array& operator=(const vectorish_array& copy)
            {
            if constexpr (std::allocator_traits::propagate_on_container_copy_assignment::value) { allocator = copy.allocator; }

            clear();
            _size = copy._size;
            for (size_t i = 0; i < _size; i++)
                {
                std::allocator_traits::construct(allocator, arr + i, copy[i]);
                }
            return *this;
            }

        vectorish_array(vectorish_array&& move) noexcept : allocator(std::move(move.allocator)), arr(std::move(move.arr))
            {
            move.arr = nullptr;
            move._size = 0;
            }

        vectorish_array& operator=(vectorish_array&& move) noexcept
            {
            if (this == std::addressof(move)) { return *this; }
            clear();

            if constexpr (std::allocator_traits::propagate_on_container_move_assignment::value) 
                { 
                allocator = std::move(move.allocator);
                arr = std::move(move.arr);
                }
            else
                {
                if (allocator == move.allocator)
                    {
                    arr = std::move(move.arr);
                    }
                else
                    {
                    for (auto& element : move)
                        {
                        std::allocator_traits::construct(allocator, arr + i, std::move(move[i]));
                        }
                    }
                }

            _size = move._size;

            move.arr = nullptr;
            move._size = 0;

            return *this;
            }

        ~vectorish_array() 
            {
            if (arr != nullptr)
                {
                clear();
                std::allocator_traits::deallocate(allocator, arr, Capacity);
                }
            }

        void resize(size_t size)
            {
            if (_size == Capacity) { throw std::out_of_range("Cannot resize over array capacity"); }
            if (size < _size) { destroy(arr + size, arr + _size); }
            else { construct(arr + _size, arr + size); }
            _size = size;
            }

        void clear()
            {
            destroy(arr, arr + _size);
            _size = 0;
            }


              T& operator[](int32_t index)       noexcept { return arr[index]; }
        const T& operator[](int32_t index) const noexcept { return arr[index]; }

              T& at(int32_t index)       { if (index >= _size) { throw std::out_of_range("Array access out of range"); } return operator[](index); }
        const T& at(int32_t index) const { if (index >= _size) { throw std::out_of_range("Array access out of range"); } return operator[](index); }

        int32_t size() const noexcept { return _size; }

              iterator begin()       { return arr; }
        const iterator begin() const { return arr; }

              iterator end()       { return arr + _size; }
        const iterator end() const { return arr + _size; }

              reverse_iterator rbegin()       { return reverse_iterator(end()); }
        const reverse_iterator rbegin() const { return reverse_iterator(end()); }

              reverse_iterator rend()       { return reverse_iterator(begin()); }
        const reverse_iterator rend() const { return reverse_iterator(begin()); }

        void push_back(const T& value) { emplace_back(value); }
        void push_back(T&& value)      { emplace_back(std::move(value)); }

        template 
        reference emplace_back(Args&&... args)
            {
            if (_size == Capacity) { throw std::out_of_range("Pushing on full array"); }
            std::allocator_traits::construct(allocator, arr + _size, std::forward(args)...);
            return arr[_size++];
            }

    private:
        Allocator allocator;
        size_t _size = 0;
        T* arr;

        void destroy(pointer from, pointer to)
            {
            for (; from < to; ++from) { std::allocator_traits::destroy(allocator, from); }
            }

        void construct(pointer from, pointer to)
            {
            for (; from < to; ++from) { std::allocator_traits::construct(allocator, from); }
            }
    };

Leave a Reply

Your email address will not be published. Required fields are marked *