#pragma once
|
|
|
|
#include "gp/containers/array.hpp"
|
|
|
|
namespace gp {
|
|
|
|
template<typename T, size_t cap>
|
|
class dynarray {
|
|
struct build_order{};
|
|
|
|
struct v_element{
|
|
char data[sizeof(T)];
|
|
|
|
operator T&() {
|
|
return *(T*)data;
|
|
}
|
|
|
|
v_element()
|
|
: data{}
|
|
{}
|
|
|
|
template<typename ...Args>
|
|
v_element(build_order, Args&&... argv) {
|
|
new(data) T(gp::forward<Args>(argv)...);
|
|
}
|
|
|
|
template<typename arg>
|
|
T& operator=(arg& argv) {
|
|
return *(T*)data = argv;
|
|
}
|
|
|
|
template<typename arg>
|
|
T& operator=(arg&& argv) {
|
|
return *(T*)data = gp::forward<arg>(argv);
|
|
}
|
|
|
|
template<typename ...Args>
|
|
void build(Args&&... argv) {
|
|
new(data) T(gp::forward<Args>(argv)...);
|
|
}
|
|
|
|
T& value() {
|
|
return *(T*)data;
|
|
}
|
|
|
|
T& value() const {
|
|
return *(T*)data;
|
|
}
|
|
|
|
void clear(){
|
|
((T*)data)->~T();
|
|
}
|
|
};
|
|
|
|
using associated_iterator = pointer_iterator<T, 1>;
|
|
using associated_const_iterator = const_pointer_iterator<T, 1>;
|
|
using associated_riterator = pointer_iterator<T, -1>;
|
|
using associated_const_riterator = const_pointer_iterator<T, -1>;
|
|
|
|
v_element data[cap];
|
|
size_t sz = 0;
|
|
|
|
public:
|
|
dynarray() = default;
|
|
|
|
dynarray(dynarray& oth)
|
|
{
|
|
for(auto& ref : oth) {
|
|
push_back(ref);
|
|
}
|
|
}
|
|
|
|
/*dynarray(dynarray&& oth)
|
|
{
|
|
for(auto& ref : oth) {
|
|
emplace_back(gp::forward<T>(ref));
|
|
}
|
|
}*/
|
|
|
|
constexpr associated_iterator begin()
|
|
{
|
|
return associated_iterator((T*)&data[0]);
|
|
}
|
|
|
|
constexpr associated_iterator end()
|
|
{
|
|
return associated_iterator((T*)&data[sz]);
|
|
}
|
|
|
|
constexpr associated_const_iterator cbegin() const
|
|
{
|
|
return associated_const_iterator((T*)&data[0]);
|
|
}
|
|
|
|
constexpr associated_const_iterator cend() const
|
|
{
|
|
return associated_const_iterator((T*)&data[sz]);
|
|
}
|
|
|
|
constexpr associated_riterator rbegin()
|
|
{
|
|
return associated_riterator((T*)&data[sz-1]);
|
|
}
|
|
|
|
constexpr associated_riterator rend()
|
|
{
|
|
return associated_riterator((T*)data-1);
|
|
}
|
|
|
|
constexpr associated_const_riterator crbegin() const
|
|
{
|
|
return associated_const_riterator((T*)&data[sz-1]);
|
|
}
|
|
|
|
constexpr associated_const_riterator crend() const
|
|
{
|
|
return associated_const_riterator((T*)data-1);
|
|
}
|
|
|
|
constexpr bool operator==(const dynarray& oth) const
|
|
{
|
|
if(size() != oth.size()) return false;
|
|
for(size_t idx = 0; idx<sz; idx++)
|
|
{
|
|
if(data[idx].value() != oth.data[idx].value())
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
constexpr bool operator!=(const dynarray& oth) const
|
|
{
|
|
return !(*this == oth);
|
|
}
|
|
|
|
size_t size() const {
|
|
return sz;
|
|
}
|
|
|
|
constexpr size_t capacity() const {
|
|
return cap;
|
|
}
|
|
|
|
T& operator[] (size_t idx) {
|
|
return data[idx];
|
|
}
|
|
|
|
const T& operator[] (size_t idx) const {
|
|
return data[idx];
|
|
}
|
|
|
|
void push_back(T& value) {
|
|
data[sz].build(value);
|
|
++sz;
|
|
}
|
|
|
|
void push_back(T&& value) {
|
|
data[sz].build(value);
|
|
++sz;
|
|
}
|
|
|
|
template<typename ...Args>
|
|
void emplace_back(Args&&... argv) {
|
|
data[sz].build(gp::forward<Args>(argv)...);
|
|
++sz;
|
|
}
|
|
|
|
void remove_back() {
|
|
--sz;
|
|
data[sz].clear();
|
|
}
|
|
|
|
gp::buffer<T> as_buffer()
|
|
{
|
|
return gp::buffer<T>{(T*)data, (T*)data+sz};
|
|
}
|
|
|
|
~dynarray() {
|
|
auto it = data;
|
|
auto end = data + size();
|
|
while(it != end) {
|
|
(*it).clear();
|
|
++it;
|
|
}
|
|
}
|
|
};
|
|
|
|
}
|