Piszę sobie dla ćwiczeń implementację wektora z zastosowaniem feature'ów z nowoczesnego c++ - move semantics, initializer lists etc.
Proszę o opinie, co byście tu zmienili, dodali, wywalili, żeby było to jeszcze bardziej zgodne z nowoczesnym C++.
template<typename T>
class Vector
{
private:
T* data;
size_t size;
size_t capacity;
private:
class Iterator
{
using iterator_tag = std::forward_iterator_tag;
using difference_type = std::ptrdiff_t;
using value_type = T;
using pointer = T*;
using reference = T&;
private:
pointer ptr;
public:
Iterator(pointer ptr)
:ptr(ptr){}
reference operator*() { return *this->ptr; }
pointer operator->() { return this->ptr; }
Iterator& operator++() { this->ptr++; return *this;}
Iterator operator++(int) { Iterator tmp = *this; this->ptr++; return tmp; }
friend bool operator==(Iterator& a, Iterator& b) { return (a.ptr == b.ptr); }
friend bool operator!=(Iterator& a, Iterator& b) { return (a.ptr != b.ptr); }
};
private:
void re_alloc(size_t new_capacity)
{
T* new_data = new T[new_capacity];
for(size_t i = 0; i < this->size; i++)
new_data[i] = this->data[i];
delete[] this->data;
this->data = new_data;
}
public:
Vector()
:data(new T[0]), size(0), capacity(0){}
Vector(size_t size)
:data(new T[size]), size(0), capacity(size){}
Vector(size_t size, const T& item)
:data(new T[size]), size(size), capacity(size)
{
for(size_t i = 0; i < this->size; i++)
this->data[i] = item;
}
Vector(const Vector<T>& vec)
:size(vec.size), capacity(vec.capacity)
{
this->data = new T[this->capacity];
for(size_t i = 0; i < this->size; i++)
this->data[i] = vec[i];
}
Vector(Vector<T>&& rhs)
:size(rhs.size), capacity(rhs.capacity), data(rhs.data)
{
rhs.data = nullptr;
}
Vector(std::initializer_list<T> list)
:size(0), capacity(list.size() * 2)
{
this->data = new T[this->capacity];
for(auto& item : list)
this->push_back(item);
}
Vector<T>& operator=(const Vector<T>& vec)
{
delete[] this->data;
this->size = vec.size;
this->capacity = vec.capacity;
this->data = new T[this->capacity];
for(size_t i = 0; i < this->size; i++)
this->data[i] = vec[i];
return *this;
}
~Vector() { delete[] this->data; }
T& operator[](size_t index) const { return this->data[index]; }
void push_back(const T& item)
{
if(this->size == this->capacity)
{
size_t new_cap = this->capacity;
if(this->capacity == 0)
new_cap = ++this->capacity;
else
new_cap *= 2;
this->re_alloc(new_cap);
this->capacity = new_cap;
}
this->data[this->size] = item;
this->size++;
}
void pop_back()
{
if(this->size > 0)
{
this->data[this->size - 1].~T();
this->size--;
}
}
void clear()
{
for(size_t i = 0; i < this->size; i++)
this->data[i].~T();
this->size = 0;
}
Iterator begin() { return Iterator(&this->data[0]); }
Iterator end() { return Iterator(&this->data[this->size]); }
size_t get_size() const { return this->size; }
size_t get_capacity() const { return this->capacity; }
};
template<typename T>
std::ostream& operator<<(std::ostream& ostr, const Vector<T>& vec)
{
for(size_t i = 0; i < vec.get_size(); i++)
ostr << vec[i] << " ";
ostr << std::endl;
return ostr;
}