19#include <initializer_list>
28#include "pw_assert/assert.h"
29#include "pw_preprocessor/compiler.h"
30#include "pw_toolchain/constexpr_tag.h"
33namespace vector_impl {
36using IsIterator = std::negation<
37 std::is_same<typename std::iterator_traits<I>::value_type,
void>>;
40inline constexpr size_t kGeneric = size_t(-1);
46template <
typename T,
size_t kMaxSize,
bool kIsTriviallyDestructible>
63template <
typename T,
size_t kMaxSize = vector_impl::kGeneric>
65 :
public VectorStorage<T, kMaxSize, std::is_trivially_destructible_v<T>> {
83 Vector()
noexcept =
default;
90 Vector(size_type count,
const T& value) { this->Append(count, value); }
92 explicit Vector(size_type count) { this->Append(count, T()); }
97 typename = std::enable_if_t<vector_impl::IsIterator<Iterator>::value>>
98 Vector(Iterator first, Iterator last) {
99 this->CopyFrom(first, last);
103 this->CopyFrom(other.begin(), other.end());
106 template <
size_t kOtherMaxSize>
108 this->CopyFrom(other.begin(), other.end());
111 Vector(
Vector&& other)
noexcept { this->MoveFrom(other); }
113 template <
size_t kOtherMaxSize>
115 this->MoveFrom(other);
118 Vector(std::initializer_list<T> list) {
119 this->CopyFrom(list.begin(), list.end());
122 static constexpr size_t max_size() {
return kMaxSize; }
125 template <
typename U = T,
126 typename = std::enable_if_t<std::is_same_v<U, char>>>
127 Vector(std::string_view source) :
Vector(source.begin(), source.end()) {}
130 template <
typename U = T,
131 typename = std::enable_if_t<std::is_same_v<U, char>>>
132 Vector(
const char* source) :
Vector(std::string_view(source)) {}
139 template <
size_t kOtherMaxSize>
150 template <
size_t kOtherMaxSize>
156 Vector& operator=(std::initializer_list<T> list) {
157 this->assign(list.begin(), list.end());
166template <
typename T,
size_t kMaxSize>
168 :
public Vector<T, vector_impl::kGeneric> {
176 :
Base(kMaxSize), array_{} {}
180 friend class Vector<T, kMaxSize>;
181 friend class Vector<T, vector_impl::kGeneric>;
183 using typename
Vector<T, vector_impl::kGeneric>::size_type;
184 static_assert(kMaxSize <= std::numeric_limits<size_type>::max());
186 using typename Vector<T, vector_impl::kGeneric>::pointer;
187 using typename Vector<T, vector_impl::kGeneric>::const_pointer;
190#ifdef __cpp_lib_launder
191 pointer array() { return std::launder(reinterpret_cast<T*>(&array_)); }
192 const_pointer array() const {
193 return std::launder(reinterpret_cast<const T*>(&array_));
196 pointer array() { return reinterpret_cast<T*>(&array_); }
197 const_pointer array() const { return reinterpret_cast<const T*>(&array_); }
207 alignas(T) std::array<std::aligned_storage_t<sizeof(T), alignof(T)>,
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<std::aligned_storage_t<sizeof(T), alignof(T)>,
273class Vector<T, vector_impl::kGeneric> {
275 using value_type = T;
280 using size_type = unsigned short;
282 using difference_type = ptrdiff_t;
283 using reference = value_type&;
284 using const_reference = const value_type&;
286 using const_pointer = const T*;
288 using const_iterator = const T*;
289 using reverse_iterator = std::reverse_iterator<iterator>;
290 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
299 Vector& operator=(const Vector& other) {
300 assign(other.begin(), other.end());
304 Vector& operator=(Vector&& other) noexcept {
310 Vector& operator=(std::initializer_list<T> list) {
315 void assign(size_type count, const T& value) {
317 Append(count, value);
323 typename = std::enable_if_t<vector_impl::IsIterator<Iterator>::value>>
324 void assign(Iterator first, Iterator last) {
326 CopyFrom(first, last);
329 void assign(std::initializer_list<T> list) {
330 assign(list.begin(), list.end());
335 reference at(size_t index) {
336 PW_ASSERT(index < size());
337 return data()[index];
339 const_reference at(size_t index) const {
340 PW_ASSERT(index < size());
341 return data()[index];
344 reference operator[](size_t index) {
345 PW_DASSERT(index < size());
346 return data()[index];
348 const_reference operator[](size_t index) const {
349 PW_DASSERT(index < size());
350 return data()[index];
353 reference front() { return data()[0]; }
354 const_reference front() const { return data()[0]; }
356 reference back() { return data()[size() - 1]; }
357 const_reference back() const { return data()[size() - 1]; }
364 T* data() noexcept { return static_cast<Vector<T, 0>*>(this)->array(); }
365 const T* data() const noexcept {
366 return static_cast<const Vector<T, 0>*>(this)->array();
371 iterator begin() noexcept { return &data()[0]; }
372 const_iterator begin() const noexcept { return &data()[0]; }
373 const_iterator cbegin() const noexcept { return &data()[0]; }
375 iterator end() noexcept { return &data()[size()]; }
376 const_iterator end() const noexcept { return &data()[size()]; }
377 const_iterator cend() const noexcept { return &data()[size()]; }
379 reverse_iterator rbegin() noexcept { return reverse_iterator(end()); }
380 const_reverse_iterator rbegin() const { return reverse_iterator(end()); }
381 const_reverse_iterator crbegin() const noexcept {
382 return reverse_iterator(cend());
385 reverse_iterator rend() noexcept { return reverse_iterator(begin()); }
386 const_reverse_iterator rend() const { return reverse_iterator(begin()); }
387 const_reverse_iterator crend() const noexcept {
388 return reverse_iterator(cbegin());
393 [[nodiscard]] bool empty() const noexcept { return size() == 0u; }
397 [[nodiscard]] bool full() const noexcept { return size() == max_size(); }
401 size_t size() const noexcept PW_NO_SANITIZE("memory") { return size_; }
404 size_t max_size() const noexcept { return max_size_; }
406 size_t capacity() const noexcept { return max_size(); }
410 void clear() noexcept;
412 iterator insert(const_iterator position, size_type count, const T& value);
414 iterator insert(const_iterator position, const T& value) {
415 return insert(position, 1, value);
418 iterator insert(const_iterator position, T&& value);
422 int&... ExplicitArgumentBarrier,
423 typename = std::enable_if_t<vector_impl::IsIterator<Iterator>::value>>
424 iterator insert(const_iterator position, Iterator first, Iterator last) {
425 return InsertFrom(position, first, last);
428 iterator insert(const_iterator position, std::initializer_list<T> list) {
429 return insert(position, list.begin(), list.end());
432 template <typename... Args>
433 iterator emplace(const_iterator position, Args&&... args);
435 iterator erase(const_iterator first, const_iterator last);
437 iterator erase(const_iterator position) {
438 return erase(position, position + 1);
441 void push_back(const T& value) { emplace_back(value); }
443 void push_back(T&& value) { emplace_back(std::move(value)); }
445 template <typename... Args>
446 void emplace_back(Args&&... args);
450 void resize(size_t new_size) { resize(new_size, T()); }
452 void resize(size_t new_size, const T& value);
457 explicit constexpr Vector(size_type max_size) noexcept
458 : max_size_(max_size) {}
464 template <typename Iterator>
465 void CopyFrom(Iterator first, Iterator last);
467 void MoveFrom(Vector& other) noexcept;
469 void Append(size_type count, const T& value);
471 template <typename Iterator>
472 iterator InsertFrom(const_iterator position, Iterator first, Iterator last);
477 void ShiftEntriesForInsert(T* first, size_type to_insert);
480 const size_type max_size_;
486template <typename T, size_t kLhsSize, size_t kRhsSize>
487bool operator==(const Vector<T, kLhsSize>& lhs,
488 const Vector<T, kRhsSize>& rhs) {
489 return std::equal(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
492template <typename T, size_t kLhsSize, size_t kRhsSize>
493bool operator!=(const Vector<T, kLhsSize>& lhs,
494 const Vector<T, kRhsSize>& rhs) {
495 return !(lhs == rhs);
498template <typename T, size_t kLhsSize, size_t kRhsSize>
499bool operator<(const Vector<T, kLhsSize>& lhs, const Vector<T, kRhsSize>& rhs) {
500 return std::lexicographical_compare(
501 lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
504template <typename T, size_t kLhsSize, size_t kRhsSize>
505bool operator<=(const Vector<T, kLhsSize>& lhs,
506 const Vector<T, kRhsSize>& rhs) {
510template <typename T, size_t kLhsSize, size_t kRhsSize>
511bool operator>(const Vector<T, kLhsSize>& lhs, const Vector<T, kRhsSize>& rhs) {
515template <typename T, size_t kLhsSize, size_t kRhsSize>
516bool operator>=(const Vector<T, kLhsSize>& lhs,
517 const Vector<T, kRhsSize>& rhs) {
524void Vector<T, vector_impl::kGeneric>::clear() noexcept {
525 if constexpr (!std::is_trivially_destructible_v<value_type>) {
526 for (auto& item : *this) {
534template <typename... Args>
535void Vector<T, vector_impl::kGeneric>::emplace_back(Args&&... args) {
537 new (&data()[size_]) T(std::forward<Args>(args)...);
543void Vector<T, vector_impl::kGeneric>::pop_back() {
545 if constexpr (!std::is_trivially_destructible_v<value_type>) {
553void Vector<T, vector_impl::kGeneric>::resize(size_t new_size, const T& value) {
554 PW_DASSERT(new_size <= std::numeric_limits<size_type>::max());
555 if (size() < new_size) {
557 static_cast<size_type>(std::min(max_size(), new_size) - size());
558 Append(count, value);
560 while (size() > new_size) {
567typename Vector<T>::iterator Vector<T>::insert(
568 Vector<T>::const_iterator position, T&& value) {
569 PW_DASSERT(position >= cbegin());
570 PW_DASSERT(position <= cend());
573 const iterator insertion_point = const_cast<iterator>(position);
574 if (insertion_point == end()) {
575 emplace_back(std::move(value));
576 return insertion_point;
579 ShiftEntriesForInsert(insertion_point, 1);
581 *insertion_point = std::move(value);
584 return insertion_point;
588typename Vector<T>::iterator Vector<T>::insert(
589 Vector<T>::const_iterator position, size_type count, const T& value) {
590 PW_DASSERT(position >= cbegin());
591 PW_DASSERT(position <= cend());
592 PW_DASSERT(size() + count <= max_size());
594 const iterator insertion_point = const_cast<iterator>(position);
595 if (count == size_type{}) {
596 return insertion_point;
599 ShiftEntriesForInsert(insertion_point, count);
601 size_type inserted = 0;
602 while (insertion_point < end() && inserted < count) {
603 *(insertion_point + inserted) = value;
606 for (; inserted < count; ++inserted) {
607 new (&*(insertion_point + inserted)) T(value);
611 return insertion_point;
615typename Vector<T>::iterator Vector<T>::erase(Vector<T>::const_iterator first,
616 Vector<T>::const_iterator last) {
617 iterator source = const_cast<iterator>(last);
623 iterator destination = const_cast<iterator>(first);
624 iterator new_end = std::move(source, end(), destination);
627 if constexpr (!std::is_trivially_destructible_v<T>) {
628 std::destroy(new_end, end());
631 size_ = static_cast<size_type>(std::distance(begin(), new_end));
634 return const_cast<iterator>(first);
638template <typename Iterator>
639void Vector<T, vector_impl::kGeneric>::CopyFrom(Iterator first, Iterator last) {
640 while (first != last) {
646void Vector<T, vector_impl::kGeneric>::MoveFrom(Vector& other) noexcept {
647 for (auto&& item : other) {
648 emplace_back(std::move(item));
654void Vector<T, vector_impl::kGeneric>::Append(size_type count, const T& value) {
655 for (size_t i = 0; i < count; ++i) {
661template <typename Iterator>
662typename Vector<T>::iterator Vector<T, vector_impl::kGeneric>::InsertFrom(
663 Vector<T>::const_iterator position, Iterator first, Iterator last) {
664 PW_DASSERT(position >= cbegin());
665 PW_DASSERT(position <= cend());
667 const iterator insertion_point = const_cast<iterator>(position);
668 const size_t count = static_cast<size_t>(std::distance(first, last));
669 PW_DASSERT(count <= max_size() - size());
671 ShiftEntriesForInsert(insertion_point, static_cast<size_type>(count));
674 iterator dest = insertion_point;
675 while (dest != end() && i < count) {
676 *dest++ = std::move(*first++);
679 for (; i < count; ++i) {
680 new (&(*dest++)) T(std::move(*first++));
683 size_ += static_cast<size_type>(count);
684 return insertion_point;
688void Vector<T, vector_impl::kGeneric>::ShiftEntriesForInsert(
689 T* first, const size_type to_insert) {
690 ptrdiff_t to_shift = std::distance(first, end());
694 T* dest = end() + to_insert;
695 while (dest != end()) {
696 if (to_shift-- == 0) {
700 new (&(*--dest)) T(std::move(*--last));
704 std::move_backward(first, last, end());
Provides basic helpers for reading and writing UTF-8 encoded strings.
Definition: alignment.h:27
Definition: constexpr_tag.h:46