jubilant-funicular
StaticVector.h
1 #ifndef NTA_STATICVECTOR_H_INCLUDED
2 #define NTA_STATICVECTOR_H_INCLUDED
3 
4 #include <memory>
5 #include <new>
6 
7 #include "nta/MyEngine.h"
8 
9 namespace nta {
10  namespace utils {
14  template<typename T, std::size_t Cap>
15  class StaticVector {
16  public:
17  using value_type = T;
18  using iterator = T*;
19  using const_iterator = const T*;
20  using reverse_iterator = std::reverse_iterator<iterator>;
21  using const_reverse_iterator = std::reverse_iterator<const_iterator>;
22  private:
23  typename std::aligned_storage_t<sizeof(T), alignof(T)> m_data[Cap];
24  std::size_t m_size;
25  public:
26  StaticVector() : m_size(0) {}
27  template<std::size_t Cap2>
28  StaticVector(const StaticVector<T, Cap2>& other) : m_size(other.size()) {
29  std::uninitialized_copy(other.cbegin(), other.cend(), begin());
30  }
31  template<std::size_t Cap2>
32  StaticVector(StaticVector<T, Cap2>&& other) : m_size(other.size()) {
33  std::uninitialized_copy(std::make_move_iterator(other.begin()), std::make_move_iterator(other.end()), begin());
34  }
35  explicit StaticVector(std::size_t count, const T& value = T()) : m_size(count) {
36  std::uninitialized_fill(begin(), end(), value);
37  }
38  StaticVector(const std::initializer_list<T>& data) : m_size(0) {
39  for (const T& elem : data) push_back(elem);
40  }
41  ~StaticVector() { clear(); }
42 
43  constexpr std::size_t capacity() const { return Cap; }
44  constexpr std::size_t cap() const { return Cap; }
45  constexpr std::size_t max_size() const { return Cap; }
46 
47  std::size_t size() const { return m_size; }
48  bool is_empty() const { return m_size == 0; }
49  bool empty() const { return is_empty(); }
50  bool is_full() const { return m_size == Cap; }
51  bool full() const { return is_full(); }
52 
53  T& front() { return at(0); }
54  T& back() { return at(m_size-1); }
55  T* data() { return begin(); }
56 
57  T& operator[](std::size_t idx) { return at(idx); }
58  T& at(std::size_t idx) { return *(data() + idx); }
59 
60  void clear() { while (m_size > 0) pop_back(); }
61  void pop_back() { at(--m_size).~T(); }
62  void erase(iterator pos) { remove(pos); }
63  void resize(std::size_t size) {
64  while (size < (m_size = std::max(m_size, size))) pop_back();
65  }
66  void remove(iterator pos) {
67  for (auto it = (m_size--, pos->~T(), pos); it != cend(); ++it) *it = *(it+1);
68  }
69 
70  void push_back(const T& elem) { new(&m_data[m_size++]) T(elem); }
71  template<typename... Args>
72  void emplace_back(Args&&... args) {
73  new(&m_data[m_size++]) T(std::forward<Args>(args)...);
74  }
75  // When you value using only one line over efficiency/readability
76  void insert(iterator pos, const T& elem) {
77  for (auto it = (m_size++, rbegin()); it != reverse_iterator(pos) || (*pos = elem, false); ++it) *it = *(it+1);
78  }
79  template<typename... Args>
80  void emplace(iterator pos, Args&&... args) {
81  for (auto it = (m_size++, rbegin()); it != reverse_iterator(pos) || (new(std::addressof(*pos)) T(std::forward<Args>(args)...), false); ++it) *it = *(it+1);
82  }
83 
84  iterator begin() { return reinterpret_cast<T*>(std::launder(&m_data[0])); }
85  const_iterator begin() const { return cbegin(); }
86  iterator end() { return begin() + m_size; }
87  const_iterator end() const { return cend(); }
88  const_iterator cbegin() const {
89  return reinterpret_cast<const T*>(std::launder(&m_data[0]));
90  }
91  const_iterator cend() const { return cbegin() + m_size; }
92  reverse_iterator rbegin() { return reverse_iterator(end()); }
93  const_reverse_iterator rbegin() const { return crbegin(); }
94  reverse_iterator rend() { return reverse_iterator(begin()); }
95  const_reverse_iterator rend() const { return crend(); }
96  const_reverse_iterator crbegin() { return const_reverse_iterator(cend()); }
97  const_reverse_iterator crend() { return const_reverse_iterator(cbegin()); }
98  };
99  }
100 }
101 
102 #endif // NTA_STATICVECTOR_H_INCLUDED
nta
Definition: Animation2D.h:6
nta::utils::StaticVector
Definition: StaticVector.h:15