Website Summary Files Commits Branches @commit @diff @stats
path: root / Seminar03 / src / dynamic-array
diff options
context:
space:
mode:
Commitd866bd4b9fb6d586d0fbe44af9ece7d105b75a0c (patch)
Author
 Stoycho Kyosev <stoycho.kk@gmail.com>
2024-11-12 16:22:20 -0500
Committer
 Stoycho Kyosev <stoycho.kk@gmail.com>
2024-11-12 16:22:20 -0500
Filesd1be21cbeb96894c25f9255fc1fd0787d89dc78f /Seminar03/src/dynamic-array
Data-structures-and-algorithms-d866bd4b9fb6d586d0fbe44af9ece7d105b75a0c.tar
Data-structures-and-algorithms-d866bd4b9fb6d586d0fbe44af9ece7d105b75a0c.tar.gz
Data-structures-and-algorithms-d866bd4b9fb6d586d0fbe44af9ece7d105b75a0c.zip
Parent5a477ea2fc4926165113b73754d856f6b3d7cfba (diff)
Integrate the use of std::allocator in dynamic array
diff --git a/Seminar03/src/dynamic-array/tests.cpp b/Seminar03/src/dynamic-array/tests.cpp
index 0d30813..cb64d5f 100644
--- a/Seminar03/src/dynamic-array/tests.cpp
+++ b/Seminar03/src/dynamic-array/tests.cpp
@@ -1,7 +1,4 @@
-#define TEST_DIR_VECTOR_ALLOC "vector-allocator/vector.hpp"
-#define TEST_DIR_VECTOR "vector/vector.hpp"
-
-#include TEST_DIR_VECTOR
+#include "vector/vector.hpp"
#include <algorithm>
#include <cassert>
#include <chrono>
diff --git a/Seminar03/src/dynamic-array/vector-allocator/allocator.hpp b/Seminar03/src/dynamic-array/vector-allocator/allocator.hpp
deleted file mode 100644
index d38587e..0000000
--- a/Seminar03/src/dynamic-array/vector-allocator/allocator.hpp
+++ /dev/null
@@ -1,104 +0,0 @@
-#pragma once
-#include <stddef.h>
-#include <utility>
-
-template <class T>
-class allocator
-{
-public:
- T *allocate(size_t n) const;
- void deallocate(T *ptr, size_t n) const;
-
- template <class... Args>
- void construct(T *ptr, Args &&...args) const;
- void destroy(T *ptr) const;
-
- void copy_range(T* begin_destination, T* begin_source, T* end_source) const;
- void move_range(T *begin_destination, T *begin_source, T *end_source) const;
-
- template <class... Args>
- void construct_range(T *begin, T *end, Args &&...args) const;
- void destroy_range(T *begin, T *end) const;
-};
-
-// allocates uninitialized storage
-template <class T>
-T *allocator<T>::allocate(size_t n) const
-{
- if(n == 0)
- return nullptr;
-
- return static_cast<T *>(::operator new(n * sizeof(T)));
-}
-
-// Deallocates the storage referenced by the pointer ptr,
-// which must be a pointer obtained by an earlier call to allocate()
-template <class T>
-void allocator<T>::deallocate(T *ptr, size_t n) const
-{
- if (!n)
- return;
-
- ::operator delete(ptr, n * sizeof(T));
-}
-
-// destructs an object in allocated storage
-template <class T>
-void allocator<T>::destroy(T *ptr) const
-{
- ptr->~T();
-}
-
-template <class T>
-template <class... Args>
-void allocator<T>::construct(T *ptr, Args &&...args) const
-{
- ::new (ptr) T(std::forward<Args>(args)...);
-}
-
-// constructs an object in allocated storage
-template <class T>
-template <class... Args>
-void allocator<T>::construct_range(T *begin, T *end, Args &&...args) const
-{
- while (begin != end)
- {
- construct(begin, std::forward<Args>(args)...);
- ++begin;
- }
-}
-
-// calls destroy on a range.
-template <class T>
-void allocator<T>::destroy_range(T *begin, T *end) const
-{
- while (begin != end)
- {
- destroy(begin);
- ++begin;
- }
-}
-
-// calls construct on a range.
-template<class T>
-void allocator<T>::copy_range(T* begin_destination, T* begin_source, T* end_source) const
-{
- while(begin_source != end_source)
- {
- construct(begin_destination, *begin_source);
- ++begin_source;
- ++begin_destination;
- }
-}
-
-// calls construct using std::move on a range.
-template <class T>
-void allocator<T>::move_range(T *begin_destination, T *begin_source, T *end_source) const
-{
- while (begin_source != end_source)
- {
- construct(begin_destination, std::move(*begin_source));
- ++begin_source;
- ++begin_destination;
- }
-} \ No newline at end of file
diff --git a/Seminar03/src/dynamic-array/vector-allocator/vector.hpp b/Seminar03/src/dynamic-array/vector-allocator/vector.hpp
deleted file mode 100644
index cb98d31..0000000
--- a/Seminar03/src/dynamic-array/vector-allocator/vector.hpp
+++ /dev/null
@@ -1,395 +0,0 @@
-//! The allocator implementation is additional
-//! information and is not mandatory.
-
-#pragma once
-#include "../iterator/iterator.hpp"
-#include "allocator.hpp"
-
-namespace Constants
-{
-constexpr unsigned GROWTH_FACTOR = 2;
-}
-
-template <class T, class Allocator = allocator<T>>
-class vector
-{
- public:
- using iterator = vector_iterator<T>;
- using const_iterator = const_vector_iterator<T>;
- using reverse_iterator = reverse_vector_iterator<T>;
-
- vector() = default;
- explicit vector(size_t count);
- vector(size_t count, const T& initial);
-
- vector(const vector& other);
- vector& operator=(const vector& other);
-
- vector(vector&& oher);
- vector& operator=(vector&& other);
-
- void push_back(const T& element);
- void push_back(T&& element);
- void pop_back();
-
- void erase(const_iterator position);
- void erase(const_iterator first, const_iterator last);
-
- void clear();
-
- template <class... Args>
- void emplace_back(Args&&... args);
-
- T& operator[](size_t idx);
- const T& operator[](size_t idx) const;
-
- T* data();
-
- void resize(size_t n);
- void reserve(size_t n);
- void shrink_to_fit();
-
- size_t size() const;
- size_t capacity() const;
- bool empty() const;
-
- iterator begin()
- {
- return iterator(_data);
- }
- iterator end()
- {
- return iterator(_data + size());
- }
-
- const_iterator c_begin() const
- {
- return const_iterator(_data);
- }
- const_iterator c_end() const
- {
- return const_iterator(_data + size());
- }
-
- reverse_iterator rbegin()
- {
- return {_data + size() - 1};
- }
-
- reverse_iterator rend()
- {
- return {_data - 1};
- }
-
- const T& back() const
- {
- return _data[size() - 1];
- }
- T& back()
- {
- return _data[size() - 1];
- }
-
- const T& front() const
- {
- return _data[0];
- }
- T& front()
- {
- return _data[0];
- }
-
- ~vector();
-
- private:
- void copy(const vector& other);
- void free();
- void move(vector&& other);
- size_t calculate_capacity() const;
-
- Allocator _allocator;
-
- T* _data = nullptr;
- size_t _size = 0;
- size_t _capacity = 0;
-};
-
-// Constructs the container with count copies of elements with default value.
-template <class T, class Allocator>
-vector<T, Allocator>::vector(size_t count)
- : _data(_allocator.allocate(count))
- , _size(count)
- , _capacity(count)
-{
- _allocator.construct_range(_data, _data + _size);
-}
-
-// Constructs the container with count copies of elements with value initial.
-template <class T, class Allocator>
-vector<T, Allocator>::vector(size_t count, const T& initial)
- : _data(_allocator.allocate(count))
- , _size(count)
- , _capacity(count)
-{
- _allocator.construct_range(_data, _data + _size, initial);
-}
-
-template <class T, class Allocator>
-vector<T, Allocator>::vector(const vector& other)
-{
- copy(other);
-}
-
-template <class T, class Allocator>
-vector<T, Allocator>& vector<T, Allocator>::operator=(const vector& other)
-{
- if (this != &other)
- {
- free();
- copy(other);
- }
- return *this;
-}
-
-template <class T, class Allocator>
-vector<T, Allocator>::vector(vector&& other)
-{
- move(std::move(other));
-}
-
-template <class T, class Allocator>
-vector<T, Allocator>& vector<T, Allocator>::operator=(vector&& other)
-{
- if (this != &other)
- {
- free();
- move(std::move(other));
- }
- return *this;
-}
-
-template <class T, class Allocator>
-vector<T, Allocator>::~vector()
-{
- free();
-}
-
-template <class T, class Allocator>
-void vector<T, Allocator>::copy(const vector<T, Allocator>& other)
-{
- _data = _allocator.allocate(other.capacity());
- _allocator.copy_range(_data, other._data, other._data + other.size());
-
- _size = other.size();
- _capacity = other.capacity();
-}
-
-template <class T, class Allocator>
-void vector<T, Allocator>::free()
-{
- _allocator.destroy_range(_data, _data + size());
- _allocator.deallocate(_data, capacity());
-}
-
-template <class T, class Allocator>
-void vector<T, Allocator>::move(vector<T, Allocator>&& other)
-{
- _size = other.size();
- _capacity = other.capacity();
- _data = other._data;
-
- other._data = nullptr;
- other._size = other._capacity = 0;
-}
-
-template <class T, class Allocator>
-size_t vector<T, Allocator>::size() const
-{
- return _size;
-}
-
-template <class T, class Allocator>
-size_t vector<T, Allocator>::capacity() const
-{
- return _capacity;
-}
-
-template <class T, class Allocator>
-size_t vector<T, Allocator>::calculate_capacity() const
-{
- if (capacity() == 0)
- return 1;
- return capacity() * Constants::GROWTH_FACTOR;
-}
-
-// Resizes the container to contain `n` elements, does nothing if `n` == size().
-// If the current size is greater than `n`, the container is reduced to its first count elements.
-// If the current size is less than `n`, then additional default-inserted elements are appended.
-template <class T, class Allocator>
-void vector<T, Allocator>::resize(size_t n)
-{
- if (n < size())
- {
- _allocator.destroy_range(_data + n, _data + size());
- _size = n;
- }
- else if (n > size())
- {
- if (n <= capacity())
- {
- _allocator.construct_range(_data + size(), _data + n);
- _size = n;
- }
- else
- {
- T* new_data = _allocator.allocate(n);
-
- // TODO: what if range is not movable?
- // _allocator.copy_range(new_data, _data, _data + size());
- _allocator.move_range(new_data, _data, _data + size());
- _allocator.construct_range(new_data + size(), new_data + n);
-
- _allocator.deallocate(_data, capacity());
-
- _data = new_data;
- _capacity = n;
- _size = n;
- }
- }
-}
-
-// Increase the capacity of the vector (the total number
-// of elements that the vector can hold without requiring reallocation)
-// to a value that's greater or equal to `n`. If `n` is greater than
-// the current capacity(), new storage is allocated, otherwise the function does nothing.
-template <class T, class Allocator>
-void vector<T, Allocator>::reserve(size_t n)
-{
- if (n <= capacity())
- return;
-
- T* new_data = _allocator.allocate(n);
-
- // TODO: what if range is not movable?
- _allocator.move_range(new_data, _data, _data + size());
-
- _allocator.deallocate(_data, capacity());
-
- _data = new_data;
- _capacity = n;
-}
-
-// Requests the container to reduce its capacity to fit its size.
-// This may cause a reallocation, but has no effect on the vector size and cannot alter its elements.
-template <class T, class Allocator>
-void vector<T, Allocator>::shrink_to_fit()
-{
- if (capacity() == size())
- return;
-
- T* new_data = _allocator.allocate(size());
- _allocator.move_range(new_data, _data, _data + size());
- _allocator.deallocate(_data, capacity());
-
- _capacity = _size;
- _data = new_data;
-}
-
-template <class T, class Allocator>
-void vector<T, Allocator>::push_back(const T& element)
-{
- if (size() == capacity())
- reserve(calculate_capacity());
-
- _allocator.construct(_data[_size++], element);
-}
-
-template <class T, class Allocator>
-void vector<T, Allocator>::push_back(T&& element)
-{
- if (size() == capacity())
- reserve(calculate_capacity());
-
- _allocator.construct(&_data[_size++], std::move(element));
-}
-
-// Erases the specified elements from the container.
-template <class T, class Allocator>
-void vector<T, Allocator>::erase(const_iterator position)
-{
- erase(position, position + 1);
-}
-
-// Erases the specified range from the container.
-template <class T, class Allocator>
-void vector<T, Allocator>::erase(const_iterator first, const_iterator last)
-{
- int deleted_count = last - first;
-
- if (deleted_count <= 0)
- return;
-
- int begin_offset = first - begin();
- int end_offset = last - begin();
-
- if (last != c_end())
- {
- _allocator.move_range(_data + begin_offset, _data + end_offset, _data + size());
- }
- _allocator.destroy_range(_data + end_offset, _data + size());
- _size -= deleted_count;
-}
-
-// Removes the last element of the container.
-// Exceptions: Throws nothing.
-template <class T, class Allocator>
-void vector<T, Allocator>::pop_back()
-{
- if (empty())
- return;
-
- erase(--end());
-}
-
-// Appends a new element to the end of the container.
-// The element is constructed through placement-new in-place.
-template <class T, class Allocator>
-template <class... Args>
-void vector<T, Allocator>::emplace_back(Args&&... args)
-{
- if (size() == capacity())
- reserve(calculate_capacity());
-
- _allocator.construct(&_data[_size++], std::forward<Args>(args)...);
-}
-
-template <class T, class Allocator>
-T& vector<T, Allocator>::operator[](size_t idx)
-{
- return _data[idx];
-}
-
-template <class T, class Allocator>
-const T& vector<T, Allocator>::operator[](size_t idx) const
-{
- return _data[idx];
-}
-
-template <class T, class Allocator>
-T* vector<T, Allocator>::data()
-{
- return _data;
-}
-
-template <class T, class Allocator>
-void vector<T, Allocator>::clear()
-{
- _allocator.destroy_range(_data, _data + size());
- _size = 0;
-}
-
-template <class T, class Allocator>
-bool vector<T, Allocator>::empty() const
-{
- return (size() == 0);
-} \ No newline at end of file
diff --git a/Seminar03/src/dynamic-array/vector/vector.hpp b/Seminar03/src/dynamic-array/vector/vector.hpp
index 5233072..8db5178 100644
--- a/Seminar03/src/dynamic-array/vector/vector.hpp
+++ b/Seminar03/src/dynamic-array/vector/vector.hpp
@@ -1,14 +1,14 @@
-
#pragma once
+
#include "../iterator/iterator.hpp"
-#include <utility>
+#include <memory>
namespace Constants
{
constexpr unsigned GROWTH_FACTOR = 2;
}
-template <class T>
+template <class T, class Allocator = std::allocator<T>>
class vector
{
public:
@@ -57,22 +57,21 @@ class vector
}
iterator end()
{
- return iterator(_data + size());
+ return iterator(&_data[size()]);
}
const_iterator c_begin() const
{
return const_iterator(_data);
}
-
const_iterator c_end() const
{
- return const_iterator(_data + size());
+ return const_iterator(&_data[size()]);
}
reverse_iterator rbegin()
{
- return {_data + size() - 1};
+ return {&_data[size() - 1]};
}
reverse_iterator rend()
@@ -106,46 +105,44 @@ class vector
void move(vector&& other);
size_t calculate_capacity() const;
+ Allocator _allocator;
+
T* _data = nullptr;
size_t _size = 0;
size_t _capacity = 0;
};
// Constructs the container with count copies of elements with default value.
-template <class T>
-vector<T>::vector(size_t count)
- : _data(static_cast<T*>(operator new(count * sizeof(T))))
+template <class T, class Allocator>
+vector<T, Allocator>::vector(size_t count)
+ : _data(_allocator.allocate(count))
, _size(count)
, _capacity(count)
{
- // default construct all elements
- for (size_t i = 0; i < count; i++)
- new (&_data[i]) T();
+ // Default construct all elements.
+ for (size_t i = 0; i < size(); i++)
+ _allocator.construct(&_data[i]);
}
// Constructs the container with count copies of elements with value initial.
-// Why dont we call `new` here?
-// When you choose a memory managment strategy its better
-// to stick with it for concistency.
-template <class T>
-vector<T>::vector(size_t count, const T& initial)
- : _data(static_cast<T*>(operator new(count * sizeof(T))))
+template <class T, class Allocator>
+vector<T, Allocator>::vector(size_t count, const T& initial)
+ : _data(_allocator.allocate(count))
, _size(count)
, _capacity(count)
{
- // construct all elements copying initial
- for (size_t i = 0; i < count; i++)
- new (&_data[i]) T(initial);
+ for (size_t i = 0; i < size(); i++)
+ _allocator.construct(&_data[i], initial);
}
-template <class T>
-vector<T>::vector(const vector& other)
+template <class T, class Allocator>
+vector<T, Allocator>::vector(const vector& other)
{
copy(other);
}
-template <class T>
-vector<T>& vector<T>::operator=(const vector& other)
+template <class T, class Allocator>
+vector<T, Allocator>& vector<T, Allocator>::operator=(const vector& other)
{
if (this != &other)
{
@@ -155,14 +152,14 @@ vector<T>& vector<T>::operator=(const vector& other)
return *this;
}
-template <class T>
-vector<T>::vector(vector&& other)
+template <class T, class Allocator>
+vector<T, Allocator>::vector(vector&& other)
{
move(std::move(other));
}
-template <class T>
-vector<T>& vector<T>::operator=(vector&& other)
+template <class T, class Allocator>
+vector<T, Allocator>& vector<T, Allocator>::operator=(vector&& other)
{
if (this != &other)
{
@@ -172,39 +169,36 @@ vector<T>& vector<T>::operator=(vector&& other)
return *this;
}
-template <class T>
-vector<T>::~vector()
+template <class T, class Allocator>
+vector<T, Allocator>::~vector()
{
free();
}
-template <class T>
-void vector<T>::copy(const vector<T>& other)
+template <class T, class Allocator>
+void vector<T, Allocator>::copy(const vector<T, Allocator>& other)
{
- // allocate enough memoty
- _data = static_cast<T*>(operator new(other.capacity() * sizeof(T)));
-
- // copy construct elements
+ _data = _allocator.allocate(other.capacity());
+
+ // Copy construct the new memory
for (size_t i = 0; i < other.size(); i++)
- new (&_data[i]) T(other[i]);
+ _allocator.construct(&_data[i], other[i]);
_size = other.size();
_capacity = other.capacity();
}
-template <class T>
-void vector<T>::free()
+template <class T, class Allocator>
+void vector<T, Allocator>::free()
{
- // call destructor on constructed elements
for (size_t i = 0; i < size(); i++)
- (_data + i)->~T();
-
- // deallocate memory
- operator delete(_data, capacity() * sizeof(T));
+ _allocator.destroy(&_data[i]);
+
+ _allocator.deallocate(_data, capacity());
}
-template <class T>
-void vector<T>::move(vector<T>&& other)
+template <class T, class Allocator>
+void vector<T, Allocator>::move(vector<T, Allocator>&& other)
{
_size = other.size();
_capacity = other.capacity();
@@ -214,64 +208,58 @@ void vector<T>::move(vector<T>&& other)
other._size = other._capacity = 0;
}
-template <class T>
-size_t vector<T>::size() const
+template <class T, class Allocator>
+size_t vector<T, Allocator>::size() const
{
return _size;
}
-template <class T>
-size_t vector<T>::capacity() const
+template <class T, class Allocator>
+size_t vector<T, Allocator>::capacity() const
{
return _capacity;
}
-template <class T>
-size_t vector<T>::calculate_capacity() const
+template <class T, class Allocator>
+size_t vector<T, Allocator>::calculate_capacity() const
{
if (capacity() == 0)
return 1;
return capacity() * Constants::GROWTH_FACTOR;
}
-// Resizes the container to contain `n` elements, does nothing if `n` == size().
-// If the current size is greater than `n`, the container is reduced to its first count elements.
+// Resizes the container to contain `n` elements, does nothing if `n` == size().
+// If the current size is greater than `n`, the container is reduced to its first count elements.
// If the current size is less than `n`, then additional default-inserted elements are appended.
-template <class T>
-void vector<T>::resize(size_t n)
+template <class T, class Allocator>
+void vector<T, Allocator>::resize(size_t n)
{
if (n < size())
{
- // call destructor on constructed elements
for (size_t i = n; i < size(); i++)
- (_data + i)->~T();
-
+ _allocator.destroy(&_data[i]);
_size = n;
}
else if (n > size())
{
if (n <= capacity())
{
- // default construct elements in range [size(), n)
for (size_t i = size(); i < n; i++)
- new (&_data[i]) T();
-
+ _allocator.construct(&_data[i]);
+
_size = n;
}
else
{
- T* new_data = static_cast<T*>(operator new(n * sizeof(T)));
+ T* new_data = _allocator.allocate(n);
for (size_t i = 0; i < size(); i++)
- {
- new (&new_data[i]) T(std::move(_data[i]));
- (_data + i)->~T();
- }
-
+ _allocator.construct(new_data, std::move(_data[i]));
+
for (size_t i = size(); i < n; i++)
- new (&new_data[i]) T();
+ _allocator.construct(&new_data[i]);
- operator delete(_data, capacity() * sizeof(T));
+ _allocator.deallocate(_data, capacity());
_data = new_data;
_capacity = n;
@@ -280,25 +268,22 @@ void vector<T>::resize(size_t n)
}
}
-// Increase the capacity of the vector (the total number
-// of elements that the vector can hold without requiring reallocation)
+// Increase the capacity of the vector (the total number
+// of elements that the vector can hold without requiring reallocation)
// to a value that's greater or equal to `n`. If `n` is greater than
-// the current capacity(), new storage is allocated, otherwise the function does nothing.
-template <class T>
-void vector<T>::reserve(size_t n)
+// the current capacity(), new storage is allocated, otherwise the function does nothing.
+template <class T, class Allocator>
+void vector<T, Allocator>::reserve(size_t n)
{
if (n <= capacity())
return;
- T* new_data = static_cast<T*>(operator new(n * sizeof(T)));
+ T* new_data = _allocator.allocate(n);
for (size_t i = 0; i < size(); i++)
- {
- new (&new_data[i]) T(std::move(_data[i]));
- (_data + i)->~T();
- }
+ _allocator.construct(&new_data[i], std::move(_data[i]));
- operator delete(_data, capacity() * sizeof(T));
+ _allocator.deallocate(_data, capacity());
_data = new_data;
_capacity = n;
@@ -306,54 +291,49 @@ void vector<T>::reserve(size_t n)
// Requests the container to reduce its capacity to fit its size.
// This may cause a reallocation, but has no effect on the vector size and cannot alter its elements.
-template <class T>
-void vector<T>::shrink_to_fit()
+template <class T, class Allocator>
+void vector<T, Allocator>::shrink_to_fit()
{
if (capacity() == size())
return;
- T* new_data = static_cast<T*>(operator new(size() * sizeof(T)));
-
+ T* new_data = _allocator.allocate(size());
for (size_t i = 0; i < size(); i++)
- {
- new (&new_data[i]) T(std::move(_data[i]));
- (_data + i)->~T();
- }
-
- operator delete(_data, capacity() * sizeof(T));
+ _allocator.construct(new_data + i, std::move(_data[i]));
+ _allocator.deallocate(_data, capacity());
_capacity = _size;
_data = new_data;
}
-template <class T>
-void vector<T>::push_back(const T& element)
+template <class T, class Allocator>
+void vector<T, Allocator>::push_back(const T& element)
{
if (size() == capacity())
reserve(calculate_capacity());
- new (&_data[_size++]) T(element);
+ _allocator.construct(_data[_size++], element);
}
-template <class T>
-void vector<T>::push_back(T&& element)
+template <class T, class Allocator>
+void vector<T, Allocator>::push_back(T&& element)
{
if (size() == capacity())
reserve(calculate_capacity());
- new (&_data[_size++]) T(std::move(element));
+ _allocator.construct(&_data[_size++], std::move(element));
}
// Erases the specified elements from the container.
-template <class T>
-void vector<T>::erase(const_iterator position)
+template <class T, class Allocator>
+void vector<T, Allocator>::erase(const_iterator position)
{
erase(position, position + 1);
}
// Erases the specified range from the container.
-template <class T>
-void vector<T>::erase(const_iterator first, const_iterator last)
+template <class T, class Allocator>
+void vector<T, Allocator>::erase(const_iterator first, const_iterator last)
{
int deleted_count = last - first;
@@ -365,20 +345,24 @@ void vector<T>::erase(const_iterator first, const_iterator last)
if (last != c_end())
{
+ size_t construct_idx = begin_offset;
for (size_t i = end_offset; i < size(); i++)
- new (&_data[begin_offset++]) T(std::move(_data[i]));
+ {
+ _allocator.construct(&_data[construct_idx], std::move(_data[i]));
+ ++construct_idx;
+ }
}
for (size_t i = end_offset; i < size(); i++)
- (_data + i)->~T();
-
+ _allocator.destroy(&_data[i]);
+
_size -= deleted_count;
}
// Removes the last element of the container.
// Exceptions: Throws nothing.
-template <class T>
-void vector<T>::pop_back()
+template <class T, class Allocator>
+void vector<T, Allocator>::pop_back()
{
if (empty())
return;
@@ -386,47 +370,49 @@ void vector<T>::pop_back()
erase(--end());
}
-// Appends a new element to the end of the container.
+// Appends a new element to the end of the container.
// The element is constructed through placement-new in-place.
-template <class T>
+template <class T, class Allocator>
template <class... Args>
-void vector<T>::emplace_back(Args&&... args)
+void vector<T, Allocator>::emplace_back(Args&&... args)
{
if (size() == capacity())
reserve(calculate_capacity());
- new (&_data[_size++]) T(std::forward<Args>(args)...);
+ _allocator.construct(&_data[_size++], std::forward<Args>(args)...);
}
-template <class T>
-T& vector<T>::operator[](size_t idx)
+template <class T, class Allocator>
+T& vector<T, Allocator>::operator[](size_t idx)
{
return _data[idx];
}
-template <class T>
-const T& vector<T>::operator[](size_t idx) const
+template <class T, class Allocator>
+const T& vector<T, Allocator>::operator[](size_t idx) const
{
return _data[idx];
}
-template <class T>
-T* vector<T>::data()
+template <class T, class Allocator>
+T* vector<T, Allocator>::data()
{
return _data;
}
-template <class T>
-void vector<T>::clear()
+template <class T, class Allocator>
+void vector<T, Allocator>::clear()
{
for (size_t i = 0; i < size(); i++)
- (_data + i)->~T();
-
+ {
+ _allocator.destroy(&_data[i]);
+ }
+
_size = 0;
}
-template <class T>
-bool vector<T>::empty() const
+template <class T, class Allocator>
+bool vector<T, Allocator>::empty() const
{
return (size() == 0);
} \ No newline at end of file