48 using const_pointer =
const T*;
50 using const_reference =
const T&;
51 using size_type = size_t;
52 using difference_type = ptrdiff_t;
54 using const_iterator =
const T*;
55 using reverse_iterator = std::reverse_iterator<iterator>;
56 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
57 using allocator_type = std::allocator<T>;
60 CorVector() noexcept : data_(
nullptr), size_(0), allocator_() {}
72 template<
typename InputIt,
73 typename std::enable_if<!std::is_integral<InputIt>::value,
int>::type = 0>
75 size_type count = std::distance(first, last);
77 for (; first != last; ++first) {
88 for (size_type i = 0; i < other.
size_; ++i) {
89 push_back(other.
data_[i]);
95 this->data_ = other.
data_;
96 this->size_ = other.
size_;
98 other.
data_ =
nullptr;
104 if (end_of_storage()) {
106 allocator().deallocate(data_, end_of_storage() - data_);
112 if (
this != &other) {
120 if (
this != &other) {
122 if (end_of_storage()) {
123 allocator().deallocate(data_, end_of_storage() - data_);
128 other.
data_ =
nullptr;
135 CorVector& operator=(std::initializer_list<T> init) {
142 reference operator[](size_type pos) {
146 const_reference operator[](size_type pos)
const {
150 reference at(size_type pos) {
152 throw std::out_of_range(
"CorVector::at: index out of range");
157 const_reference at(size_type pos)
const {
159 throw std::out_of_range(
"CorVector::at: index out of range");
168 const_reference front()
const {
173 return data_[size_ - 1];
176 const_reference back()
const {
177 return data_[size_ - 1];
184 const T* data()
const noexcept {
189 iterator begin()
noexcept {
193 const_iterator begin()
const noexcept {
197 const_iterator cbegin()
const noexcept {
201 iterator end()
noexcept {
202 return data_ + size();
205 const_iterator end()
const noexcept {
206 return data_ + size();
209 const_iterator cend()
const noexcept {
210 return data_ + size();
213 reverse_iterator rbegin()
noexcept {
214 return reverse_iterator(end());
217 const_reverse_iterator rbegin()
const noexcept {
218 return const_reverse_iterator(end());
221 const_reverse_iterator crbegin()
const noexcept {
222 return const_reverse_iterator(cend());
225 reverse_iterator rend()
noexcept {
226 return reverse_iterator(begin());
229 const_reverse_iterator rend()
const noexcept {
230 return const_reverse_iterator(begin());
233 const_reverse_iterator crend()
const noexcept {
234 return const_reverse_iterator(cbegin());
238 bool empty()
const noexcept {
242 size_type size()
const noexcept {
246 size_type max_size()
const noexcept {
247 return allocator().max_size();
250 size_type capacity()
const noexcept {
251 return end_of_storage() ? (end_of_storage() - data_) : 0;
254 void reserve(size_type new_cap) {
255 if (new_cap > capacity()) {
257 allocate_and_copy(new_cap);
261 void shrink_to_fit() {
262 if (capacity() > size()) {
263 allocate_and_copy(size());
268 void clear()
noexcept {
269 if (end_of_storage()) {
270 for (size_type i = 0; i < size(); ++i) {
271 allocator().destroy(data_ + i);
277 iterator insert(const_iterator pos,
const T& value) {
278 difference_type offset = pos - cbegin();
279 if (size_ >= capacity()) {
282 std::move_backward(data_ + offset, data_ + size_, data_ + size_ + 1);
283 allocator().construct(data_ + offset, value);
285 return data_ + offset;
288 iterator insert(const_iterator pos,
T&& value) {
289 difference_type offset = pos - cbegin();
290 if (size_ >= capacity()) {
293 std::move_backward(data_ + offset, data_ + size_, data_ + size_ + 1);
294 allocator().construct(data_ + offset, std::move(value));
296 return data_ + offset;
299 iterator insert(const_iterator pos, size_type count,
const T& value) {
300 difference_type offset = pos - cbegin();
301 if (size_ + count > capacity()) {
302 reserve(size_ + count);
304 std::move_backward(data_ + offset, data_ + size_, data_ + size_ + count);
305 for (size_type i = 0; i < count; ++i) {
306 allocator().construct(data_ + offset + i, value);
309 return data_ + offset;
312 template<
typename InputIt,
313 typename std::enable_if<!std::is_integral<InputIt>::value,
int>::type = 0>
314 iterator insert(const_iterator pos, InputIt first, InputIt last) {
315 difference_type offset = pos - cbegin();
316 size_type count = std::distance(first, last);
317 if (size_ + count > capacity()) {
318 reserve(size_ + count);
320 std::move_backward(data_ + offset, data_ + size_, data_ + size_ + count);
321 T* cur = data_ + offset;
322 for (; first != last; ++first, ++cur) {
323 allocator().construct(cur, *first);
326 return data_ + offset;
329 iterator insert(const_iterator pos, std::initializer_list<T> init) {
330 return insert(pos, init.begin(), init.end());
333 iterator erase(const_iterator pos) {
334 difference_type offset = pos - cbegin();
335 std::move(data_ + offset + 1, data_ + size_, data_ + offset);
337 allocator().destroy(data_ + size_);
338 return data_ + offset;
341 iterator erase(const_iterator first, const_iterator last) {
342 difference_type start = first - cbegin();
343 difference_type count = last - first;
344 std::move(data_ + start + count, data_ + size_, data_ + start);
345 for (difference_type i = 0; i < count; ++i) {
346 allocator().destroy(data_ + size_ - i - 1);
349 return data_ + start;
352 void push_back(
const T& value) {
353 if (size_ >= capacity()) {
354 reserve(size_ == 0 ? 1 : size_ * 2);
356 allocator().construct(data_ + size_, value);
360 void push_back(
T&& value) {
361 if (size_ >= capacity()) {
362 reserve(size_ == 0 ? 1 : size_ * 2);
364 allocator().construct(data_ + size_, std::move(value));
371 allocator().destroy(data_ + size_);
374 void resize(size_type count) {
376 if (count > capacity()) {
379 for (size_type i = size_; i < count; ++i) {
380 allocator().construct(data_ + i);
382 }
else if (count < size_) {
383 for (size_type i = count; i < size_; ++i) {
384 allocator().destroy(data_ + i);
390 void resize(size_type count,
const T& value) {
392 if (count > capacity()) {
395 for (size_type i = size_; i < count; ++i) {
396 allocator().construct(data_ + i, value);
398 }
else if (count < size_) {
399 for (size_type i = count; i < size_; ++i) {
400 allocator().destroy(data_ + i);
407 std::swap(data_, other.
data_);
408 std::swap(size_, other.
size_);
414 return end_of_storage() ==
nullptr;
418 return end_of_storage() !=
nullptr;
424 allocator_.end_of_storage_ =
nullptr;
429 T* end_of_storage_{
nullptr};
431 allocator_type& allocator() noexcept{
434 const allocator_type& allocator() const noexcept{
437 T* end_of_storage() const noexcept {
438 return allocator_.end_of_storage_;
447 void allocate_and_copy(size_type new_cap) {
449 if (end_of_storage()) {
451 allocator().deallocate(data_, end_of_storage() - data_);
453 allocator_.end_of_storage_ =
nullptr;
458 T* new_data = allocator().allocate(new_cap);
459 size_type copy_size = (std::min)(size_, new_cap);
462 for (size_type i = 0; i < copy_size; ++i) {
463 allocator().construct(new_data + i, data_[i]);
467 if (end_of_storage()) {
469 allocator().deallocate(data_, end_of_storage() - data_);
473 allocator_.end_of_storage_ = data_ + new_cap;