Home > database >  How can i Implement iterator insert (const_iterator position, InputIterator first, InputIterator las
How can i Implement iterator insert (const_iterator position, InputIterator first, InputIterator las

Time:04-29

Hello I am trying to make vector class in C . and I want to make below one. Can you hint me how to make? https://www.cplusplus.com/reference/vector/vector/insert/ std::vector::insert range (3)
template iterator insert (const_iterator position, InputIterator first, InputIterator last);

Here is my code. and plz let me know if there are mistakes.

#ifndef VECTOR_H
#define VECTOR_H

#include <algorithm>
#include <iostream>
#include <stdexcept>
#include "dsexceptions.h"

template <typename Object>
class Vector
{
public:
    explicit Vector(int initSize = 0)
        : theSize(initSize), theCapacity(initSize   SPARE_CAPACITY),objects(nullptr)
        
    {
        (objects = new Object[theCapacity]);
        for(int k=0; k<theSize;   k)
        {
            objects[k] = 0;
        }
    }
    Vector(const Vector& rhs)
        : theSize(rhs.theSize), theCapacity( rhs.theCapacity ), objects( nullptr)
    {
        objects = new Object[theCapacity];
        for (int k = 0; k < theSize;   k)
            objects[k] = rhs.objects[k];
    }

    Vector& operator= (const Vector& rhs)
    {
        Vector copy = rhs;
        std::swap(*this, copy);
        return *this;
    }

    ~Vector()
    {
        delete[] objects;
    }

    Vector(Vector&& rhs)
        : theSize{ rhs.theSize }, theCapacity{ rhs.theCapacity }, objects{ rhs.objects }
    {
        rhs.objects = nullptr;
        rhs.theSize = 0;
        rhs.theCapacity = 0;
    }

    Vector& operator= (Vector&& rhs)
    {
        std::swap(theSize, rhs.theSize);
        std::swap(theCapacity, rhs.theCapacity);
        std::swap(objects, rhs.objects);

        return *this;
    }

    bool empty() const
    {
        return size() == 0;
    }
    int size() const
    {
        return theSize;
    }
    int capacity() const
    {
        return theCapacity;
    }

    Object& operator[](int index)
    {
#ifndef NO_CHECK
        if (index < 0 || index >= size())
            throw ArrayIndexOutOfBoundsException{ };
#endif
        return objects[index];
    }

    const Object& operator[](int index) const
    {
#ifndef NO_CHECK
        if (index < 0 || index >= size())
            throw ArrayIndexOutOfBoundsException{ };
#endif
        return objects[index];
    }

    void resize(int newSize)
    {
        if (newSize > theCapacity)
            reserve(newSize * 2);
        theSize = newSize;
    }

    void reserve(int newCapacity)
    {
        if (newCapacity < theSize)
            return;

        Object* newArray = new Object[newCapacity];
        for (int k = 0; k < theSize;   k)
            newArray[k] = std::move(objects[k]);

        theCapacity = newCapacity;
        std::swap(objects, newArray);
        delete[] newArray;
    }

    // Stacky stuff
    void push_back(const Object& x)
    {
        if (theSize == theCapacity)
            reserve(2 * theCapacity   1);
        objects[theSize  ] = x;
    }
    // Stacky stuff
    void push_back(Object&& x)
    {
        if (theSize == theCapacity)
            reserve(2 * theCapacity   1);
        objects[theSize  ] = std::move(x);
    }

    void pop_back()
    {
        if (empty())
            throw UnderflowException{ };
        --theSize;
    }

    const Object& back() const
    {
        if (empty())
            throw UnderflowException{ };
        return objects[theSize - 1];
    }

    // Iterator stuff: not bounds checked
    typedef Object* iterator;
    typedef const Object* const_iterator;

    iterator begin()
    {
        return &objects[0];
    }
    const_iterator begin() const
    {
        return &objects[0];
    }
    iterator end()
    {
        return &objects[size()];
    }
    const_iterator end() const
    {
        return &objects[size()];
    }

    static const int SPARE_CAPACITY = 2;

    /*************************************************************************/
    /*************************************************************************/
 
    iterator insert(const_iterator position, const Object& val)
    {
        if (theSize == theCapacity)
        {
            reserve(2 * theCapacity   1);
        }
        int index = position - objects;
        for (int i = theSize - 1; i >= index; --i)
            objects[i   1] = objects[i];
        objects[index] = val;
        theSize  ;

        return &objects;
        
    }

    iterator insert(const_iterator position, Object&& val)
    {
        if (theSize == theCapacity)
        {
            reserve(2 * theCapacity   1);
        }
        int index = position - objects;
        for (int i = theSize-1; i>=index; --i)
            objects[i 1] = objects[i];
        objects[index] = std::move(val);
        theSize  ;

        return objects;
    }

CodePudding user response:

That particular overload is a tricky thing, because it requires you to accept the most general kind of iterator, but people will expect better performance with other iterator types.

The naive way is to loop from first to last, inserting each element.

template<typename InputIterator>
void insert(const_iterator position, InputIterator first, InputIterator last) {
    for (; first != last;   first) {
         position = insert(position, *first);
    }
}

However this may require multiple reallocations. You must do that with InputIterators, because they don't necessarily support multiple passes, but it would be really useful to reserve enough space ahead of time.

You can have an extra overload that only applies to ForwardIterators, which do support multiple passes, so you can know how much capacity is needed.

With C 20 this can be done by having overloads with constrained template types

template<std::input_iterator InputIterator>
void insert(const_iterator position, InputIterator first, InputIterator last) {
    for (; first != last;   first) {
         position = insert(position, *first);
    }
}

template<std::forward_iterator ForwardIterator>
void insert(const_iterator position, ForwardIterator first, ForwardIterator last) {
    auto requiredCapacity = theSize   std::distance(first, last);
    if (requiredCapacity > theCapacity) {
        auto index = std::distance(objects, position);
        reserve(requiredCapacity);
        position = objects   index;
    }
    for (; first != last;   first) {
         position = insert(position, *first);
    }
}

Prior to C 20 you can have the public insert dispatch to one of two private implementations

template<typename InputIterator>
void insert(const_iterator position, InputIterator first, InputIterator last) {
    insert_impl(position, first, last, std::iterator_traits<InputIterator>::iterator_category{});
}

template<typename InputIterator>
void insert_impl(const_iterator position, InputIterator first, InputIterator last, std::input_iterator_tag) {
    for (; first != last;   first) {
         position = insert(position, *first);
    }
}

template<typename ForwardIterator>
void insert_impl(const_iterator position, ForwardIterator first, ForwardIterator last, std::forward_iterator_tag) {
    auto requiredCapacity = theSize   std::distance(first, last);
    if (requiredCapacity > theCapacity) {
        auto index = std::distance(objects, position);
        reserve(requiredCapacity);
        position = objects   index;
    }
    for (; first != last;   first) {
         position = insert(position, *first);
    }
}
  • Related