I haven't really programmed in C++ for about a year, and realised that I should get back into it, and tried my abilities out by remaking the STD vector class. However, my C++ is a bit rusty at the moment, and was wondering if I have made many mistakes in my implementation.

# ifndef VECTOR_H
# define VECTOR_H
# include <memory>

namespace test
    {
    template
        <class T,
    class A>
    class vector;

    template
        <class A>
        class vector_alloc_types
        {
    public:
        typedef typename A::value_type value_type;
        typedef typename A::size_type size_type;
        typedef typename A::reference reference;
        typedef typename A::const_reference const_reference;
        typedef typename A::pointer iterator;
        typedef typename A::const_pointer const_iterator;
        typedef typename A::const_pointer const_pointer;
        typedef A allocator_type;
        };

    template
        <class T,
        class A>
        class vector_base
        {
        friend class vector<T, A>;
    public:
        typedef typename A::pointer pointer;
        vector_base()
            {
            vm_begin = pointer();
            value_end = pointer();
            memory_end = pointer();
            }
    private:
        pointer vm_begin, value_end, memory_end;
        };

    template 
        <class T,
        class A = std::allocator<T> >
        class vector
            : public vector_alloc_types<A>,
            public vector_base<T, A>
        {
    public:
        typedef vector<T, A> my_T;
        typedef vector_base<T, A> my_base;

        vector()
            : my_base()
            {
            }

        vector(my_T const &rhs)
            {
            if (allocate(rhs.size()))
                {
                try
                    {
                    this->value_end = std::uninitialized_copy(rhs.vm_begin, rhs.value_end, this->vm_begin);
                    }
                catch (...)
                    {
                    kill();
                    throw;
                    }
                }
            }

        vector(pointer first, pointer last)
            : my_base()
            {
            if (allocate(std::distance(first, last)))
                {
                try
                    {
                    this->value_end = std::uninitialized_copy(first, last, this->vm_begin);
                    }
                catch (...)
                    {
                    kill();
                    throw;
                    }
                }
            }

        template<size_type sz>
        vector(T arr[sz])
            {
            if (allocate(sz))
                {
                try
                    {
                    this->value_end = std::uninitialized_copy_n(arr, sz, this->vm_begin);
                    }
                catch (...)
                    {
                    kill();
                    throw;
                    }
                }
            }

        vector(size_type sz)
            {
            if (allocate(sz))
                {
                try
                    {
                    this->value_end = std::uninitialized_fill_n(this->vm_begin, sz, T());
                    }
                catch (...)
                    {
                    kill();
                    throw;
                    }
                }
            }

        vector(size_type sz, T const &val)
            {
            if (allocate(sz))
                {
                try
                    {
                    this->value_end = std::uninitialized_fill_n(this->vm_begin, sz, val);
                    }
                catch (...)
                    {
                    kill();
                    throw;
                    }
                }
            }

        ~vector()
            {
            kill();
            }

        void operator=(my_T &rhs)
            {
            if (this != &rhs)
                {
                assign(rhs);
                }
            }

        template<unsigned sz>
        void operator=(T (&arr)[sz])
            {
            assign(&arr[0], &arr[sz]);
            }

        void clear()
            {
            wipe(this->vm_begin, this->value_end);
            }

        iterator begin()
            {
            return (this->vm_begin);
            }

        const_iterator cbegin() const
            {
            return ((const_iterator)this->vm_begin);
            }

        iterator end()
            {
            return (this->value_end);
            }

        const_iterator cend() const
            {
            return ((const_iterator)this->value_end);
            }

        void swap(my_T &rhs)
            {
            std::swap(this->vm_begin, rhs.vm_begin);
            std::swap(this->value_end, rhs.value_end);
            std::swap(this->memory_end, rhs.memory_end);
            }

        void shrink_to_fit()
            {
            if (has_spare_capacity())
                {
                my_T tmp(*this);
                swap(tmp);
                }
            }

        void erase(iterator iter)
            {
            pointer tmp;
            if (iter == (this->value_end - 1))
                {
                pop_back();
                }
            else if (iter == this->vm_begin)
                {
                pop_front();
                }
            else if (iterator_in_range(iter))
                {
                tmp = allocator_type().allocate(size() - 1);
                pointer tmp2 = std::uninitialized_copy(this->vm_begin, iter, tmp);
                tmp2 = std::uninitialized_copy((iter + 1), this->value_end, tmp2);
                assign(tmp, tmp2);
                }
            }

        void erase(iterator first, iterator last)
            {
            if (last == (this->value_end - 1))
                {
                while (last-- != first)
                    {
                    pop_back();
                    }
                pop_back();
                }
            else if (first == this->vm_begin)
                {
                while (first++ != last)
                    {
                    pop_front();
                    }
                pop_front();
                }
            else if (iterator_in_range(first) && iterator_in_range(last))
                {
                pointer tmp = allocator_type().allocate(size() - std::distance(first, last));
                pointer tmp2 = std::uninitialized_copy(this->vm_begin, first, tmp);
                tmp2 = std::uninitialized_copy((last + 1), this->value_end, tmp2);
                assign(tmp, tmp2);
                }
            }

        void insert(iterator iter, T const &val)
            {
            T v1 = val;
            if (iter == this->vm_begin)
                {
                push_front(v1);
                }
            else if (iter == (this->value_end - 1))
                {
                push_back(v1);
                }
            else if (iterator_in_range(iter))
                {
                allocator_type alloc;
                pointer tmp = alloc.allocate(realloc_size(size() + 1));
                pointer tmp2 = std::uninitialized_copy(this->vm_begin, iter, tmp);
                alloc.construct(tmp2++, v1);
                tmp2 = std::uninitialized_copy(iter, this->value_end, tmp2);
                assign(tmp, tmp2);
                }
            }

        void insert(iterator iter, int count, T const &val)
            {
            T v1 = val;
            if (iter == this->vm_begin)
                {
                while (count--)
                    {
                    push_front(v1);
                    }
                }
            else if (iter == (this->value_end - 1))
                {
                while (count--)
                    {
                    push_back(v1);
                    }
                }
            else if (iterator_in_range(iter))
                {
                allocator_type alloc;
                pointer tmp = alloc.allocate(realloc_size(size() + 1));
                pointer tmp2 = std::uninitialized_copy(this->vm_begin, iter, tmp);
                while (count--)
                    {
                    alloc.construct(tmp2++, v1);
                    }
                tmp2 = std::uninitialized_copy(iter, this->value_end, tmp2);
                assign(tmp, tmp2);
                }
            }

        void insert(iterator iter, iterator first, iterator last)
            {
            if (iter == this->vm_begin)
                {
                while (first != last)
                    {
                    push_front(*(first++));
                    }
                }
            else if (iter == (this->value_end - 1))
                {
                while (first != last)
                    {
                    push_back(*(first++));
                    }
                }
            else if (iterator_in_range(iter))
                {   
                allocator_type alloc;
                pointer tmp = alloc.allocate(realloc_size(size() + 1));
                pointer tmp2 = std::uninitialized_copy(this->vm_begin, iter, tmp);
                while (first != last)
                    {
                    alloc.construct(tmp2++, *(first++));
                    }
                tmp2 = std::uninitialized_copy(iter, this->value_end, tmp2);
                assign(tmp, tmp2);
                }
            }

        void push_back(T const &val)
            {
            allocator_type alloc;
            T v1 = val;
            if (has_spare_capacity())
                {
                this->value_end++;
                alloc.construct(this->value_end - 1, v1);
                }
            else if (reallocate(realloc_size(size() + 1)))
                {
                this->value_end++;
                alloc.construct(this->value_end - 1, v1);
                }
            }

        void pop_back()
            {
            pointer tmp = allocator_type().allocate(size() - 1);
            pointer tmp2 = std::uninitialized_copy(this->vm_begin, this->value_end - 1, tmp);
            assign(tmp, tmp2);
            }

        void push_front(T const &val)
            {
            allocator_type alloc;
            T v1 = val;
            vector tmp;
            tmp.push_back(v1);
            for (iterator it = this->vm_begin; it != this->value_end; ++it)
                {
                tmp.push_back(*it);
                }
            swap(tmp);
            }

        void pop_front()
            {
            pointer tmp = allocator_type().allocate(size() - 1);
            pointer tmp2 = std::uninitialized_copy(this->vm_begin + 1, this->value_end, tmp);
            assign(tmp, tmp2);
            }

        size_type size() const
            {
            return (this->value_end - this->vm_begin);
            }

        reference operator[](size_type pos)
            {
            return (*(this->vm_begin + pos));
            }

        const_reference operator[](size_type pos) const
            {
            return (*(this->vm_begin + pos));
            }

    private:
        bool allocate(size_type sz)
            {
            allocator_type alloc;
            if (alloc.max_size() > sz)
                {
                try
                    {
                    this->vm_begin = alloc.allocate(sz);
                    this->value_end = this->vm_begin;
                    this->memory_end = this->vm_begin + sz;
                    }
                catch (...)
                    {
                    kill();
                    throw;
                    }
                return (true);
                }
            return (false);
            }

        bool reallocate(size_type sz)
            {
            allocator_type alloc;
            if (alloc.max_size() > sz)
                {
                try
                    {
                    pointer nbegin, nvend, nmend;
                    nbegin = alloc.allocate(sz);
                    nmend = nbegin + sz;
                    nvend = std::uninitialized_copy(this->vm_begin, this->value_end, nbegin);
                    this->vm_begin = nbegin;
                    this->value_end = nvend;
                    this->memory_end = nmend;
                    }
                catch (...)
                    {
                    kill();
                    throw;
                    }
                return (true);
                }
            return (false);
            }

        size_type realloc_size(size_type sz) const
            {
            return ((allocator_type().max_size() > (sz * 1.5)) ? (sz * 1.5) : sz);
            }

        bool iterator_in_range(const_iterator iter) const
            {
            return (iter >= this->vm_begin && iter < this->value_end);
            }

        void assign(my_T &rhs)
            {
            assign(rhs.vm_begin, rhs.value_end);
            }

        void assign(pointer first, pointer last)
            {
            size_type sz = std::distance(first, last);
            if (sz > capacity())
                {
                if (reallocate(realloc_size(sz)))
                    {
                    wipe(this->vm_begin, this->value_end);
                    this->value_end = std::uninitialized_copy(first, last, this->vm_begin);
                    }
                }
            else
                {
                wipe(this->vm_begin, this->value_end);
                this->value_end = std::uninitialized_copy(first, last, this->vm_begin);
                }
            }

        void wipe(pointer ptr)
            {
            allocator_type().destroy(ptr);
            }

        void wipe(pointer first, pointer last)
            {
            allocator_type alloc;
            while (first != last)
                {
                alloc.destroy(first++);
                }
            }

        void wipe(pointer ptr, size_type dist)
            {
            allocator_type alloc;
            while (dist-- != 0)
                {
                alloc.destroy(ptr);
                }
            }

        void kill()
            {
            if (this->vm_begin != pointer())
                {
                wipe(this->vm_begin, this->value_end);
                allocator_type().deallocate(this->vm_begin, capacity());
                }
            }

        inline size_type capacity() const
            {
            return (this->memory_end - this->vm_begin);
            }

        inline size_type spare_capacity() const
            {
            return (this->memory_end - this->value_end);
            }

        bool has_spare_capacity() const
            {
            return (spare_capacity() > 0);
            }
        };
    }

# endif

Your Answer

 
discard

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Browse other questions tagged or ask your own question.