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
, insert
ing 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);
}
}