libwordring
static_vector.hpp
1 #pragma once
2 
3 #include <algorithm>
4 #include <array>
5 #include <cassert>
6 #include <cstdint>
7 #include <initializer_list>
8 #include <iterator>
9 #include <memory>
10 #include <type_traits>
11 
12 namespace wordring
13 {
14  template <typename T, std::size_t N>
16 }
17 
18 namespace wordring::detail
19 {
20  template <typename Container>
22  {
23  template <typename T, std::size_t N>
24  friend class wordring::static_vector;
25 
26  friend class static_vector_iterator<Container const>;
27  friend class static_vector_iterator<std::remove_const_t<Container>>;
28 
29  template <typename Container1, typename Container2>
30  friend auto operator+(static_vector_iterator<Container1> const&, static_vector_iterator<Container2> const&);
31 
32  template <typename Container1>
33  friend static_vector_iterator<Container1> operator+(static_vector_iterator<Container1> const&, std::size_t n);
34 
35  template <typename Container1>
36  friend static_vector_iterator<Container1> operator+(std::size_t n, static_vector_iterator<Container1> const&);
37 
38  template <typename Container1, typename Container2>
39  friend auto operator-(static_vector_iterator<Container1> const&, static_vector_iterator<Container2> const&);
40 
41  template <typename Container1>
42  friend static_vector_iterator<Container1> operator-(static_vector_iterator<Container1> const&, std::size_t n);
43 
44  template <typename Container1, typename Container2>
45  friend bool operator==(static_vector_iterator<Container1> const&, static_vector_iterator<Container2> const&);
46 
47  template <typename Container1, typename Container2>
48  friend bool operator!=(static_vector_iterator<Container1> const&, static_vector_iterator<Container2> const&);
49 
50  template <typename Container1, typename Container2>
51  friend bool operator>(static_vector_iterator<Container1> const&, static_vector_iterator<Container2> const&);
52 
53  template <typename Container1, typename Container2>
54  friend bool operator<(static_vector_iterator<Container1> const&, static_vector_iterator<Container2> const&);
55 
56  template <typename Container1, typename Container2>
57  friend bool operator>=(static_vector_iterator<Container1> const&, static_vector_iterator<Container2> const&);
58 
59  template <typename Container1, typename Container2>
60  friend bool operator<=(static_vector_iterator<Container1> const&, static_vector_iterator<Container2> const&);
61 
62  public:
63  using container = Container;
64 
65  using value_type = typename container::value_type;
66  using size_type = typename container::size_type;
67  using difference_type = typename container::difference_type;
68  using reference = std::conditional_t<std::is_const_v<container>, value_type const&, value_type&>;
69  using const_reference = typename container::const_reference;
70  using pointer = std::conditional_t<std::is_const_v<container>, value_type const*, value_type*>;
71  using const_pointer = typename container::const_pointer;
72 
73  using iterator_category = std::random_access_iterator_tag;
74 
75  public:
76  static_vector_iterator()
77  : m_container(nullptr)
78  , m_position(0)
79  {
80  }
81 
82  static_vector_iterator(container& c, difference_type pos)
83  : m_container(std::addressof(c))
84  , m_position(pos)
85  {
86  }
87 
88  template <typename Container1>
89  static_vector_iterator(static_vector_iterator<Container1> const& rhs)
90  : m_container(rhs.m_container)
91  , m_position(rhs.m_position)
92  {
93  }
94 
95  static_vector_iterator(static_vector_iterator const&) = default;
96 
97  static_vector_iterator(static_vector_iterator&&) = default;
98 
99  ~static_vector_iterator() noexcept = default;
100 
101  template <typename Container1>
102  static_vector_iterator& operator=(static_vector_iterator<Container1> const& rhs)
103  {
104  static_assert(std::is_const_v<container>);
105 
106  m_container = rhs.m_container;
107  m_position = rhs.m_position;
108  return *this;
109  }
110 
111  static_vector_iterator& operator=(static_vector_iterator const&) = default;
112 
113  static_vector_iterator& operator=(static_vector_iterator&&) = default;
114 
115  reference operator*()
116  {
117  return *(m_container->data() + m_position);
118  }
119 
120  const_reference operator*() const { return *(m_container->data() + m_position); }
121 
122  pointer operator->() { return m_container->data() + m_position; }
123 
124  const_pointer operator->() const { return m_container->data() + m_position; }
125 
126  reference operator[](int n) { return *(m_container->data() + m_position + n); }
127 
128  const_reference operator[](int n) const { return *(m_container->data() + m_position + n); }
129 
130  static_vector_iterator& operator++()
131  {
132  assert(static_cast<std::make_unsigned_t<decltype(m_position)>>(m_position) < m_container->size());
133  ++m_position;
134  return *this;
135  }
136 
137  static_vector_iterator operator++(int)
138  {
139  static_vector_iterator result = *this;
140  operator++();
141  return result;
142  }
143 
144  static_vector_iterator& operator--()
145  {
146  assert(static_cast<std::make_unsigned_t<difference_type>>(m_position) <= m_container->size());
147  --m_position;
148  return *this;
149  }
150 
151  static_vector_iterator operator--(int)
152  {
153  static_vector_iterator<container> result = *this;
154  operator--();
155  return result;
156  }
157 
158  static_vector_iterator& operator+=(size_t n)
159  {
160  m_position += n;
161  assert(static_cast<std::make_unsigned_t<difference_type>>(m_position) < m_container->size());
162  return *this;
163  }
164 
165  static_vector_iterator& operator-=(size_t n)
166  {
167  m_position -= n;
168  assert(0 <= m_position);
169  return *this;
170  }
171 
172  protected:
173  container* m_container;
174  difference_type m_position;
175  };
176 
177  template <typename Container1, typename Container2>
178  inline auto operator+(static_vector_iterator<Container1> const& lhs, static_vector_iterator<Container2> const& rhs)
179  {
180  return lhs.m_position + rhs.m_position;
181  }
182 
183  template <typename Container1>
184  inline static_vector_iterator<Container1> operator+(static_vector_iterator<Container1> const& it, std::size_t n)
185  {
186  return static_vector_iterator<Container1>(*it.m_container, it.m_position + n);
187  }
188 
189  template <typename Container1>
190  inline static_vector_iterator<Container1> operator+(std::size_t n, static_vector_iterator<Container1> const& it)
191  {
192  return static_vector_iterator<Container1>(*it.m_container, n + it.m_position);
193  }
194 
195  template <typename Container1, typename Container2>
196  inline auto operator-(static_vector_iterator<Container1> const& lhs, static_vector_iterator<Container2> const& rhs)
197  {
198  return lhs.m_position - rhs.m_position;
199  }
200 
201  template <typename Container1>
202  inline static_vector_iterator<Container1> operator-(static_vector_iterator<Container1> const& it, std::size_t n)
203  {
204  return static_vector_iterator<Container1>(*it.m_container, it.m_position - n);
205  }
206 
207  template <typename Container1, typename Container2>
208  inline bool operator==(static_vector_iterator<Container1> const& lhs, static_vector_iterator<Container2> const& rhs)
209  {
210  return lhs.m_position == rhs.m_position;
211  }
212 
213  template <typename Container1, typename Container2>
214  inline bool operator!=(static_vector_iterator<Container1> const& lhs, static_vector_iterator<Container2> const& rhs)
215  {
216  return !(lhs == rhs);
217  }
218 
219  template <typename Container1, typename Container2>
220  inline bool operator>(static_vector_iterator<Container1> const& lhs, static_vector_iterator<Container2> const& rhs)
221  {
222  return rhs < lhs;
223  }
224 
225  template <typename Container1, typename Container2>
226  inline bool operator<(static_vector_iterator<Container1> const& lhs, static_vector_iterator<Container2> const& rhs)
227  {
228  return rhs.m_position - lhs.m_position > 0;
229  }
230 
231  template <typename Container1, typename Container2>
232  inline bool operator>=(static_vector_iterator<Container1> const& lhs, static_vector_iterator<Container2> const& rhs)
233  {
234  return !(lhs < rhs);
235  }
236 
237  template <typename Container1, typename Container2>
238  inline bool operator<=(static_vector_iterator<Container1> const& lhs, static_vector_iterator<Container2> const& rhs)
239  {
240  return !(lhs > rhs);
241  }
242 }
243 
244 namespace wordring
245 {
246  // ------------------------------------------------------------------------
247  // static_vector
248  // ------------------------------------------------------------------------
249 
256  template <typename T, std::size_t N>
257  class static_vector
258  {
259  template <typename T1, std::size_t N1>
260  friend bool operator==(static_vector<T1, N1> const& lhs, static_vector<T1, N1> const& rhs);
261 
262  template <typename T1, std::size_t N1>
263  friend bool operator!=(static_vector<T1, N1> const& lhs, static_vector<T1, N1> const& rhs);
264 
265  template <typename T1, std::size_t N1>
266  friend bool operator<(static_vector<T1, N1> const& lhs, static_vector<T1, N1> const& rhs);
267 
268  template <typename T1, std::size_t N1>
269  friend bool operator<=(static_vector<T1, N1> const& lhs, static_vector<T1, N1> const& rhs);
270 
271  template <typename T1, std::size_t N1>
272  friend bool operator>(static_vector<T1, N1> const& lhs, static_vector<T1, N1> const& rhs);
273 
274  template <typename T1, std::size_t N1>
275  friend bool operator>=(static_vector<T1, N1> const& lhs, static_vector<T1, N1> const& rhs);
276 
277  protected:
278  using container = std::array<T, N>;
279 
280  public:
281  // メンバ型 -----------------------------------------------------------
282 
283  using value_type = typename container::value_type;
284  using size_type = typename container::size_type;
285  using difference_type = typename container::difference_type;
286  using reference = typename container::reference;
287  using const_reference = typename container::const_reference;
288  using pointer = typename container::pointer;
289  using const_pointer = typename container::const_pointer;
290  using iterator = detail::static_vector_iterator<container>;
291  using const_iterator = detail::static_vector_iterator<container const>;
292  using reverse_iterator = std::reverse_iterator<iterator>;
293  using const_reverse_iterator = std::reverse_iterator<const_iterator>;
294 
295  public:
296  static_vector() noexcept
297  : m_container()
298  , m_size(0)
299  {
300  }
301 
302  static_vector(size_type count, value_type const& value)
303  : m_container()
304  , m_size(count)
305  {
306  assert(count <= N);
307  for (size_type i = 0; i < count; ++i) *(m_container.data() + i) = value;
308  }
309 
310  explicit static_vector(size_type count)
311  : m_container()
312  , m_size(count)
313  {
314  assert(count <= N);
315  for (size_type i = 0; i < count; ++i) *(m_container.data() + i) = value_type();
316  }
317 
318  template <typename InputIterator>
319  static_vector(InputIterator first, InputIterator last)
320  : m_container()
321  , m_size(0)
322  {
323  assert(std::distance(first, last) <= N);
324  for (; first != last; ++m_size) *(m_container.data() + m_size) = *first++;
325  }
326 
327  static_vector(static_vector const&) = default;
328 
329  static_vector(static_vector&&) = default;
330 
331  static_vector(std::initializer_list<value_type> ilist)
332  : m_container()
333  , m_size(0)
334  {
335  assert(ilist.size() <= N);
336  for (auto it = ilist.begin(); it != ilist.end(); ++m_size) *(m_container.data() + m_size) = *it++;
337  }
338 
339  ~static_vector() = default;
340 
341  static_vector& operator=(static_vector const&) = default;
342 
343  static_vector& operator=(static_vector&&) = default;
344 
345  static_vector& operator=(std::initializer_list<value_type> ilist)
346  {
347  assert(ilist.size() <= N);
348  m_size = 0;
349  for (auto it = ilist.begin(); it != ilist.end(); ++m_size) *(m_container.data() + m_size) = *it++;
350 
351  return *this;
352  }
353 
354  void assign(size_type count, value_type const& value)
355  {
356  assert(count <= N);
357  for (m_size = 0; m_size < count; ++m_size) *(m_container.data() + m_size) = value;
358  }
359 
360  template <typename InputIterator>
361  void assign(InputIterator first, InputIterator last)
362  {
363  assert(std::distance(first, last) <= N);
364  for (m_size = 0; first != last; ++m_size) *(m_container.data() + m_size) = *first++;
365  }
366 
367  void assign(std::initializer_list<value_type> ilist)
368  {
369  assert(ilist.size() <= N);
370  m_size = 0;
371  for (auto it = ilist.begin(); it != ilist.end(); ++m_size) *(m_container.data() + m_size) = *it++;
372  }
373 
374  // 要素アクセス --------------------------------------------------------
375 
376  reference at(size_type pos) { return m_container.at(pos); }
377 
378  const_reference at(size_type pos) const { return m_container.at(pos); }
379 
380  reference operator[](size_type pos) { return m_container.operator[](pos); }
381 
382  const_reference operator[](size_type pos) const { return m_container.operator[](pos); }
383 
384  reference front() { return m_container.front(); }
385 
386  const_reference front() const { return m_container.front(); }
387 
388  reference back() { return *(m_container.data() + m_size - 1); }
389 
390  const_reference back() const { return *(m_container.data() + m_size - 1); }
391 
392  pointer data() noexcept { return m_container.data(); }
393 
394  const_pointer data() const noexcept { return m_container.data(); }
395 
396  // イテレータ ----------------------------------------------------------
397 
398  iterator begin() { return iterator(m_container, 0); }
399 
400  const_iterator begin() const { return const_iterator(m_container, 0); }
401 
402  const_iterator cbegin() const { return const_iterator(m_container, 0); }
403 
404  iterator end() { return iterator(m_container, m_size); }
405 
406  const_iterator end() const { return const_iterator(m_container, m_size); }
407 
408  const_iterator cend() const { return const_iterator(m_container, m_size); }
409 
410  reverse_iterator rbegin() { return std::make_reverse_iterator(end()); }
411 
412  const_reverse_iterator rbegin() const { return std::make_reverse_iterator(end()); }
413 
414  const_reverse_iterator crbegin() const { return std::make_reverse_iterator(cend()); }
415 
416  reverse_iterator rend() { return std::make_reverse_iterator(begin()); }
417 
418  const_reverse_iterator rend() const { return std::make_reverse_iterator(begin()); }
419 
420  const_reverse_iterator crend() const { return std::make_reverse_iterator(cbegin()); }
421 
422  // 容量 ---------------------------------------------------------------
423 
424  bool empty() const noexcept { return m_size == 0; }
425 
426  size_type size() const noexcept { return m_size; }
427 
428  size_type max_size() const noexcept { return N; }
429 
430  size_type capacity() const noexcept { return N; }
431 
432  // 変更 ---------------------------------------------------------------
433 
434  void clear() noexcept { m_size = 0; }
435 
436  iterator insert(const_iterator pos, value_type const& value)
437  {
438  assert(size() < N);
439 
440  std::copy_backward(pos, cend(), end() + 1);
441  *(m_container.data() + pos.m_position) = value;
442  ++m_size;
443 
444  return iterator(m_container, pos.m_position);
445  }
446 
447  iterator insert(const_iterator pos, value_type&& value)
448  {
449  assert(size() < N);
450 
451  std::copy_backward(pos, cend(), end() + 1);
452  *(m_container.data() + pos.m_position) = std::move(value);
453  ++m_size;
454 
455  return iterator(m_container, pos.m_position);
456  }
457 
458  iterator insert(const_iterator pos, size_type count, value_type const& value)
459  {
460  assert(size() + count <= N);
461 
462  std::copy_backward(pos, cend(), end() + count);
463 
464  iterator p(m_container, pos.m_position);
465  for (const_iterator last = pos + count; p != last; ++p) *p = value;
466 
467  m_size += count;
468 
469  return iterator(m_container, pos.m_position);
470  }
471 
472  template <typename InputIterator>
473  iterator insert(const_iterator pos, InputIterator first, InputIterator last)
474  {
475  size_type count = std::distance(first, last);
476 
477  assert(size() + count <= N);
478 
479  std::copy_backward(pos, cend(), end() + count);
480 
481  iterator p(m_container, pos.m_position);
482  for (const_iterator last = pos + count; p != last; ++p) *p = *first++;
483 
484  m_size += count;
485 
486  return iterator(m_container, pos.m_position);;
487  }
488 
489  iterator insert(const_iterator pos, std::initializer_list<value_type> ilist)
490  {
491  assert(size() + ilist.size() <= N);
492 
493  std::copy_backward(pos, cend(), end() + ilist.size());
494 
495  iterator p(m_container, pos.m_position);
496  auto it = ilist.begin();
497  while (it != ilist.end()) *p++ = *it++;
498 
499  m_size += ilist.size();
500 
501  return iterator(m_container, pos.m_position);
502  }
503 
504  iterator erase(const_iterator pos)
505  {
506  assert(pos != cend());
507 
508  iterator p(m_container, pos.m_position);
509  std::copy(pos + 1, cend(), p);
510 
511  --m_size;
512 
513  return iterator(m_container, pos.m_position);
514  }
515 
516  iterator erase(const_iterator first, const_iterator last)
517  {
518  assert(first != cend());
519  assert(first <= last);
520 
521  std::copy(last, cend(), iterator(m_container, first.m_position));
522  m_size -= std::distance(first, last);
523 
524  return iterator(m_container, first.m_position);
525  }
526 
527  void push_back(value_type const& value)
528  {
529  assert(m_size < m_container.size());
530 
531  *(m_container.data() + m_size) = value;
532  ++m_size;
533  }
534 
535  void push_back(value_type&& value)
536  {
537  assert(m_size < m_container.size());
538 
539  *(m_container.data() + m_size) = std::move(value);
540  ++m_size;
541  }
542 
543  void pop_back()
544  {
545  assert(m_size != 0);
546 
547  erase(--cend());
548  }
549 
550  void resize(size_type count)
551  {
552  resize(count, value_type());
553  }
554 
555  void resize(size_type count, value_type const& value)
556  {
557  assert(count <= m_container.max_size());
558 
559  if (count < m_size) erase(const_iterator(m_container, count), cend());
560  else if(m_size < count) insert(cend(), count - m_size, value);
561  }
562 
563  void swap(static_vector& other)
564  {
565  m_container.swap(other.m_container);
566  std::swap(m_size, other.m_size);
567  }
568 
569  protected:
570  container m_container;
571  size_type m_size;
572  };
573 
574  template <typename T1, std::size_t N1>
575  inline bool operator==(static_vector<T1, N1> const& lhs, static_vector<T1, N1> const& rhs)
576  {
577  return std::equal(lhs.cbegin(), lhs.cend(), rhs.cbegin(), rhs.cend());
578  }
579 
580  template <typename T1, std::size_t N1>
581  inline bool operator!=(static_vector<T1, N1> const& lhs, static_vector<T1, N1> const& rhs)
582  {
583  return !(lhs == rhs);
584  }
585 
586  template <typename T1, std::size_t N1>
587  inline bool operator<(static_vector<T1, N1> const& lhs, static_vector<T1, N1> const& rhs)
588  {
589  return std::lexicographical_compare(lhs.cbegin(), lhs.cend(), rhs.cbegin(), rhs.cend());
590  }
591 
592  template <typename T1, std::size_t N1>
593  inline bool operator<=(static_vector<T1, N1> const& lhs, static_vector<T1, N1> const& rhs)
594  {
595  return lhs < rhs || lhs == rhs;
596  }
597 
598  template <typename T1, std::size_t N1>
599  inline bool operator>(static_vector<T1, N1> const& lhs, static_vector<T1, N1> const& rhs)
600  {
601  return std::lexicographical_compare(rhs.cbegin(), rhs.cend(), lhs.cbegin(), lhs.cend());
602  }
603 
604  template <typename T1, std::size_t N1>
605  inline bool operator>=(static_vector<T1, N1> const& lhs, static_vector<T1, N1> const& rhs)
606  {
607  return lhs > rhs || lhs == rhs;
608  }
609 
610 }
wordring::static_vector
最大長固定の静的vector
Definition: static_vector.hpp:15
wordring
Definition: algorithm_.hpp:10
wordring::detail
wordring::html::operator==
bool operator==(simple_attr< String1 > const &lhs, simple_attr< String1 > const &rhs)
名前空間、接頭辞、ローカル名が一致する場合、true を返す
Definition: simple_node.hpp:168
wordring::detail::static_vector_iterator
Definition: static_vector.hpp:21