Lumiera  0.pre.03
»edit your freedom«
uninitialised-storage.hpp
Go to the documentation of this file.
1 /*
2  UNINITIALISED-STORAGE.hpp - array-like container with raw storage
3 
4  Copyright (C)
5  2023, Hermann Vosseler <Ichthyostega@web.de>
6 
7   **Lumiera** is free software; you can redistribute it and/or modify it
8   under the terms of the GNU General Public License as published by the
9   Free Software Foundation; either version 2 of the License, or (at your
10   option) any later version. See the file COPYING for further details.
11 
12 */
13 
61 #ifndef LIB_UNINITIALISED_STORAGE_H
62 #define LIB_UNINITIALISED_STORAGE_H
63 
64 
65 #include <cstddef>
66 #include <utility>
67 #include <array>
68 #include <new>
69 
70 
71 namespace lib {
72 
78  template<typename T, size_t cnt>
80  {
81  using _Arr = std::array<T,cnt>;
82  alignas(T) std::byte buffer_[sizeof(_Arr)];
83 
84  public:
85  _Arr&
86  array()
87  {
88  return * std::launder (reinterpret_cast<_Arr* > (&buffer_));
89  }
90 
91  _Arr const&
92  array() const
93  {
94  return * std::launder (reinterpret_cast<_Arr const*> (&buffer_));
95  }
96 
97 
98  operator _Arr&() { return array(); }
99  operator _Arr const&() const { return array(); }
100 
101  T & operator[] (size_t idx) { return array()[idx]; }
102  T const& operator[] (size_t idx) const { return array()[idx]; }
103 
104 
105  template<typename...Args>
106  T&
107  createAt (size_t idx, Args&& ...args)
108  {
109  return *new(&operator[](idx)) T{std::forward<Args>(args)...};
110  }
111 
112  void
113  destroyAt (size_t idx)
114  {
115  operator[](idx).~T();
116  }
117 
118  static constexpr size_t size() { return cnt; }
119  };
120 
121 
122 
123 
128  template<typename T>
130  {
131  using _Arr = T[];
132 
133  void* buff_{nullptr};
134  size_t size_{0};
135 
136  public:
137  T*
138  allocate(size_t cnt)
139  {
140  if (buff_) discard();
141  size_ = cnt;
142  buff_ = cnt? std::aligned_alloc (std::alignment_of<T>(), cnt * sizeof(T))
143  : nullptr;
144  return front();
145  }
146 
147  void
148  discard()
149  {
150  std::free (buff_);
151  buff_ = nullptr;
152  size_ = 0;
153  }
154 
155 
156  UninitialisedDynBlock() =default;
158  {
159  if (buff_)
160  discard();
161  }
162  explicit
163  UninitialisedDynBlock (size_t cnt)
164  {
165  if (cnt)
166  allocate(cnt);
167  }
168 
170  {
171  if (this != &rr)
172  swap (*this, rr);
173  }
174 
176  UninitialisedDynBlock& operator= (UninitialisedDynBlock &&) =delete;
177  UninitialisedDynBlock& operator= (UninitialisedDynBlock const&) =delete;
178 
179  friend void
181  {
182  using std::swap;
183  swap (u1.size_, u2.size_);
184  swap (u1.buff_, u2.buff_);
185  }
186 
187  explicit
188  operator bool() const
189  {
190  return bool(buff_);
191  }
192 
193  size_t
194  size() const
195  {
196  return size_;
197  }
198 
199 
200  _Arr&
201  array()
202  {
203  return * std::launder (reinterpret_cast<_Arr* > (buff_));
204  }
205 
206  _Arr const&
207  array() const
208  {
209  return * std::launder (reinterpret_cast<_Arr const*> (buff_));
210  }
211 
212 
213  T * front() { return &array()[0]; }
214  T const* front() const { return &array()[0]; }
215  T * after() { return &array()[size_];}
216  T const* after() const { return &array()[size_];}
217  T * back () { return after() - 1; }
218  T const* back () const { return after() - 1; }
219 
220  T & operator[] (size_t idx) { return array()[idx]; }
221  T const& operator[] (size_t idx) const { return array()[idx]; }
222 
223 
224  template<typename...Args>
225  T&
226  createAt (size_t idx, Args&& ...args)
227  {
228  return *new(&operator[](idx)) T{std::forward<Args>(args)...};
229  }
230 
231  void
232  destroyAt (size_t idx)
233  {
234  operator[](idx).~T();
235  }
236  };
237 
238 
239 } // namespace lib
240 #endif /*LIB_UNINITIALISED_STORAGE_H*/
Implementation namespace for support and library code.
Block of raw uninitialised storage with array like access.
Managed uninitialised Heap-allocated storage with array like access.