#include <iostream>
#include <algorithm>
#include <fstream>
#include <memory>
#include <iterator>
#include <utility>
using std::cout;
using std::endl;
using std::allocator;
using std::sort;
using std::move;
using std::ostream;
using std::initializer_list;
using std::reverse;
using std::remove;
class Point
{
private:
int x;
int y;
public:
Point() : x(0), y(0){}
Point(int x1) : x(x1), y(0){}
Point(int x1, int y1) : x(x1), y(y1){}
Point(const Point& p) : x(p.x), y(p.y){}
~Point(){}
Point& operator=(const Point& other)
{
this->x = other.x;
this->y = other.y;
return *this;
}
Point& operator=(Point&& other)
{
this->x = move(other.x);
this->y = move(other.y);
return *this;
}
friend ostream& operator << (ostream & out, Point p)
{
out << "(" << p.x << ", " << p.y << ")";
return out;
}
bool operator == (Point p)
{
return (x == p.x && y == p.y);
}
bool operator < (Point p)
{
return (x*x + y*y < p.x*p.x + p.y*p.y);
}
};
template <class T>
class Vector
{
private:
T* ptr;
size_t size;
size_t capacity;
std::allocator<T> a1;
public:
Vector() : size(0), capacity(0), ptr(nullptr){}
Vector(size_t size) : size(size), capacity(size * 2)
{
ptr = a1.allocate(capacity);
for (size_t i = 0; i < size; i++)
{
try
{
a1.construct(ptr + i, T());
}
catch (...)
{
clean();
throw;
}
}
}
Vector(size_t size, T& value) : size(size), capacity(size * 2)
{
ptr = a1.allocate(capacity);
for (size_t i = 0; i < size; i++)
{
try
{
a1.construct(ptr + i, value);
}
catch (...)
{
clean();
throw;
}
}
}
Vector(const Vector& v) : size(v.size), capacity(v.capacity)
{
this->ptr = a1.allocate(capacity);
for (size_t i = 0; i < size; i++)
{
try
{
a1.construct(ptr + i, v.ptr[i]);
}
catch (...)
{
clean();
throw;
}
}
}
Vector(initializer_list<T> l)
{
size = l.size();
ptr = a1.allocate(size * 2);
capacity = size * 2;
size_t index = 0;
for (const auto& item : l)
{
a1.construct(ptr + index, item);
index++;
}
}
~Vector()
{
for (size_t i = 0; i < size; i++)
{
a1.destroy(ptr + i);
}
a1.deallocate(ptr, capacity);
}
void print()
{
for (size_t i = 0; i < size; i++)
{
cout << ptr[i] << "; ";
}
cout << endl;
}
void clean()
{
for (size_t i = 0; i < size; i++)
{
a1.destroy(ptr + i);
}
size = 0;
}
Vector& operator=(const Vector& other)
{
for (size_t i = 0; i < size; i++)
{
a1.destroy(ptr + i);
}
a1.deallocate(ptr, capacity);
this->size = other.size;
this->capacity = other.capacity;
this->ptr = a1.allocate(capacity);
for (size_t i = 0; i < size; i++)
{
a1.construct(ptr + i, other.ptr[i]);
}
return *this;
}
Vector& operator=(Vector&& other)
{
this->size = move(other.size);
this->capacity = move(other.capacity);
ptr = other.ptr;
other.size = 0;
other.capacity = 0;
other.ptr = nullptr;
return *this;
}
T& operator [] (size_t index)
{
if (index < 0 || index >= size)
throw std::out_of_range("Error");
return ptr[index];
}
const T& operator [] (size_t index) const
{
if (index < 0 || index >= size)
throw std::out_of_range("Error");
return ptr[index];
}
void push_back(T value)
{
if (size < capacity)
{
a1.construct(ptr + size, value);
size++;
}
else
{
capacity = size * 2;
T* temp_ptr = a1.allocate(capacity);
for (size_t i = 0; i < size; i++)
{
a1.construct(temp_ptr + i, ptr[i]);
}
for (size_t i = 0; i < size; i++)
{
a1.destroy(ptr + i);
}
a1.deallocate(ptr, size);
a1.construct(temp_ptr + size, value);
size++;
ptr = temp_ptr;
}
}
void pop_back()
{
if (size == 0)
throw std::out_of_range("Error");
a1.destroy(ptr + size - 1);
size--;
}
void resize(size_t new_size, T value = T())
{
if (size >= new_size)
{
for (size_t i = new_size; i < size; i++)
{
this->pop_back();
}
}
else
{
for (size_t i = size; i < new_size; i++)
{
this->push_back(value);
}
}
}
T* begin()
{
return ptr;
}
T* end()
{
return ptr + size;
}
void insert(T* p, T value)
{
if (p > this->end() || p < this->begin())
throw std::out_of_range("Error");
size_t index = 0, index_1 = 0;
for (T* i = this->begin(); i < this->end(); i++)
{
if (i < p)
{
index++;
index_1 = index;
}
else
{
index_1++;
}
}
if (size == capacity)
{
capacity *= 2;
}
size++;
T* temp_ptr = a1.allocate(capacity);
for (size_t i = 0; i < index; i++)
{
a1.construct(temp_ptr + i, ptr[i]);
}
a1.construct(temp_ptr + index, value);
index++;
for (size_t i = index; i < size; i++)
{
a1.construct(temp_ptr + i, ptr[i - 1]);
}
for (size_t i = 0; i < size - 1; i++)
{
a1.destroy(ptr + i);
}
a1.deallocate(ptr, size - 1);
ptr = temp_ptr;
}
void insert(T* p, T* first, T* last)
{
if (p > this->end() || p < this->begin())
throw std::out_of_range("Error");
if (first > last)
throw std::out_of_range("Error");
size_t index = 0, index_1 = 0;
for (T* i = this->begin(); i < this->end(); i++)
{
if (i < p)
{
index++;
index_1 = index;
}
else
{
index_1++;
}
}
capacity = 10000;
T* temp_ptr = a1.allocate(capacity);
for (size_t i = 0; i < index; i++)
{
a1.construct(temp_ptr + i, ptr[i]);
}
size_t index_2 = index;
for (T* i = first; i < last; i++)
{
a1.construct(temp_ptr + index_2, *i);
index_2++;
}
for (size_t i = index; i < size; i++)
{
a1.construct(temp_ptr + index_2, ptr[i]);
index_2++;
}
for (size_t i = 0; i < size; i++)
{
a1.destroy(ptr + i);
}
a1.deallocate(ptr, size);
size = index_2;
ptr = temp_ptr;
}
void erase(T*p)
{
if (p > this->end() || p < this->begin())
throw std::out_of_range("Error");
size_t index = 0, index_1 = 0;
for (T* i = this->begin(); i < this->end(); i++)
{
if (i < p)
{
index++;
index_1 = index;
}
else
{
index_1++;
}
}
index++;
for (size_t i = index; i < size; i++)
{
ptr[i - 1] = ptr[i];
}
a1.destroy(ptr + size - 1);
size--;
}
void erase(T* first, T* last)
{
if (first > this->end() || first < this->begin())
throw std::out_of_range("Error");
if (last > this->end() || last < this->begin())
throw std::out_of_range("Error");
if (first > last)
throw std::out_of_range("Error");
size_t index = 0, index_1 = 0, index_2 = 0;
for (T* i = this->begin(); i < this->end(); i++)
{
if (i < first)
{
index++;
index_1 = index;
}
else
{
if (i > last)
{
index_1++;
}
else
{
index_1++;
index_2 = index_1;
}
}
}
size_t temp = index;
for (size_t i = index_2; i < size; i++)
{
ptr[temp] = ptr[i];
temp++;
}
for (size_t i = temp; i < size; i++)
{
a1.destroy(ptr + i);
}
size -= (index_2 - index);
}
size_t Size() const
{
return size;
}
template<class... T1>
void emplace_back(T1&&... args)
{
if (size < capacity)
{
std::allocator_traits<std::allocator<T>>::construct(a1, ptr + size, std::forward<T1>(args)...);
size++;
}
else
{
capacity = size * 2;
T* temp_ptr = a1.allocate(capacity);
for (size_t i = 0; i < size; i++)
{
a1.construct(temp_ptr + i, ptr[i]);
}
for (size_t i = 0; i < size; i++)
{
a1.destroy(ptr + i);
}
a1.deallocate(ptr, size);
std::allocator_traits<std::allocator<T>>::construct(a1, temp_ptr + size, std::forward<T1>(args)...);
size++;
ptr = temp_ptr;
}
}
};
int main()
{
Vector <Point> v2(5);
Vector <Point> v3(7, Point(1, 1));
Vector <Point> v4 = v3;
Vector <Point> v5;
cout << "v2(5), v2 = ";
v2.print();
cout << "v3(7,2), v3 = ";
v3.print();
cout << "v4=v3, v4 = ";
v4.print();
cout << "v5(), v5 = ";
v5.print();
v4 = move(v2);
cout << "v4 = move(v2)" << endl << "v4 = ";
v4.print();
v4 = v5;
cout << "v4 = v5" << endl << "v4 = ";
v4.print();
cout << "v3[1] = " << v3[1] << endl;
Point a(1, 1);
cout << "a = " << a << endl;
Vector <Point> v1(3, Point(2, 2));
cout << "v1 = ";
v1.print();
cout << "v1.pop_back()" << endl;
v1.pop_back();
cout << "v1 = ";
v1.print();
cout << "v1.push_back(Point(1,1))" << endl;
v1.push_back(Point(1, 1));
cout << "v1 = ";
v1.print();
cout << "v1.push_back(Point(3,3))" << endl;
v1.push_back(Point(3, 3));
cout << "v1 = ";
v1.print();
cout << "reverse(v1.begin(), v1.end() - 1)" << endl;
reverse(v1.begin(), v1.end() - 1);
cout << "v1 = ";
v1.print();
cout << "v1.resize(v1.size_of_vector() - 1)" << endl;
v1.resize(v1.Size() - 1);
cout << "v1 = ";
v1.print();
cout << "v1.resize(v1.size_of_vector() + 3)" << endl;
v1.resize(v1.Size() + 3);
cout << "v1 = ";
v1.print();
cout << "v1.insert(v1.begin()+2, a)" << endl;
v1.insert(v1.begin() + 2, a);
cout << "v1 = ";
v1.print();
Point myarray[2] = { { 3, 4 }, { 5, 6 } };
cout << "myarray[2] = {{ 3, 4 }, { 5, 6 } }" << endl;
cout << "v1.insert(v1.begin() + 1, myarray, myarray+2)" << endl;
v1.insert(v1.begin() + 1, myarray, myarray + 2);
cout << "v1 = ";
v1.print();
cout << "v1.erase(v1.begin() + 1)" << endl;
v1.erase(v1.begin() + 1);
cout << "v1 = ";
v1.print();
cout << "v1.erase(v1.end()-2, v1.end())" << endl;
v1.erase(v1.end() - 2, v1.end());
cout << "v1 = ";
v1.print();
cout << "v1.erase(remove(v1.begin(), v1.end(), Point{ 2, 2 }), v1.end())" << endl;
v1.erase(remove(v1.begin(), v1.end(), Point{ 2, 2 }), v1.end());
cout << "v1 = ";
v1.print();
cout << "sort(v1.begin(), v1.end())" << endl;
sort(v1.begin(), v1.end());
cout << "v1 = ";
v1.print();
Vector<Point> v = { { 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 } };
cout << "Vector<Point> v = { { 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 } }" << endl;
cout << "v = ";
v.print();
v.emplace_back(10, 10);
cout << "v.emplace_back(10, 10)" << endl;
cout << "v = ";
v.print();
return 0;
}