16 #include <type_traits> 22 static_assert(std::is_trivially_destructible<T>::value &&
23 std::is_standard_layout<T>::value,
24 "this class should only use with trivially copyable class, " 26 "care about fundamental type");
29 using pointer = value_type *;
30 using const_pointer =
const value_type *;
31 using reference = value_type &;
32 using const_reference =
const value_type &;
33 using iterator = value_type *;
34 using const_iterator =
const value_type *;
35 using size_type = std::size_t;
36 using difference_type = std::ptrdiff_t;
37 using reverse_iterator = std::reverse_iterator<iterator>;
38 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
40 naivevector() noexcept : m_start(
nullptr), m_end(
nullptr), m_cap(
nullptr) {}
44 reserve(other.size());
45 for (
auto value : other) {
58 swap(m_start, __other.m_start);
59 swap(m_end, __other.m_end);
60 swap(m_cap, __other.m_cap);
64 iterator begin() noexcept {
return iterator(data()); }
66 const_iterator begin()
const noexcept {
return const_iterator(data()); }
68 iterator end() noexcept {
return iterator(m_end); }
70 const_iterator end()
const noexcept {
return const_iterator(m_end); }
72 reverse_iterator rbegin() noexcept {
return reverse_iterator(end()); }
74 const_reverse_iterator rbegin()
const noexcept {
75 return const_reverse_iterator(end());
78 reverse_iterator rend() noexcept {
return reverse_iterator(begin()); }
80 const_reverse_iterator rend()
const noexcept {
81 return const_reverse_iterator(begin());
84 const_iterator cbegin()
const noexcept {
return const_iterator(data()); }
86 const_iterator cend()
const noexcept {
return const_iterator(m_end); }
88 const_reverse_iterator crbegin()
const noexcept {
89 return const_reverse_iterator(end());
92 const_reverse_iterator crend()
const noexcept {
93 return const_reverse_iterator(begin());
97 size_type size()
const noexcept {
return size_type(m_end - m_start); }
99 constexpr size_type max_size()
const noexcept {
100 return size_type(-1) /
sizeof(value_type);
103 void clear() { resize(0); }
105 void resize(size_type new_size) {
106 if (new_size > size()) {
107 auto old_size = size();
108 auto cap = capacity();
109 while (new_size > cap) {
110 cap = cap ? (2 * cap) : 32;
114 m_end = m_start + new_size;
115 if constexpr (!std::is_trivial_v<value_type>) {
116 for (
auto *p = m_start + old_size; p != m_end; p++) {
117 new (p) value_type();
120 std::memset(m_start + old_size, 0,
121 sizeof(value_type) * (new_size - old_size));
124 m_end = m_start + new_size;
128 void shrink_to_fit() {
130 _realloc_array(size_type(reinterpret_cast<char *>(m_end) -
131 reinterpret_cast<char *>(m_start)));
135 void reserve(size_type new_size) {
136 if (new_size > max_size()) {
137 throw std::length_error(
"larger than max_size");
140 if (new_size > capacity()) {
141 _realloc_array(new_size *
sizeof(value_type));
145 size_type capacity()
const noexcept {
return size_type(m_cap - m_start); }
147 bool empty()
const noexcept {
return size() == 0; }
150 reference operator[](size_type __n) noexcept {
return m_start[__n]; }
152 const_reference operator[](size_type __n)
const noexcept {
156 reference at(size_type __n) {
158 throw std::out_of_range(
"out_of_range");
163 const_reference at(size_type __n)
const {
165 throw std::out_of_range(
"out_of_range");
170 reference front() noexcept {
return *begin(); }
172 const_reference front()
const noexcept {
return *cbegin(); }
174 reference back() noexcept {
return size() ? *(end() - 1) : *end(); }
176 const_reference back()
const noexcept {
177 return size() ? *(cend() - 1) : *cend();
180 pointer data() noexcept {
return m_start; }
182 const_pointer data()
const noexcept {
return m_start; }
184 void push_back(
const value_type &__x) { emplace_back(__x); }
186 void push_back(value_type &&__x) { emplace_back(std::move(__x)); }
188 template <
typename... _Args>
189 void emplace_back(_Args &&...__args) {
190 if (m_end == m_cap) {
191 reserve(capacity() ? (2 * capacity()) : 32);
193 new (m_end) value_type(std::forward<_Args>(__args)...);
197 void pop_back() { m_end--; }
200 void _realloc_array(size_type bytes) {
203 m_start = m_end = m_cap =
nullptr;
205 auto old_bytes = size_type(reinterpret_cast<char *>(m_end) -
206 reinterpret_cast<char *>(m_start));
208 reinterpret_cast<pointer
>(std::realloc(m_start, bytes));
211 m_cap =
reinterpret_cast<pointer
>(
212 reinterpret_cast<char *
>(new_start) + bytes);
213 m_end =
reinterpret_cast<pointer
>(
214 reinterpret_cast<char *
>(new_start) + old_bytes);
216 throw std::bad_alloc();
226 template <
typename T>
232 #endif // NAIVEVECTOR_H