This repository has been archived by the owner on Jun 16, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathvector.h
104 lines (92 loc) · 2.91 KB
/
vector.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
#ifndef EPC_VECTOR_H
#define EPC_VECTOR_H
#include <cstdlib>
#include <algorithm>
#include <memory>
namespace epc {
template <typename T>
class vector {
size_t m_Size, m_Capacity;
unsigned char * m_Buffer;
public:
vector() noexcept
: m_Size(0), m_Capacity(0), m_Buffer (nullptr) {}
vector(const vector& other) : m_Size(other.m_Size),
m_Capacity(other.m_Capacity), m_Buffer(nullptr) {
if ( !m_Capacity ) return;
m_Buffer = new unsigned char [m_Capacity * sizeof(T)]; // might throw, no cleanup
try {
std::uninitialized_copy_n ( other.data(), other.m_Size, reinterpret_cast<T*>(m_Buffer) );
}
catch (...) {
delete [] m_Buffer;
throw;
}
}
vector& operator=(const vector& other) {
if (this != &other) {
vector tmp = other; // might throw, no cleanup
swap(tmp);
}
return *this;
}
~vector() {
std::destroy ( data(), data() + m_Size ); // destructors won't throw
delete [] m_Buffer;
}
T* data() {
return reinterpret_cast<T*> ( m_Buffer );
}
const T* data() const {
return reinterpret_cast<T*> ( m_Buffer );
}
T& operator[](size_t ix) {
return data()[ix];
}
const T& operator[](size_t ix) const {
return data()[ix];
}
void push_back(const T& elem) {
if (m_Size == m_Capacity)
reserve(m_Capacity ? m_Capacity * 2 : 1); // might throw, no cleanup
new (data() + m_Size) T ( elem ); // might throw
++m_Size;
}
void pop_back() {
std::destroy_at ( data() + m_Size - 1 ); // call destructor
--m_Size;
}
void clear() {
std::destroy ( data(), data() + m_Size ); // call destructors
m_Size = 0;
}
void reserve(size_t newCapacity) {
if (newCapacity <= m_Capacity)
return;
unsigned char * newBuffer = new unsigned char [newCapacity * sizeof(T)]; // might throw, no cleanup
try {
std::uninitialized_copy_n ( data(), m_Size, reinterpret_cast<T*>(newBuffer) );
}
catch (...) {
delete [] newBuffer;
throw;
}
std::destroy ( data(), data() + m_Size ); // won't throw
delete [] m_Buffer; // won't throw
m_Buffer = newBuffer;
m_Capacity = newCapacity;
}
size_t capacity() const {
return m_Capacity;
}
size_t size() const {
return m_Size;
}
void swap(vector& other) noexcept {
std::swap (m_Buffer, other.m_Buffer);
std::swap (m_Size, other.m_Size);
std::swap (m_Capacity, other.m_Capacity);
}
};
}
#endif