20 #ifndef PSTORE_ADT_SMALL_VECTOR_HPP 21 #define PSTORE_ADT_SMALL_VECTOR_HPP 25 #include <initializer_list> 38 template <
typename ElementType, std::
size_t BodyElements = 256>
41 using value_type = ElementType;
43 using reference = value_type &;
44 using const_reference = value_type
const &;
45 using pointer = value_type *;
46 using const_pointer = value_type
const *;
48 using size_type = std::size_t;
49 using difference_type = std::ptrdiff_t;
53 using reverse_iterator = std::reverse_iterator<iterator>;
54 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
72 ElementType
const * data ()
const noexcept {
return buffer_; }
73 ElementType * data () noexcept {
return buffer_; }
75 ElementType
const & operator[] (std::size_t n)
const noexcept {
return index (*
this, n); }
76 ElementType & operator[] (std::size_t n) noexcept {
return index (*
this, n); }
78 ElementType & back () {
return index (*
this, size () - 1U); }
85 std::size_t size ()
const noexcept {
return elements_; }
86 std::size_t size_bytes ()
const noexcept {
return elements_ *
sizeof (ElementType); }
89 bool empty () const noexcept {
return elements_ == 0; }
94 return std::max (BodyElements, big_buffer_.capacity ());
106 void reserve (std::size_t new_cap);
116 void resize (std::size_t new_elements);
128 reverse_iterator
rbegin () noexcept {
return reverse_iterator{this->
end ()}; }
129 const_reverse_iterator
rbegin ()
const noexcept {
130 return const_reverse_iterator{this->
end ()};
132 const_reverse_iterator rcbegin () noexcept {
return const_reverse_iterator{this->cend ()}; }
138 reverse_iterator rend () noexcept {
return reverse_iterator{this->begin ()}; }
139 const_reverse_iterator rend ()
const noexcept {
140 return const_reverse_iterator{this->begin ()};
142 const_reverse_iterator rcend () noexcept {
return const_reverse_iterator{this->cbegin ()}; }
152 void clear () noexcept;
156 template <
typename... Args>
157 void emplace_back (Args &&... args);
159 template <
typename InputIt>
160 void assign (InputIt first, InputIt last);
162 void assign (std::initializer_list<ElementType> ilist) {
163 this->assign (std::begin (ilist), std::end (ilist));
167 template <
typename InputIt>
168 void append (InputIt first, InputIt last);
169 void append (std::initializer_list<ElementType> ilist) {
170 this->
append (std::begin (ilist), std::end (ilist));
177 template <
typename SmallVector,
179 static ResultType & index (SmallVector && sm, std::size_t
const n) noexcept {
180 PSTORE_ASSERT (n < sm.size ());
181 return sm.buffer_[n];
186 std::size_t elements_ = 0;
190 std::array<ElementType, BodyElements> small_buffer_{{}};
194 std::vector<ElementType> big_buffer_;
197 ElementType * buffer_ =
nullptr;
201 static constexpr
bool is_small (std::size_t
const elements) noexcept {
202 return elements <= BodyElements;
205 void switch_to_big (std::size_t new_elements);
206 template <
typename... Args>
207 void emplace_back_big (Args &&... args);
208 ElementType * set_buffer_ptr (std::size_t
const required_elements) noexcept {
209 buffer_ = is_small (required_elements) ? small_buffer_.data () : big_buffer_.data ();
216 template <
typename ElementType, std::
size_t BodyElements>
218 : elements_{required_elements} {
220 if (!is_small (elements_)) {
221 big_buffer_.resize (elements_);
223 this->set_buffer_ptr (elements_);
226 template <
typename ElementType, std::
size_t BodyElements>
228 this->set_buffer_ptr (elements_);
231 template <
typename ElementType, std::
size_t BodyElements>
233 : elements_ (std::move (other.elements_))
234 , small_buffer_ (std::move (other.small_buffer_))
235 , big_buffer_ (std::move (other.big_buffer_)) {
237 this->set_buffer_ptr (elements_);
240 template <
typename ElementType, std::
size_t BodyElements>
243 this->reserve (init.size ());
244 std::copy (std::begin (init), std::end (init), std::back_inserter (*
this));
247 template <
typename ElementType, std::
size_t BodyElements>
250 this->reserve (rhs.size ());
251 std::copy (std::begin (rhs), std::end (rhs), std::back_inserter (*
this));
256 template <
typename ElementType, std::
size_t BodyElements>
259 elements_ = std::move (other.elements_);
260 small_buffer_ = std::move (other.small_buffer_);
261 big_buffer_ = std::move (other.big_buffer_);
263 this->set_buffer_ptr (elements_);
267 template <
typename ElementType, std::
size_t BodyElements>
270 if (
this != &other) {
272 this->resize (other.size ());
273 std::copy (std::begin (other), std::end (other), std::begin (*
this));
280 template <
typename ElementType, std::
size_t BodyElements>
282 if (new_cap > capacity ()) {
289 template <
typename ElementType, std::
size_t BodyElements>
291 if (new_elements != elements_) {
292 bool const is_small_before = is_small (elements_);
293 bool const is_small_after = is_small (new_elements);
295 big_buffer_.resize (is_small_after ? 0 : new_elements);
299 auto *
const old_buffer = buffer_;
300 auto *
const new_buffer = this->set_buffer_ptr (new_elements);
302 if (is_small_before != is_small_after) {
303 std::copy (old_buffer, old_buffer + elements_, new_buffer);
306 elements_ = new_elements;
312 template <
typename ElementType, std::
size_t BodyElements>
314 big_buffer_.
clear ();
316 this->set_buffer_ptr (elements_);
321 template <
typename ElementType, std::
size_t BodyElements>
323 auto const new_elements = elements_ + 1U;
324 if (is_small (new_elements)) {
325 small_buffer_[elements_] = v;
327 if (is_small (elements_)) {
328 this->switch_to_big (new_elements);
330 big_buffer_.push_back (v);
331 this->set_buffer_ptr (new_elements);
333 elements_ = new_elements;
338 template <
typename ElementType, std::
size_t BodyElements>
339 template <
typename... Args>
341 auto const new_elements = elements_ + 1U;
342 if (!is_small (new_elements)) {
343 return emplace_back_big (std::forward<Args> (args)...);
345 small_buffer_[elements_] = ElementType (std::forward<Args> (args)...);
346 elements_ = new_elements;
352 template <
typename ElementType, std::
size_t BodyElements>
353 template <
typename... Args>
355 auto const new_elements = elements_ + 1U;
356 if (is_small (elements_)) {
357 this->switch_to_big (new_elements);
359 big_buffer_.emplace_back (std::forward<Args> (args)...);
360 this->set_buffer_ptr (new_elements);
361 elements_ = new_elements;
366 template <
typename ElementType, std::
size_t BodyElements>
368 big_buffer_.
clear ();
369 big_buffer_.reserve (new_elements);
370 std::copy (buffer_, buffer_ + elements_, std::back_inserter (big_buffer_));
371 this->set_buffer_ptr (new_elements);
376 template <
typename ElementType, std::
size_t BodyElements>
377 template <
typename InputIt>
380 for (; first != last; ++first) {
381 this->push_back (*first);
387 template <
typename ElementType, std::
size_t BodyElements>
388 template <
typename Iterator>
390 for (; first != last; ++first) {
391 this->push_back (*first);
395 template <
typename ElementType, std::
size_t LhsBodyElements, std::
size_t RhsBodyElements>
398 return std::equal (std::begin (lhs), std::end (lhs), std::begin (rhs), std::end (rhs));
400 template <
typename ElementType, std::
size_t LhsBodyElements, std::
size_t RhsBodyElements>
403 return !operator== (lhs, rhs);
407 #endif // PSTORE_ADT_SMALL_VECTOR_HPP void clear() noexcept
Removes all elements from the container.
Definition: small_vector.hpp:313
reverse_iterator rbegin() noexcept
Returns a reverse iterator to the first element of the reversed container.
Definition: small_vector.hpp:128
void resize(std::size_t new_elements)
Resizes the container so that it is large enough for accommodate the given number of elements...
Definition: small_vector.hpp:290
A class which provides a vector-like interface to a small, normally stack allocated, buffer which may, if necessary, be resized.
Definition: small_vector.hpp:39
void push_back(ElementType const &v)
Adds an element to the end.
Definition: small_vector.hpp:322
const_iterator end() const noexcept
Returns an iterator to the end of the container.
Definition: small_vector.hpp:135
A utility template intended to simplify the writing of the const- and non-const variants of member fu...
Definition: pointer_based_iterator.hpp:53
Definition: nonpod2.cpp:40
void append(InputIt first, InputIt last)
Add the specified range to the end of the small vector.
void reserve(std::size_t new_cap)
Increase the capacity of the vector to a value that's greater or equal to new_cap.
Definition: small_vector.hpp:281
An implementation of the standard assert() macro with the exception that it will, on failure...
bool empty() const noexcept
Checks whether the container is empty.
Definition: small_vector.hpp:89
small_vector() noexcept
Constructs the buffer with an initial size of 0.
Definition: small_vector.hpp:227
Provides pointer_based_iterator<> an iterator wrapper for pointers.
typename std::conditional< std::is_const< typename std::remove_reference< T >::type >::value, RC, R >::type type
If T is const, R const otherwise R.
Definition: inherit_const.hpp:112
std::size_t capacity() const noexcept
Returns the number of elements that can be held in currently allocated storage.
Definition: small_vector.hpp:93