|
|
- #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::move(ref));
- }
- oth.sz = 0;
- }
-
- dynarray& operator=(const dynarray& oth) {
- for(auto& self : data) {
- self.clear();
- }
- sz = 0;
- for(auto& ref : oth) {
- push_back(ref);
- }
- return *this;
- }
-
- dynarray& operator=(dynarray&& oth) {
- for(auto& self : data) {
- self.clear();
- }
- sz = 0;
- for(auto& ref : oth) {
- emplace_back(gp::forward<T>(ref));
- }
- oth.sz = 0;
- return *this;
- }
-
- constexpr associated_iterator begin()
- {
- return associated_iterator((T*)&data[0]);
- }
-
- constexpr associated_iterator end()
- {
- return associated_iterator((T*)&data[sz]);
- }
-
- constexpr const associated_iterator begin() const
- {
- return associated_iterator((T*)&data[0]);
- }
-
- constexpr const associated_iterator end() const
- {
- 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;
- }
- }
- };
-
- }
|