MRPT  2.0.0
vector_with_small_size_optimization.h
Go to the documentation of this file.
1 /* +------------------------------------------------------------------------+
2  | Mobile Robot Programming Toolkit (MRPT) |
3  | https://www.mrpt.org/ |
4  | |
5  | Copyright (c) 2005-2020, Individual contributors, see AUTHORS file |
6  | See: https://www.mrpt.org/Authors - All rights reserved. |
7  | Released under BSD License. See: https://www.mrpt.org/License |
8  +------------------------------------------------------------------------+ */
9 #pragma once
10 
11 #include <mrpt/core/aligned_allocator.h> // aligned_allocator_cpp11
12 #include <array>
13 #include <cstddef> // size_t
14 #include <type_traits> // conditional_t, ...
15 #include <vector>
16 
17 namespace mrpt::containers
18 {
20 {
21  operator const bool&() const { return b; }
22  operator bool&() { return b; }
23 
24  bool b;
25 };
26 
27 /** Container that transparently and dynamically switches between a std::array
28  * and std::vector. Used to avoid heap allocations with small vectors.
29  *
30  * \note In `#include <mrpt/containers/vector_with_small_size_optimization.h>`
31  * \ingroup mrpt_containers_grp
32  */
33 template <typename VAL, size_t small_size, size_t alignment = 16>
35 {
36  private:
37  using T =
38  std::conditional_t<std::is_same_v<VAL, bool>, UnspecializedBool, VAL>;
40  using self_t =
42  using large_vec = std::vector<T, ALLOC>;
43  using small_array = std::array<T, small_size>;
44 
46  alignas(alignment) small_array m_a;
47  bool m_is_small = true;
48  size_t m_size = 0;
49 
50  public:
51  using value_type = T;
52  using reference = T&;
53  using const_reference = const T&;
54  using difference_type = typename large_vec::difference_type;
55  using size_type = typename large_vec::size_type;
56 
59  : m_is_small(n <= small_size), m_size(n)
60  {
61  if (!m_is_small) m_v.resize(n);
62  }
63  template <typename TYPE, typename POINTER, typename REFERENCE>
65  {
66  using STORAGE = std::conditional_t<
67  std::is_same_v<POINTER, bool*>, UnspecializedBool*,
68  std::conditional_t<
69  std::is_same_v<POINTER, const bool*>, const UnspecializedBool*,
70  POINTER>>;
72 
73  public:
74  using value_type = TYPE;
75  using reference = REFERENCE;
76  using pointer = POINTER;
77  using iterator_category = std::random_access_iterator_tag;
78  using difference_type = typename large_vec::difference_type;
79  iteratorImpl() = default;
80  iteratorImpl(STORAGE ptr) : m_ptr(ptr) {}
81  self operator++()
82  {
83  self i = *this;
84  m_ptr++;
85  return i;
86  }
87  self operator--()
88  {
89  self i = *this;
90  m_ptr--;
91  return i;
92  }
93  self operator++(int)
94  {
95  m_ptr++;
96  return *this;
97  }
98  self operator--(int)
99  {
100  m_ptr--;
101  return *this;
102  }
104  {
105  self i = *this;
106  i.m_ptr += n;
107  return i;
108  }
110  {
111  self i = *this;
112  i.m_ptr -= n;
113  return i;
114  }
116  {
117  m_ptr += n;
118  return *this;
119  }
121  {
122  m_ptr -= n;
123  return *this;
124  }
125  difference_type operator-(const self& o) const
126  {
127  return m_ptr - o.m_ptr;
128  }
129  REFERENCE operator*() { return *m_ptr; }
130  const REFERENCE operator*() const { return *m_ptr; }
131  POINTER operator->() { return m_ptr; }
132  const POINTER operator->() const { return m_ptr; }
133  bool operator==(const self& o) { return m_ptr == o.m_ptr; }
134  bool operator!=(const self& o) { return m_ptr != o.m_ptr; }
135 
136  private:
137  STORAGE m_ptr{nullptr};
138  };
139 
140  using iterator = iteratorImpl<VAL, VAL*, VAL&>;
141  using const_iterator = iteratorImpl<VAL, const VAL*, const VAL&>;
142 
144  {
145  if (m_size)
146  {
147  if (m_is_small && n > small_size)
148  {
149  m_v.assign(m_a.begin(), m_a.begin() + m_size);
150  }
151  else if (!m_is_small && n <= small_size)
152  {
153  std::copy(m_v.begin(), m_v.begin() + n, m_a.begin());
154  }
155  }
156  m_size = n;
157  m_is_small = (n <= small_size);
158  if (!m_is_small)
159  {
160  m_v.resize(m_size);
161  }
162  }
163 
164  void fill(const T& v)
165  {
166  if (m_is_small)
167  m_a.fill(v);
168  else
169  m_v.assign(m_v.size(), v);
170  }
171 
172  size_t size() const { return m_size; }
173  bool empty() const { return m_size == 0; }
174 
175  reference operator[](size_type n) { return m_is_small ? m_a[n] : m_v[n]; }
176 
178  {
179  return m_is_small ? m_a[n] : m_v[n];
180  }
181 
183  {
184  return m_is_small ? m_a[m_size - 1] : m_v.back();
185  }
186  reference back() { return m_is_small ? m_a[m_size - 1] : m_v.back(); }
187 
189  {
190  return m_is_small ? m_a.front() : m_v.front();
191  }
192  reference front() { return m_is_small ? m_a.front() : m_v.front(); }
193 
194  void swap(self_t& x)
195  {
196  if (m_is_small && x.m_is_small)
197  {
198  m_a.swap(x.m_a);
199  }
200  else if (!m_is_small && !x.m_is_small)
201  {
202  m_v.swap(x.m_v);
203  }
204  else if (!m_is_small && x.m_is_small)
205  {
206  std::copy(x.m_a.begin(), x.m_a.begin() + x.m_size, m_a.begin());
207  x.m_v.swap(m_v);
208  }
209  else
210  {
211  m_v.swap(x.m_v);
212  std::copy(m_a.begin(), m_a.begin() + m_size, x.m_a.begin());
213  }
214  std::swap(m_size, x.m_size);
215  std::swap(m_is_small, x.m_is_small);
216  }
217 
218  iterator begin() noexcept { return m_is_small ? m_a.data() : m_v.data(); }
219  const_iterator begin() const noexcept
220  {
221  return m_is_small ? m_a.data() : m_v.data();
222  }
223 
224  iterator end() noexcept
225  {
226  return m_is_small ? m_a.data() + m_size : m_v.data() + m_size;
227  }
228  const_iterator end() const noexcept
229  {
230  return m_is_small ? m_a.data() + m_size : m_v.data() + m_size;
231  }
232 };
233 
234 } // namespace mrpt::containers
std::conditional_t< std::is_same_v< VAL, bool >, UnspecializedBool, VAL > T
Container that transparently and dynamically switches between a std::array and std::vector.
Aligned allocator that is compatible with C++11.
std::conditional_t< std::is_same_v< POINTER, bool * >, UnspecializedBool *, std::conditional_t< std::is_same_v< POINTER, const bool * >, const UnspecializedBool *, POINTER > > STORAGE



Page generated by Doxygen 1.8.14 for MRPT 2.0.0 Git: b38439d21 Tue Mar 31 19:58:06 2020 +0200 at miƩ abr 1 00:50:30 CEST 2020