19#include <initializer_list>
28#include "pw_assert/assert.h"
29#include "pw_containers/storage.h"
30#include "pw_preprocessor/compiler.h"
31#include "pw_toolchain/constexpr_tag.h"
34namespace vector_impl {
37using IsIterator = std::negation<
38 std::is_same<typename std::iterator_traits<I>::value_type,
void>>;
41inline constexpr size_t kGeneric = size_t(-1);
47template <
typename T,
size_t kMaxSize,
bool kIsTriviallyDestructible>
64template <
typename T,
size_t kMaxSize = vector_impl::kGeneric>
66 :
public VectorStorage<T, kMaxSize, std::is_trivially_destructible_v<T>> {
84 Vector()
noexcept =
default;
91 Vector(size_type count,
const T& value) { this->Append(count, value); }
93 explicit Vector(size_type count) { this->Append(count, T()); }
98 typename = std::enable_if_t<vector_impl::IsIterator<Iterator>::value>>
99 Vector(Iterator first, Iterator last) {
100 this->CopyFrom(first, last);
104 this->CopyFrom(other.begin(), other.end());
107 template <
size_t kOtherMaxSize>
109 this->CopyFrom(other.begin(), other.end());
112 Vector(
Vector&& other)
noexcept { this->MoveFrom(other); }
114 template <
size_t kOtherMaxSize>
116 this->MoveFrom(other);
119 Vector(std::initializer_list<T> list) {
120 this->CopyFrom(list.begin(), list.end());
123 static constexpr size_t max_size() {
return kMaxSize; }
126 template <
typename U = T,
127 typename = std::enable_if_t<std::is_same_v<U, char>>>
128 Vector(std::string_view source) :
Vector(source.begin(), source.end()) {}
131 template <
typename U = T,
132 typename = std::enable_if_t<std::is_same_v<U, char>>>
133 Vector(
const char* source) :
Vector(std::string_view(source)) {}
140 template <
size_t kOtherMaxSize>
151 template <
size_t kOtherMaxSize>
157 Vector& operator=(std::initializer_list<T> list) {
158 this->assign(list.begin(), list.end());
167template <
typename T,
size_t kMaxSize>
169 :
public Vector<T, vector_impl::kGeneric> {
177 :
Base(kMaxSize), array_{} {}
181 friend class Vector<T, kMaxSize>;
182 friend class Vector<T, vector_impl::kGeneric>;
184 using typename
Vector<T, vector_impl::kGeneric>::size_type;
185 static_assert(kMaxSize <= std::numeric_limits<size_type>::max());
187 using typename Vector<T, vector_impl::kGeneric>::pointer;
188 using typename Vector<T, vector_impl::kGeneric>::const_pointer;
191#ifdef __cpp_lib_launder
192 pointer array() { return std::launder(reinterpret_cast<T*>(&array_)); }
193 const_pointer array() const {
194 return std::launder(reinterpret_cast<const T*>(&array_));
197 pointer array() { return reinterpret_cast<T*>(&array_); }
198 const_pointer array() const { return reinterpret_cast<const T*>(&array_); }
208 alignas(T) std::array<pw::containers::StorageFor<T>, kMaxSize> array_;
214template <typename T, size_t kMaxSize>
215struct VectorStorage<T, kMaxSize, false>
216 : public Vector<T, vector_impl::kGeneric> {
218 using Base = Vector<T, vector_impl::kGeneric>;
222 static_cast<Vector<T, vector_impl::kGeneric>*>(this)->clear();
229 : Base(kMaxSize), array_{} {}
232 friend class Vector<T, kMaxSize>;
233 friend class Vector<T, vector_impl::kGeneric>;
235 using typename Vector<T, vector_impl::kGeneric>::size_type;
236 static_assert(kMaxSize <= std::numeric_limits<size_type>::max());
238 using typename Vector<T, vector_impl::kGeneric>::pointer;
239 using typename Vector<T, vector_impl::kGeneric>::const_pointer;
242#ifdef __cpp_lib_launder
243 pointer array() { return std::launder(reinterpret_cast<T*>(&array_)); }
244 const_pointer array() const {
245 return std::launder(reinterpret_cast<const T*>(&array_));
248 pointer array() { return reinterpret_cast<T*>(&array_); }
249 const_pointer array() const { return reinterpret_cast<const T*>(&array_); }
259 alignas(T) std::array<pw::containers::StorageFor<T>, kMaxSize> array_;
272class Vector<T, vector_impl::kGeneric> {
274 using value_type = T;
279 using size_type = unsigned short;
281 using difference_type = ptrdiff_t;
282 using reference = value_type&;
283 using const_reference = const value_type&;
285 using const_pointer = const T*;
287 using const_iterator = const T*;
288 using reverse_iterator = std::reverse_iterator<iterator>;
289 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
298 Vector& operator=(const Vector& other) {
299 assign(other.begin(), other.end());
303 Vector& operator=(Vector&& other) noexcept {
309 Vector& operator=(std::initializer_list<T> list) {
314 void assign(size_type count, const T& value) {
316 Append(count, value);
322 typename = std::enable_if_t<vector_impl::IsIterator<Iterator>::value>>
323 void assign(Iterator first, Iterator last) {
325 CopyFrom(first, last);
328 void assign(std::initializer_list<T> list) {
329 assign(list.begin(), list.end());
334 reference at(size_t index) {
335 PW_ASSERT(index < size());
336 return data()[index];
338 const_reference at(size_t index) const {
339 PW_ASSERT(index < size());
340 return data()[index];
343 reference operator[](size_t index) {
344 PW_DASSERT(index < size());
345 return data()[index];
347 const_reference operator[](size_t index) const {
348 PW_DASSERT(index < size());
349 return data()[index];
352 reference front() { return data()[0]; }
353 const_reference front() const { return data()[0]; }
355 reference back() { return data()[size() - 1]; }
356 const_reference back() const { return data()[size() - 1]; }
363 T* data() noexcept { return static_cast<Vector<T, 0>*>(this)->array(); }
364 const T* data() const noexcept {
365 return static_cast<const Vector<T, 0>*>(this)->array();
370 iterator begin() noexcept { return &data()[0]; }
371 const_iterator begin() const noexcept { return &data()[0]; }
372 const_iterator cbegin() const noexcept { return &data()[0]; }
374 iterator end() noexcept { return &data()[size()]; }
375 const_iterator end() const noexcept { return &data()[size()]; }
376 const_iterator cend() const noexcept { return &data()[size()]; }
378 reverse_iterator rbegin() noexcept { return reverse_iterator(end()); }
379 const_reverse_iterator rbegin() const { return reverse_iterator(end()); }
380 const_reverse_iterator crbegin() const noexcept {
381 return reverse_iterator(cend());
384 reverse_iterator rend() noexcept { return reverse_iterator(begin()); }
385 const_reverse_iterator rend() const { return reverse_iterator(begin()); }
386 const_reverse_iterator crend() const noexcept {
387 return reverse_iterator(cbegin());
392 [[nodiscard]] bool empty() const noexcept { return size() == 0u; }
396 [[nodiscard]] bool full() const noexcept { return size() == max_size(); }
400 size_t size() const noexcept PW_NO_SANITIZE("memory") { return size_; }
403 size_t max_size() const noexcept { return max_size_; }
405 size_t capacity() const noexcept { return max_size(); }
409 void clear() noexcept;
411 iterator insert(const_iterator position, size_type count, const T& value);
413 iterator insert(const_iterator position, const T& value) {
414 return insert(position, 1, value);
417 iterator insert(const_iterator position, T&& value);
421 int&... ExplicitArgumentBarrier,
422 typename = std::enable_if_t<vector_impl::IsIterator<Iterator>::value>>
423 iterator insert(const_iterator position, Iterator first, Iterator last) {
424 return InsertFrom(position, first, last);
427 iterator insert(const_iterator position, std::initializer_list<T> list) {
428 return insert(position, list.begin(), list.end());
431 template <typename... Args>
432 iterator emplace(const_iterator position, Args&&... args);
434 iterator erase(const_iterator first, const_iterator last);
436 iterator erase(const_iterator position) {
437 return erase(position, position + 1);
440 void push_back(const T& value) { emplace_back(value); }
442 void push_back(T&& value) { emplace_back(std::move(value)); }
444 template <typename... Args>
445 void emplace_back(Args&&... args);
449 void resize(size_t new_size) { resize(new_size, T()); }
451 void resize(size_t new_size, const T& value);
456 explicit constexpr Vector(size_type max_size) noexcept
457 : max_size_(max_size) {}
463 template <typename Iterator>
464 void CopyFrom(Iterator first, Iterator last);
466 void MoveFrom(Vector& other) noexcept;
468 void Append(size_type count, const T& value);
470 template <typename Iterator>
471 iterator InsertFrom(const_iterator position, Iterator first, Iterator last);
476 void ShiftEntriesForInsert(T* first, size_type to_insert);
479 const size_type max_size_;
485template <typename T, size_t kLhsSize, size_t kRhsSize>
486bool operator==(const Vector<T, kLhsSize>& lhs,
487 const Vector<T, kRhsSize>& rhs) {
488 return std::equal(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
491template <typename T, size_t kLhsSize, size_t kRhsSize>
492bool operator!=(const Vector<T, kLhsSize>& lhs,
493 const Vector<T, kRhsSize>& rhs) {
494 return !(lhs == rhs);
497template <typename T, size_t kLhsSize, size_t kRhsSize>
498bool operator<(const Vector<T, kLhsSize>& lhs, const Vector<T, kRhsSize>& rhs) {
499 return std::lexicographical_compare(
500 lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
503template <typename T, size_t kLhsSize, size_t kRhsSize>
504bool operator<=(const Vector<T, kLhsSize>& lhs,
505 const Vector<T, kRhsSize>& rhs) {
509template <typename T, size_t kLhsSize, size_t kRhsSize>
510bool operator>(const Vector<T, kLhsSize>& lhs, const Vector<T, kRhsSize>& rhs) {
514template <typename T, size_t kLhsSize, size_t kRhsSize>
515bool operator>=(const Vector<T, kLhsSize>& lhs,
516 const Vector<T, kRhsSize>& rhs) {
523void Vector<T, vector_impl::kGeneric>::clear() noexcept {
524 if constexpr (!std::is_trivially_destructible_v<value_type>) {
525 for (auto& item : *this) {
533template <typename... Args>
534void Vector<T, vector_impl::kGeneric>::emplace_back(Args&&... args) {
536 new (&data()[size_]) T(std::forward<Args>(args)...);
542void Vector<T, vector_impl::kGeneric>::pop_back() {
544 if constexpr (!std::is_trivially_destructible_v<value_type>) {
552void Vector<T, vector_impl::kGeneric>::resize(size_t new_size, const T& value) {
553 PW_DASSERT(new_size <= std::numeric_limits<size_type>::max());
554 if (size() < new_size) {
556 static_cast<size_type>(std::min(max_size(), new_size) - size());
557 Append(count, value);
559 while (size() > new_size) {
566typename Vector<T>::iterator Vector<T>::insert(
567 Vector<T>::const_iterator position, T&& value) {
568 PW_DASSERT(position >= cbegin());
569 PW_DASSERT(position <= cend());
572 const iterator insertion_point = const_cast<iterator>(position);
573 if (insertion_point == end()) {
574 emplace_back(std::move(value));
575 return insertion_point;
578 ShiftEntriesForInsert(insertion_point, 1);
580 *insertion_point = std::move(value);
583 return insertion_point;
587typename Vector<T>::iterator Vector<T>::insert(
588 Vector<T>::const_iterator position, size_type count, const T& value) {
589 PW_DASSERT(position >= cbegin());
590 PW_DASSERT(position <= cend());
591 PW_DASSERT(size() + count <= max_size());
593 const iterator insertion_point = const_cast<iterator>(position);
594 if (count == size_type{}) {
595 return insertion_point;
598 ShiftEntriesForInsert(insertion_point, count);
600 size_type inserted = 0;
601 while (insertion_point < end() && inserted < count) {
602 *(insertion_point + inserted) = value;
605 for (; inserted < count; ++inserted) {
606 new (&*(insertion_point + inserted)) T(value);
610 return insertion_point;
614typename Vector<T>::iterator Vector<T>::erase(Vector<T>::const_iterator first,
615 Vector<T>::const_iterator last) {
616 iterator source = const_cast<iterator>(last);
622 iterator destination = const_cast<iterator>(first);
623 iterator new_end = std::move(source, end(), destination);
626 if constexpr (!std::is_trivially_destructible_v<T>) {
627 std::destroy(new_end, end());
630 size_ = static_cast<size_type>(std::distance(begin(), new_end));
633 return const_cast<iterator>(first);
637template <typename Iterator>
638void Vector<T, vector_impl::kGeneric>::CopyFrom(Iterator first, Iterator last) {
639 while (first != last) {
645void Vector<T, vector_impl::kGeneric>::MoveFrom(Vector& other) noexcept {
646 for (auto&& item : other) {
647 emplace_back(std::move(item));
653void Vector<T, vector_impl::kGeneric>::Append(size_type count, const T& value) {
654 for (size_t i = 0; i < count; ++i) {
660template <typename Iterator>
661typename Vector<T>::iterator Vector<T, vector_impl::kGeneric>::InsertFrom(
662 Vector<T>::const_iterator position, Iterator first, Iterator last) {
663 PW_DASSERT(position >= cbegin());
664 PW_DASSERT(position <= cend());
666 const iterator insertion_point = const_cast<iterator>(position);
667 const size_t count = static_cast<size_t>(std::distance(first, last));
668 PW_DASSERT(count <= max_size() - size());
670 ShiftEntriesForInsert(insertion_point, static_cast<size_type>(count));
673 iterator dest = insertion_point;
674 while (dest != end() && i < count) {
675 *dest++ = std::move(*first++);
678 for (; i < count; ++i) {
679 new (&(*dest++)) T(std::move(*first++));
682 size_ += static_cast<size_type>(count);
683 return insertion_point;
687void Vector<T, vector_impl::kGeneric>::ShiftEntriesForInsert(
688 T* first, const size_type to_insert) {
689 ptrdiff_t to_shift = std::distance(first, end());
693 T* dest = end() + to_insert;
694 while (dest != end()) {
695 if (to_shift-- == 0) {
699 new (&(*--dest)) T(std::move(*--last));
703 std::move_backward(first, last, end());
The Pigweed namespace.
Definition: alignment.h:27
Definition: constexpr_tag.h:48