scnlib  0.2.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
small_vector.h
Go to the documentation of this file.
1 // Copyright 2017-2019 Elias Kosunen
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 //
15 // This file is a part of scnlib:
16 // https://github.com/eliaskosunen/scnlib
17 
18 #ifndef SCN_DETAIL_SMALL_VECTOR_H
19 #define SCN_DETAIL_SMALL_VECTOR_H
20 
21 #include "util.h"
22 
23 #include <cstring>
24 #include <iterator>
25 #include <limits>
26 #include <new>
27 
28 namespace scn {
30 
31  namespace detail {
32  template <typename Iter>
33  std::reverse_iterator<Iter> make_reverse_iterator(Iter i)
34  {
35  return std::reverse_iterator<Iter>(i);
36  }
37 
38  namespace small_vector_algos {
39  template <typename ForwardIt, typename T>
40  void uninitialized_fill(ForwardIt first,
41  ForwardIt last,
42  const T& value,
43  std::true_type) noexcept
44  {
45  auto dist = static_cast<size_t>(std::distance(first, last));
46  std::memset(&*first, static_cast<unsigned char>(value), dist);
47  }
48  template <typename ForwardIt, typename T>
49  void uninitialized_fill(ForwardIt first,
50  ForwardIt last,
51  const T& value,
52  std::false_type) noexcept
53  {
54  using value_type =
55  typename std::iterator_traits<ForwardIt>::value_type;
56  ForwardIt current = first;
57  for (; current != last; ++current) {
58  ::new (static_cast<void*>(std::addressof(*current)))
59  value_type(value);
60  }
61  }
62  template <typename ForwardIt, typename T>
63  void uninitialized_fill(ForwardIt first,
64  ForwardIt last,
65  const T& value) noexcept
66  {
67  return uninitialized_fill(
68  first, last, value, std::integral_constant < bool,
69  std::is_trivially_copyable<T>::value&&
70  std::is_pointer<ForwardIt>::value &&
71  sizeof(T) == 1 > {});
72  }
73 
74  template <typename ForwardIt>
76  ForwardIt last) noexcept
77  {
78  using value_type =
79  typename std::iterator_traits<ForwardIt>::value_type;
80  ForwardIt current = first;
81  for (; current != last; ++current) {
82  ::new (static_cast<void*>(std::addressof(*current)))
83  value_type;
84  }
85  }
86  template <typename ForwardIt>
87  void uninitialized_fill_value_init(ForwardIt first,
88  ForwardIt last) noexcept
89  {
90  using value_type =
91  typename std::iterator_traits<ForwardIt>::value_type;
92  ForwardIt current = first;
93  for (; current != last; ++current) {
94  ::new (static_cast<void*>(std::addressof(*current)))
95  value_type();
96  }
97  }
98 
99  template <typename InputIt,
100  typename ForwardIt,
101  typename std::enable_if<!std::is_trivially_copyable<
102  typename std::iterator_traits<
103  ForwardIt>::value_type>::value>::type* = nullptr>
104  ForwardIt uninitialized_copy(InputIt first,
105  InputIt last,
106  ForwardIt d_first) noexcept
107  {
108  using value_type =
109  typename std::iterator_traits<ForwardIt>::value_type;
110  ForwardIt current = d_first;
111  for (; first != last; ++first, (void)++current) {
112  ::new (static_cast<void*>(std::addressof(*current)))
113  value_type(*first);
114  }
115  return current;
116  }
117  template <typename InputIt,
118  typename ForwardIt,
119  typename std::enable_if<std::is_trivially_copyable<
120  typename std::iterator_traits<
121  ForwardIt>::value_type>::value>::type* = nullptr>
122  ForwardIt uninitialized_copy(InputIt first,
123  InputIt last,
124  ForwardIt d_first) noexcept
125  {
126  using pointer =
127  typename std::iterator_traits<ForwardIt>::pointer;
128  auto ptr = std::memcpy(
129  std::addressof(*d_first), std::addressof(*first),
130  static_cast<size_t>(std::distance(first, last)));
131  return ForwardIt{static_cast<pointer>(ptr)};
132  }
133 
134  template <typename InputIt,
135  typename ForwardIt,
136  typename std::enable_if<!std::is_trivially_copyable<
137  typename std::iterator_traits<
138  ForwardIt>::value_type>::value>::type* = nullptr>
139  ForwardIt uninitialized_move(InputIt first,
140  InputIt last,
141  ForwardIt d_first) noexcept
142  {
143  using value_type =
144  typename std::iterator_traits<ForwardIt>::value_type;
145  ForwardIt current = d_first;
146  for (; first != last; ++first, (void)++current) {
147  ::new (static_cast<void*>(std::addressof(*current)))
148  value_type(std::move(*first));
149  }
150  return current;
151  }
152  template <typename InputIt,
153  typename ForwardIt,
154  typename std::enable_if<std::is_trivially_copyable<
155  typename std::iterator_traits<
156  ForwardIt>::value_type>::value>::type* = nullptr>
157  ForwardIt uninitialized_move(InputIt first,
158  InputIt last,
159  ForwardIt d_first) noexcept
160  {
161  using pointer =
162  typename std::iterator_traits<ForwardIt>::pointer;
163  auto ptr = std::memcpy(
164  std::addressof(*d_first), std::addressof(*first),
165  static_cast<size_t>(std::distance(first, last)));
166  return ForwardIt(static_cast<pointer>(ptr));
167  }
168  } // namespace small_vector_algos
169 
171  uint64_t _next_pow2_64(uint64_t x)
172  {
173  --x;
174  x |= (x >> 1);
175  x |= (x >> 2);
176  x |= (x >> 4);
177  x |= (x >> 8);
178  x |= (x >> 16);
179  x |= (x >> 32);
180  return x + 1;
181  }
182  uint32_t _next_pow2_32(uint32_t x)
183  {
184  --x;
185  x |= (x >> 1);
186  x |= (x >> 2);
187  x |= (x >> 4);
188  x |= (x >> 8);
189  x |= (x >> 16);
190  return x + 1;
191  }
192 
193  protected:
194  size_t next_pow2(size_t x)
195  {
197  SCN_MSVC_IGNORE(4127) // conditional expression is constant
198  if (sizeof(size_t) == sizeof(uint64_t)) {
199  return static_cast<size_t>(
200  _next_pow2_64(static_cast<uint64_t>(x)));
201  }
203  return static_cast<size_t>(
204  _next_pow2_32(static_cast<uint32_t>(x)));
205  }
206  };
207 
209  SCN_CLANG_IGNORE("-Wpadded")
210 
211  template <typename T, size_t N>
213  alignas(T) unsigned char data[N * sizeof(T)];
214 
216  {
217  return ::scn::detail::launder(reinterpret_unconstructed_data());
218  }
219  const T* reinterpret_data() const
220  {
221  return ::scn::detail::launder(reinterpret_unconstructed_data());
222  }
223 
225  {
226  return static_cast<T*>(static_cast<void*>(data));
227  }
229  {
230  return static_cast<const T*>(static_cast<const void*>(data));
231  }
232 
233  unsigned char* get_unconstructed_data()
234  {
235  return data;
236  }
237  const unsigned char* get_unconstructed_data() const
238  {
239  return data;
240  }
241  };
242 
244 
245  template <typename T>
246  struct basic_stack_storage<T, 0> {
247  T* data{nullptr};
248 
250  {
251  return nullptr;
252  }
253  const T* reinterpret_data() const
254  {
255  return nullptr;
256  }
257 
259  {
260  return nullptr;
261  }
263  {
264  return nullptr;
265  }
266 
267  unsigned char* get_unconstructed_data()
268  {
269  return nullptr;
270  }
271  const unsigned char* get_unconstructed_data() const
272  {
273  return nullptr;
274  }
275  };
276 
277  template <typename T>
278  constexpr T constexpr_max(T val)
279  {
280  return val;
281  }
282  template <typename T, typename... Ts>
283  constexpr T constexpr_max(T val, Ts... a)
284  {
285  return val > constexpr_max(a...) ? val : constexpr_max(a...);
286  }
287 
289  SCN_CLANG_IGNORE("-Wpadded")
290 
291  template <typename T, size_t StackN>
292  class small_vector : protected small_vector_base {
293  public:
294  using value_type = T;
295  using size_type = size_t;
296  using difference_type = std::ptrdiff_t;
297  using reference = T&;
298  using const_reference = const T&;
299  using pointer = T*;
300  using const_pointer = const T*;
301  using iterator = pointer;
303  using reverse_iterator = std::reverse_iterator<pointer>;
304  using const_reverse_iterator = std::reverse_iterator<const_pointer>;
305 
306  struct stack_storage : basic_stack_storage<T, StackN> {
307  };
308  struct heap_storage {
309  size_type cap{0};
310  };
311 
312  small_vector() noexcept
313  : m_ptr(_construct_stack_storage()
314  .reinterpret_unconstructed_data())
315  {
317  SCN_MSVC_IGNORE(4127) // conditional expression is constant
318 
319  if (StackN == 0) {
320  _destruct_stack_storage();
321  _construct_heap_storage();
322  }
323 
325 
326  SCN_ENSURE(size() == 0);
327  }
328 
329  explicit small_vector(size_type count, const T& value)
330  {
331  if (!can_be_small(count)) {
332  auto& heap = _construct_heap_storage();
333  auto cap = next_pow2(count);
334  auto storage_ptr = new unsigned char[count * sizeof(T)];
335  auto ptr =
336  static_cast<pointer>(static_cast<void*>(storage_ptr));
338  value);
339 
340  heap.cap = cap;
341  m_size = count;
342  m_ptr = ::scn::detail::launder(ptr);
343  }
344  else {
345  auto& stack = _construct_stack_storage();
347  stack.reinterpret_unconstructed_data(),
348  stack.reinterpret_unconstructed_data() + StackN, value);
349  m_size = count;
350  m_ptr = stack.reinterpret_data();
351  }
352 
353  SCN_ENSURE(data());
354  SCN_ENSURE(size() == count);
355  SCN_ENSURE(capacity() >= size());
356  }
357 
358  explicit small_vector(size_type count)
359  {
360  if (!can_be_small(count)) {
361  auto& heap = _construct_heap_storage();
362  auto cap = next_pow2(count);
363  auto storage_ptr = new unsigned char[count * sizeof(T)];
364  auto ptr =
365  static_cast<pointer>(static_cast<void*>(storage_ptr));
367  ptr, ptr + count);
368  heap.cap = cap;
369  m_size = count;
370  m_ptr = ::scn::detail::launder(ptr);
371  }
372  else {
373  auto& stack = _construct_stack_storage();
375  stack.reinterpret_unconstructed_data(),
376  stack.reinterpret_unconstructed_data() + count);
377  m_size = count;
378  m_ptr = stack.reinterpret_data();
379  }
380 
381  SCN_ENSURE(data());
382  SCN_ENSURE(size() == count);
383  SCN_ENSURE(capacity() >= size());
384  }
385 
387  {
388  if (other.empty()) {
389  auto& stack = _construct_stack_storage();
390  m_ptr = stack.reinterpret_unconstructed_data();
391  return;
392  }
393 
394  auto s = other.size();
395  if (!other.is_small()) {
396  auto& heap = _construct_heap_storage();
397  auto cap = other.capacity();
398  auto optr = other.data();
399 
400  auto storage_ptr = new unsigned char[cap * sizeof(T)];
401  auto ptr =
402  static_cast<pointer>(static_cast<void*>(storage_ptr));
403  small_vector_algos::uninitialized_copy(optr, optr + s, ptr);
404 
405  m_ptr = ::scn::detail::launder(ptr);
406  m_size = s;
407  heap.cap = cap;
408  }
409  else {
410  auto& stack = _construct_stack_storage();
411  auto optr = other.data();
413  optr, optr + s, stack.reinterpret_unconstructed_data());
414  m_size = s;
415  m_ptr = stack.reinterpret_data();
416  }
417 
418  SCN_ENSURE(data());
419  SCN_ENSURE(other.data());
420  SCN_ENSURE(other.size() == size());
421  SCN_ENSURE(other.capacity() == capacity());
422  }
423  small_vector(small_vector&& other) noexcept
424  {
425  if (other.empty()) {
426  auto& stack = _construct_stack_storage();
427  m_ptr = stack.reinterpret_unconstructed_data();
428  return;
429  }
430 
431  auto s = other.size();
432  if (!other.is_small()) {
433  auto& heap = _construct_heap_storage();
434  m_ptr = other.data();
435 
436  m_size = s;
437  heap.cap = other.capacity();
438  }
439  else {
440  auto& stack = _construct_stack_storage();
441  auto optr = other.data();
443  optr, optr + s, stack.reinterpret_unconstructed_data());
444 
445  m_size = s;
446  other._destruct_elements();
447  }
448  other.m_ptr = nullptr;
449 
450  SCN_ENSURE(data());
451  }
452 
454  {
455  _destruct_elements();
456 
457  if (other.empty()) {
458  return *this;
459  }
460 
461  SCN_ASSERT(size() == 0, "");
462 
463  // this other
464  // s s false || true
465  // s h false || false second
466  // h s true || true
467  // h h true || false
468  if (!is_small() || other.is_small()) {
470  other.data(), other.data() + other.size(), data());
471  m_ptr = ::scn::detail::launder(data());
472  m_size = other.size();
473  if (!other.is_small()) {
474  _get_heap().cap = other.capacity();
475  }
476  }
477  else {
478  _destruct_stack_storage();
479  auto& heap = _construct_heap_storage();
480 
481  auto cap = next_pow2(other.size());
482  auto storage_ptr = new unsigned char[cap * sizeof(T)];
483  auto ptr =
484  static_cast<pointer>(static_cast<void*>(storage_ptr));
486  other.data(), other.data() + other.size(), ptr);
487  m_ptr = ::scn::detail::launder(ptr);
488  m_size = other.size();
489  heap.cap = cap;
490  }
491  return *this;
492  }
493 
495  {
496  _destruct_elements();
497 
498  if (other.empty()) {
499  return *this;
500  }
501 
502  SCN_ASSERT(size() == 0, "");
503 
504  if (!is_small() && !other.is_small()) {
505  if (!is_small()) {
506  if (capacity() != 0) {
507  delete[] ::scn::detail::launder(
508  static_cast<unsigned char*>(
509  static_cast<void*>(m_ptr)));
510  }
511  }
512 
513  m_ptr = other.data();
514  m_size = other.size();
515  _get_heap().cap = other.capacity();
516  }
517  else if (!is_small() || other.is_small()) {
519  other.data(), other.data() + other.size(), data());
520  m_size = other.size();
521  other._destruct_elements();
522  }
523  else {
524  _destruct_stack_storage();
525  auto& heap = _construct_heap_storage();
526 
527  m_ptr = other.data();
528  m_size = other.size();
529  heap.cap = other.capacity();
530  }
531 
532  other.m_ptr = nullptr;
533 
534  return *this;
535  }
536 
538  {
539  _destruct();
540  }
541 
542  pointer data() noexcept
543  {
544  return m_ptr;
545  }
546  const_pointer data() const noexcept
547  {
548  return m_ptr;
549  }
550  size_type size() const noexcept
551  {
552  return m_size;
553  }
554  size_type capacity() const noexcept
555  {
556  if (SCN_LIKELY(is_small())) {
557  return StackN;
558  }
559  return _get_heap().cap;
560  }
561 
562  bool empty() const noexcept
563  {
564  return size() == 0;
565  }
566 
567  constexpr bool is_small() const noexcept
568  {
569  // oh so very ub
570  return m_ptr == reinterpret_cast<const_pointer>(
571  std::addressof(m_stack_storage));
572  }
573  constexpr static bool can_be_small(size_type n) noexcept
574  {
575  return n <= StackN;
576  }
577 
579  {
580  SCN_EXPECT(pos < size());
581  return *(begin() + pos);
582  }
583  constexpr const_reference operator[](size_type pos) const
584  {
585  SCN_EXPECT(pos < size());
586  return *(begin() + pos);
587  }
588 
590  {
591  SCN_EXPECT(!empty());
592  return *begin();
593  }
594  constexpr const_reference front() const
595  {
596  SCN_EXPECT(!empty());
597  return *begin();
598  }
599 
601  {
602  SCN_EXPECT(!empty());
603  return *(end() - 1);
604  }
605  constexpr const_reference back() const
606  {
607  SCN_EXPECT(!empty());
608  return *(end() - 1);
609  }
610 
612  {
613  return data();
614  }
615  constexpr const_iterator begin() const noexcept
616  {
617  return data();
618  }
619  constexpr const_iterator cbegin() const noexcept
620  {
621  return begin();
622  }
623 
625  {
626  return begin() + size();
627  }
628  constexpr const_iterator end() const noexcept
629  {
630  return begin() + size();
631  }
632  constexpr const_iterator cend() const noexcept
633  {
634  return end();
635  }
636 
638  {
639  return make_reverse_iterator(end());
640  }
641  constexpr const_reverse_iterator rbegin() const noexcept
642  {
643  return make_reverse_iterator(end());
644  }
645  constexpr const_reverse_iterator crbegin() const noexcept
646  {
647  return rbegin();
648  }
649 
651  {
652  return make_reverse_iterator(begin());
653  }
654  constexpr const_reverse_iterator rend() const noexcept
655  {
656  return make_reverse_iterator(begin());
657  }
658  constexpr const_reverse_iterator crend() const noexcept
659  {
660  return rend();
661  }
662 
663  constexpr size_type max_size() const noexcept
664  {
666  }
667 
668  void make_small() noexcept
669  {
670  if (is_small() || !can_be_small(size())) {
671  return;
672  }
673 
674  stack_storage s;
677  auto tmp_size = size();
678 
679  _destruct();
680  auto& stack = _construct_stack_storage();
682  s.reinterpret_data(), s.reinterpret_data() + tmp_size,
683  stack.reinterpret_unconstructed_data());
684  m_size = tmp_size;
685  }
686 
687  void reserve(size_type new_cap)
688  {
689  if (new_cap <= capacity()) {
690  return;
691  }
692  _realloc(next_pow2(new_cap));
693  }
694 
696  {
697  if (is_small()) {
698  return;
699  }
700  if (!can_be_small(size())) {
701  _realloc(size());
702  }
703  else {
704  make_small();
705  }
706  }
707 
708  void clear() noexcept
709  {
710  _destruct_elements();
711  }
712 
714  {
715  if (pos == end()) {
716  pos->~T();
717  m_size = size() - 1;
718  return end();
719  }
720  else {
721  for (auto it = pos; it != end(); ++it) {
722  it->~T();
723  ::new (static_cast<void*>(it)) T(std::move(*(it + 1)));
724  }
725  (end() - 1)->~T();
726  m_size = size() - 1;
727  return pos;
728  }
729  }
730 
732  {
733  if (begin() == end()) {
734  return b;
735  }
736  if (e == end()) {
737  auto n = static_cast<size_t>(std::distance(b, e));
738  for (auto it = b; it != e; ++it) {
739  it->~T();
740  }
741  m_size = size() - n;
742  return end();
743  }
744  SCN_ENSURE(false);
746  }
747 
748  void push_back(const T& value)
749  {
750  ::new (_prepare_push_back()) T(value);
751  m_size = size() + 1;
752  }
753  void push_back(T&& value)
754  {
755  ::new (_prepare_push_back()) T(std::move(value));
756  m_size = size() + 1;
757  }
758 
759  template <typename... Args>
760  reference emplace_back(Args&&... args)
761  {
762  ::new (_prepare_push_back()) T(std::forward<Args>(args)...);
763  m_size = size() + 1;
764  return back();
765  }
766 
767  void pop_back()
768  {
769  back().~T();
770  m_size = size() - 1;
771  }
772 
773  void resize(size_type count)
774  {
775  if (count > size()) {
776  if (count > capacity()) {
777  _realloc(next_pow2(capacity()));
778  }
780  begin() + size(), begin() + count);
781  }
782  else {
783  for (auto it = begin() + count; it != end(); ++it) {
784  it->~T();
785  }
786  }
787  m_size = count;
788  }
789 
790  SCN_CONSTEXPR14 void swap(small_vector& other) noexcept
791  {
792  small_vector tmp{std::move(other)};
793  other = std::move(*this);
794  *this = std::move(tmp);
795  }
796 
797  private:
798  stack_storage& _construct_stack_storage() noexcept
799  {
800  ::new (std::addressof(m_stack_storage)) stack_storage;
801  m_ptr = m_stack_storage.reinterpret_unconstructed_data();
802  return m_stack_storage;
803  }
804  heap_storage& _construct_heap_storage() noexcept
805  {
806  ::new (std::addressof(m_heap_storage)) heap_storage;
807  m_ptr = nullptr;
808  return m_heap_storage;
809  }
810 
811  void _destruct_stack_storage() noexcept
812  {
813  _get_stack().~stack_storage();
814  }
815  void _destruct_heap_storage() noexcept
816  {
817  if (capacity() != 0) {
818  delete[] static_cast<unsigned char*>(
819  static_cast<void*>(m_ptr));
820  }
821  _get_heap().~heap_storage();
822  }
823 
824  void _destruct_elements() noexcept
825  {
826  const auto s = size();
827  for (size_type i = 0; i != s; ++i) {
828  m_ptr[i].~T();
829  }
830  m_size = 0;
831  }
832 
833  void _destruct() noexcept
834  {
835  _destruct_elements();
836  if (SCN_UNLIKELY(!is_small())) {
837  _destruct_heap_storage();
838  }
839  else {
840  _destruct_stack_storage();
841  }
842  }
843 
844  void _realloc(size_type new_cap)
845  {
846  auto storage_ptr = new unsigned char[new_cap * sizeof(T)];
847  auto ptr =
848  static_cast<pointer>(static_cast<void*>(storage_ptr));
849  auto n = size();
851  _destruct();
852  auto& heap = [this]() -> heap_storage& {
853  if (is_small()) {
854  return _construct_heap_storage();
855  }
856  return _get_heap();
857  }();
858  m_ptr = ptr;
859  m_size = n;
860  heap.cap = new_cap;
861  }
862 
863  void* _prepare_push_back()
864  {
865  if (SCN_UNLIKELY(size() == capacity())) {
866  _realloc(next_pow2(size() + 1));
867  }
868  return m_ptr + size();
869  }
870 
871  stack_storage& _get_stack() noexcept
872  {
873  return m_stack_storage;
874  }
875  const stack_storage& _get_stack() const noexcept
876  {
877  return m_stack_storage;
878  }
879 
880  heap_storage& _get_heap() noexcept
881  {
882  return m_heap_storage;
883  }
884  const heap_storage& _get_heap() const noexcept
885  {
886  return m_heap_storage;
887  }
888 
889  pointer m_ptr{nullptr};
890  size_type m_size{0};
891  union {
892  stack_storage m_stack_storage;
893  heap_storage m_heap_storage;
894  };
895  };
896 
897  template <typename T, size_t N>
900  small_vector<T, N>& r) noexcept(noexcept(l.swap(r)))
901  {
902  l.swap(r);
903  }
904 
906  } // namespace detail
907 
909 } // namespace scn
910 
911 #endif // SCN_DETAIL_SMALL_VECTOR_H
const T * reinterpret_data() const
Definition: small_vector.h:219
size_type size() const noexcept
Definition: small_vector.h:550
const unsigned char * get_unconstructed_data() const
Definition: small_vector.h:237
iterator erase(iterator b, iterator e)
Definition: small_vector.h:731
constexpr const_iterator cend() const noexcept
Definition: small_vector.h:632
void resize(size_type count)
Definition: small_vector.h:773
constexpr size_type max_size() const noexcept
Definition: small_vector.h:663
#define SCN_END_NAMESPACE
Definition: config.h:401
void size(T &&)=delete
#define SCN_UNLIKELY(x)
Definition: config.h:362
pointer data() noexcept
Definition: small_vector.h:542
small_vector(size_type count)
Definition: small_vector.h:358
constexpr T constexpr_max(T val)
Definition: small_vector.h:278
SCN_CONSTEXPR14 reverse_iterator rbegin() noexcept
Definition: small_vector.h:637
void push_back(const T &value)
Definition: small_vector.h:748
#define SCN_UNREACHABLE
Definition: config.h:347
constexpr const_reference back() const
Definition: small_vector.h:605
#define SCN_MSVC_PUSH
Definition: config.h:155
#define SCN_CLANG_IGNORE(x)
Definition: config.h:144
constexpr T max(T a, T b) noexcept
Definition: util.h:509
constexpr const_reverse_iterator crbegin() const noexcept
Definition: small_vector.h:645
SCN_CONSTEXPR14 iterator begin() noexcept
Definition: small_vector.h:611
void reserve(size_type new_cap)
Definition: small_vector.h:687
constexpr const_reverse_iterator rend() const noexcept
Definition: small_vector.h:654
iterator erase(iterator pos)
Definition: small_vector.h:713
void uninitialized_fill_value_init(ForwardIt first, ForwardIt last) noexcept
Definition: small_vector.h:87
std::ptrdiff_t difference_type
Definition: small_vector.h:296
const_pointer data() const noexcept
Definition: small_vector.h:546
size_type capacity() const noexcept
Definition: small_vector.h:554
constexpr const_reverse_iterator crend() const noexcept
Definition: small_vector.h:658
#define SCN_CLANG_POP
Definition: config.h:143
constexpr T * launder(T *p) noexcept
Definition: util.h:486
small_vector(size_type count, const T &value)
Definition: small_vector.h:329
SCN_CONSTEXPR14 void swap(small_vector< T, N > &l, small_vector< T, N > &r) noexcept(noexcept(l.swap(r)))
Definition: small_vector.h:898
small_vector & operator=(const small_vector &other)
Definition: small_vector.h:453
const_pointer const_iterator
Definition: small_vector.h:302
const unsigned char * get_unconstructed_data() const
Definition: small_vector.h:271
unsigned char * get_unconstructed_data()
Definition: small_vector.h:233
constexpr bool is_small() const noexcept
Definition: small_vector.h:567
const T * reinterpret_unconstructed_data() const
Definition: small_vector.h:228
reference emplace_back(Args &&...args)
Definition: small_vector.h:760
void uninitialized_fill_default_construct(ForwardIt first, ForwardIt last) noexcept
Definition: small_vector.h:75
bool empty() const noexcept
Definition: small_vector.h:562
#define SCN_MSVC_IGNORE(x)
Definition: config.h:157
#define SCN_BEGIN_NAMESPACE
Definition: config.h:400
#define SCN_ENSURE(cond)
Definition: config.h:397
constexpr const_reference front() const
Definition: small_vector.h:594
const T * reinterpret_unconstructed_data() const
Definition: small_vector.h:262
SCN_CONSTEXPR14 iterator end() noexcept
Definition: small_vector.h:624
stack_storage m_stack_storage
Definition: small_vector.h:892
std::reverse_iterator< const_pointer > const_reverse_iterator
Definition: small_vector.h:304
std::reverse_iterator< Iter > make_reverse_iterator(Iter i)
Definition: small_vector.h:33
SCN_CONSTEXPR14 void swap(small_vector &other) noexcept
Definition: small_vector.h:790
ForwardIt uninitialized_move(InputIt first, InputIt last, ForwardIt d_first) noexcept
Definition: small_vector.h:139
void push_back(T &&value)
Definition: small_vector.h:753
#define SCN_MSVC_POP
Definition: config.h:156
small_vector(const small_vector &other)
Definition: small_vector.h:386
constexpr const_reference operator[](size_type pos) const
Definition: small_vector.h:583
ForwardIt uninitialized_copy(InputIt first, InputIt last, ForwardIt d_first) noexcept
Definition: small_vector.h:104
constexpr const_reverse_iterator rbegin() const noexcept
Definition: small_vector.h:641
void end(T &&)=delete
void uninitialized_fill(ForwardIt first, ForwardIt last, const T &value, std::true_type) noexcept
Definition: small_vector.h:40
SCN_CONSTEXPR14 reference back()
Definition: small_vector.h:600
void begin(T &&)=delete
constexpr const_iterator cbegin() const noexcept
Definition: small_vector.h:619
SCN_CONSTEXPR14 reference front()
Definition: small_vector.h:589
constexpr const_iterator begin() const noexcept
Definition: small_vector.h:615
#define SCN_LIKELY(x)
Definition: config.h:361
void make_small() noexcept
Definition: small_vector.h:668
SCN_CONSTEXPR14 reference operator[](size_type pos)
Definition: small_vector.h:578
small_vector(small_vector &&other) noexcept
Definition: small_vector.h:423
SCN_CONSTEXPR14 reverse_iterator rend() noexcept
Definition: small_vector.h:650
std::reverse_iterator< pointer > reverse_iterator
Definition: small_vector.h:303
small_vector & operator=(small_vector &&other) noexcept
Definition: small_vector.h:494
static constexpr bool can_be_small(size_type n) noexcept
Definition: small_vector.h:573
#define SCN_ASSERT(cond, msg)
Definition: config.h:395
constexpr const_iterator end() const noexcept
Definition: small_vector.h:628
#define SCN_EXPECT(cond)
Definition: config.h:396
#define SCN_CLANG_PUSH
Definition: config.h:142
#define SCN_CONSTEXPR14
Definition: config.h:240