Libsaki
Core library of Pancake Mahjong
stactor.h
1 #ifndef SAKI_UTIL_STACTOR_H
2 #define SAKI_UTIL_STACTOR_H
3 
4 #include <type_traits>
5 #include <functional>
6 #include <new>
7 #include <cassert>
8 
9 
10 
11 namespace saki
12 {
13 
14 
15 
16 namespace util
17 {
18 
19 
20 
21 template <class T>
22 constexpr T* launder(T* p) noexcept
23 {
24 #ifdef __clang__
25  return p; // clang++ in NDK don't have launder??
26 #else
27  return std::launder(p);
28 #endif
29 }
30 
31 
32 
33 template<typename T>
34 class Range
35 {
36 public:
37  explicit Range(const T *begin, const T *end) : mBegin(begin), mEnd(end) {}
38  const T *begin() const noexcept { return mBegin; }
39  const T *end() const noexcept { return mEnd; }
40  bool empty() const noexcept { return mBegin == mEnd; }
41 
42 private:
43  const T *mBegin;
44  const T *mEnd;
45 };
46 
47 
48 
49 template<typename T, size_t MAX>
51 {
52 public:
53  StactorBase() = default;
54 
55  StactorBase(std::initializer_list<T> inits) noexcept
56  {
57  for (const auto &e : inits)
58  pushBack(e);
59  }
60 
62  using value_type = T;
63  using iterator = T *;
64  using const_iterator = const T *;
65 
66  const T *data() const noexcept
67  {
68  return launder(reinterpret_cast<const T *>(mData));
69  }
70 
71  T *data() noexcept
72  {
73  return launder(reinterpret_cast<T *>(mData));
74  }
75 
76  T &operator[](size_t i) noexcept
77  {
78  assert(i < mSize);
79  return data()[i];
80  }
81 
82  const T &operator[](size_t i) const noexcept
83  {
84  assert(i < mSize);
85  return data()[i];
86  }
87 
88  T &at(size_t i) noexcept
89  {
90  return (*this)[i];
91  }
92 
93  const T &at(size_t i) const noexcept
94  {
95  return (*this)[i];
96  }
97 
98  bool empty() const noexcept
99  {
100  return mSize == 0;
101  }
102 
103  bool full() const noexcept
104  {
105  return mSize == MAX;
106  }
107 
108  size_t size() const noexcept
109  {
110  return mSize;
111  }
112 
113  int iSize() const noexcept
114  {
115  return static_cast<int>(size());
116  }
117 
118  T *begin() noexcept
119  {
120  return data();
121  }
122 
123  const T *begin() const noexcept
124  {
125  return data();
126  }
127 
128  T *end() noexcept
129  {
130  return begin() + mSize;
131  }
132 
133  const T *end() const noexcept
134  {
135  return begin() + mSize;
136  }
137 
138  Range<T> range() const noexcept
139  {
140  return Range<T>(begin(), end());
141  }
142 
143  T &front() noexcept
144  {
145  assert(!empty());
146  return operator[](0);
147  }
148 
149  const T &front() const noexcept
150  {
151  assert(!empty());
152  return operator[](0);
153  }
154 
155  T &back() noexcept
156  {
157  assert(!empty());
158  return operator[](mSize - 1);
159  }
160 
161  const T &back() const noexcept
162  {
163  assert(!empty());
164  return operator[](mSize - 1);
165  }
166 
167  template<typename... Args>
168  void emplaceBack(Args && ... elem) noexcept
169  {
170  assert(mSize + 1 <= MAX);
171  new (mData + mSize) T(std::forward<Args>(elem) ...);
172  mSize++;
173  }
174 
175  void pushBack(const T &elem) noexcept
176  {
177  assert(mSize + 1 <= MAX);
178  new (mData + mSize) T(elem);
179  mSize++;
180  }
181 
182  void pushBack(T &&elem) noexcept
183  {
184  assert(mSize + 1 <= MAX);
185  new (mData + mSize) T(std::move(elem));
186  mSize++;
187  }
188 
189  void pushBack(const Range<T> &range) noexcept
190  {
191  for (const T &v : range)
192  pushBack(v);
193  }
194 
196  void push_back(const T &elem) noexcept
197  {
198  pushBack(elem);
199  }
200 
202  void push_back(T &&elem) noexcept
203  {
204  pushBack(std::forward<T>(elem));
205  }
206 
207  void popBack() noexcept
208  {
209  assert(!empty());
210  (data() + mSize - 1)->T::~T();
211  mSize--;
212  }
213 
214  void clear() noexcept
215  {
216  while (mSize > 0)
217  popBack();
218  }
219 
220 protected:
221  static const size_t ALIGN = std::alignment_of_v<T>;
222  std::aligned_storage_t<sizeof(T), ALIGN> mData[MAX];
223  size_t mSize = 0;
224 };
225 
226 
227 
246 template<typename T, size_t MAX, typename SFINAE = void>
247 class Stactor;
248 
249 
250 
251 template<typename T, size_t MAX>
252 class Stactor<T, MAX, std::enable_if_t<std::is_trivially_copyable_v<T>>>
253  : public StactorBase<T, MAX>
254 {
255 public:
257 };
258 
259 
260 
261 template<typename T, size_t MAX>
262 class Stactor<T, MAX, std::enable_if_t<!std::is_trivially_copyable_v<T>>>
263  : public StactorBase<T, MAX>
264 {
265 public:
266  using Base = StactorBase<T, MAX>;
267 
268  using Base::StactorBase;
269 
270  ~Stactor()
271  {
272  Base::clear();
273  }
274 
275  Stactor(const Stactor &copy)
276  {
277  for (const auto &e : copy)
278  pushBack(e);
279  }
280 
281  Stactor(Stactor &&move) noexcept
282  : Stactor(static_cast<const Stactor &>(move))
283  {
284  }
285 
286  Stactor &operator=(const Stactor &that)
287  {
288  Base::clear();
289  for (const auto &e : that)
290  pushBack(e);
291  }
292 
293  Stactor &operator=(Stactor &&that) noexcept
294  {
295  *this = static_cast<const Stactor &>(that);
296  return *this;
297  }
298 };
299 
300 
301 
302 } // namespace util
303 
304 
305 
306 } // namespace saki
307 
308 
309 
310 
311 #endif // SAKI_UTIL_STACTOR_H
void push_back(const T &elem) noexcept
alias to enable std::back_inserter
Definition: stactor.h:196
void push_back(T &&elem) noexcept
alias to enable std::back_inserter
Definition: stactor.h:202
Definition: json.hpp:16563
T value_type
enable std funcs
Definition: stactor.h:62
Definition: stactor.h:50
Definition: ai.cpp:18
Definition: stactor.h:34
Stactor = statically allocated vector.
Definition: stactor.h:247