|
|
@ -6,6 +6,12 @@ |
|
|
|
#include <initializer_list>
|
|
|
|
|
|
|
|
namespace gp{ |
|
|
|
/**
|
|
|
|
* @brief A vector type most similar to that of the standard library |
|
|
|
* Always uses polymorphic allocation, no small value optimization |
|
|
|
* |
|
|
|
* @tparam T |
|
|
|
*/ |
|
|
|
template<typename T> |
|
|
|
class vector final { |
|
|
|
T* ary = nullptr; |
|
|
@ -116,11 +122,26 @@ namespace gp{ |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Ensures the vector can hold at least 1 more element |
|
|
|
* |
|
|
|
* @return true if it is at least now possible to fit one more element |
|
|
|
* @return false if fiting one more element is not possible even now |
|
|
|
*/ |
|
|
|
bool grow() { |
|
|
|
if(sz == cap) return reserve(1 + sz + (sz >> 1)); |
|
|
|
return true; |
|
|
|
} |
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Reserves space so that the capacity is at least equal to the provided value. |
|
|
|
* |
|
|
|
* This will never shrink the datastructure |
|
|
|
* |
|
|
|
* @param new_cap the new capacity |
|
|
|
* @return true on success |
|
|
|
* @return false on failure |
|
|
|
*/ |
|
|
|
bool reserve(size_t new_cap) { |
|
|
|
if(new_cap <= cap) return true; |
|
|
|
|
|
|
@ -147,6 +168,13 @@ namespace gp{ |
|
|
|
|
|
|
|
constexpr const T& operator[] (size_t off) const |
|
|
|
{ |
|
|
|
if constexpr (gp_config::has_buffer_bounds) |
|
|
|
{ |
|
|
|
gp_config::assertion( |
|
|
|
off < sz, |
|
|
|
"Array bounds infringed" |
|
|
|
); |
|
|
|
} |
|
|
|
return ary[off]; |
|
|
|
} |
|
|
|
|
|
|
@ -160,6 +188,13 @@ namespace gp{ |
|
|
|
return cap; |
|
|
|
} |
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Adds the provided value to the vector |
|
|
|
* |
|
|
|
* @param value |
|
|
|
* @return true on success |
|
|
|
* @return false on failure |
|
|
|
*/ |
|
|
|
constexpr bool push_back(T& value) { |
|
|
|
if(grow()) { |
|
|
|
new(ary+sz) T(value); |
|
|
@ -169,6 +204,14 @@ namespace gp{ |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Moves the provided value to the vector |
|
|
|
* |
|
|
|
* @param value |
|
|
|
* @return true on success |
|
|
|
* @return false on failure |
|
|
|
*/ |
|
|
|
constexpr bool push_back(T&& value) { |
|
|
|
if(grow()) { |
|
|
|
new(ary+sz) T(gp::move(value)); |
|
|
@ -178,6 +221,13 @@ namespace gp{ |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Constructs a new element at the end of the vector |
|
|
|
* |
|
|
|
* @param value the parameters to be sent to the constructor of T |
|
|
|
* @return true on success |
|
|
|
* @return false on failure |
|
|
|
*/ |
|
|
|
template<typename ...U> |
|
|
|
constexpr bool emplace_back(U&&... value) { |
|
|
|
if(grow()) { |
|
|
@ -188,6 +238,11 @@ namespace gp{ |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief moves the last element of the vector out if it exists, returning an optional. |
|
|
|
* |
|
|
|
* @return constexpr gp::optional<T> contains a value if it existed, else it is empty |
|
|
|
*/ |
|
|
|
constexpr gp::optional<T> pop_back() { |
|
|
|
if(sz == 0) return gp::nullopt; |
|
|
|
sz--; |
|
|
@ -253,6 +308,12 @@ namespace gp{ |
|
|
|
return !(*this == oth); |
|
|
|
} |
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Provides a span access to the vector |
|
|
|
* |
|
|
|
* @return A buffer of the vector. |
|
|
|
* It is invalidated by any operation that may change the size of the vector. |
|
|
|
*/ |
|
|
|
gp::buffer<T> as_buffer() |
|
|
|
{ |
|
|
|
return gp::buffer<T>{(T*)ary, (T*)ary+sz}; |
|
|
|