105 lines
2.7 KiB
C++
105 lines
2.7 KiB
C++
#pragma once
|
|
#include <algorithm>
|
|
#include <cassert>
|
|
#include <iostream>
|
|
|
|
template <class T>
|
|
class Vector {
|
|
public:
|
|
// Constructor
|
|
Vector(unsigned int capacity = 10)
|
|
: capacity(capacity), element_count(0), data(new T[capacity]) {
|
|
std::cout << "Vector created" << std::endl;
|
|
}
|
|
|
|
// Copy Constructor
|
|
Vector(const Vector &other)
|
|
: capacity(other.capacity), element_count(other.element_count),
|
|
data(new T[capacity]) {
|
|
// `std::copy` is used because it is more flexible than `std::memcpy`,
|
|
// and the compiler will replace it with `memcpy` anyway if appropriate,
|
|
// so there is no performance loss.
|
|
std::copy(other.data, other.data + element_count, data);
|
|
}
|
|
|
|
// Move Constructor using the copy-and-swap-idiom
|
|
Vector(Vector &&other) : data(new T[capacity]) {
|
|
swap(*this, other);
|
|
}
|
|
|
|
// Copy Assignment Operator using the copy-and-swap-idiom
|
|
// Since this takes a value rather than a const reference due to
|
|
// copy-and-swap, this is also the Move Assignment Operator
|
|
Vector &operator=(Vector other) {
|
|
swap(*this, other);
|
|
|
|
return *this;
|
|
}
|
|
|
|
// Destructor
|
|
~Vector() {
|
|
delete[] data;
|
|
|
|
std::cout << "Vector deleted" << std::endl;
|
|
}
|
|
|
|
// Bracket Operator
|
|
T &operator[](unsigned int position) const {
|
|
return at(position);
|
|
}
|
|
|
|
// Swap function for the copy-and-swap idiom.
|
|
// See also:
|
|
// https://stackoverflow.com/questions/3279543/what-is-the-copy-and-swap-idiom
|
|
// The `friend` keyword is used so it is found through ADL.
|
|
friend void swap(Vector &first, Vector &second) {
|
|
// Enable ADL (good practice)
|
|
using std::swap;
|
|
|
|
swap(first.capacity, second.capacity);
|
|
swap(first.element_count, second.element_count);
|
|
swap(first.data, second.data);
|
|
}
|
|
|
|
void push_back(const T &element) {
|
|
if (element_count >= capacity) {
|
|
// TODO: Increase capacity!
|
|
}
|
|
|
|
// Use placement new to directly use pre-allocated memory
|
|
new (data + element_count) T(element);
|
|
element_count++;
|
|
}
|
|
|
|
void erase(unsigned int position) {
|
|
assert(position < element_count);
|
|
|
|
std::copy_backward(data + position + 1, data + element_count,
|
|
data + element_count - 1);
|
|
|
|
element_count--;
|
|
}
|
|
|
|
unsigned int size() const {
|
|
return element_count;
|
|
}
|
|
|
|
unsigned int length() const {
|
|
return capacity;
|
|
}
|
|
|
|
T &at(unsigned int position) const {
|
|
assert(position < element_count);
|
|
return data[position];
|
|
}
|
|
|
|
void reserve(unsigned int);
|
|
|
|
void resize(unsigned int);
|
|
|
|
private:
|
|
T *data;
|
|
unsigned int element_count;
|
|
unsigned int capacity;
|
|
};
|