我如何在 C++ 中实现 vector 的迭代器插入(const_iterator 位置,InputIterator 首先,InputIterator 最后)?

How can i Implement iterator insert (const_iterator position, InputIterator first, InputIterator last) of vector in c++?

你好,我正在尝试用 C++ 制作向量 class。我想制作下面的一个。你能告诉我怎么做吗? https://www.cplusplus.com/reference/vector/vector/insert/ std::vector::insert 范围 (3)
模板 迭代器插入(const_iterator位置,InputIterator在前,InputIterator在后);

这是我的代码。如果有错误请告诉我。

#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;
    }

那个特定的重载是一件棘手的事情,因为它要求您接受最通用的迭代器类型,但人们会期望其他迭代器类型具有更好的性能。

天真的方法是从 first 循环到 lastinsert 遍历每个元素。

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

然而,这可能需要多次重新分配。你 必须 使用 InputIterator 来做到这一点,因为它们不一定支持多次传递,但保留足够的 [=36] 真的很有用=]提前。

您可以有一个仅适用于 ForwardIterators 的额外重载,它支持多次传递,因此您可以知道需要多少容量。

对于 C++20,这可以通过使用受限模板类型进行重载来完成

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);
    }
}

在 C++20 之前,您可以将 public insert 分派到两个私有实现之一

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);
    }
}