6#include <initializer_list>
37template<
typename T, std::
size_t Alignment = config::default_alignment>
48 Buffer() noexcept: data_(
nullptr), size_(0) {}
60 construct_default(0, size_);
78 std::is_trivially_destructible_v<T>,
79 "uninitialized Buffer storage is only safe for trivially destructible types"
93 construct_fill(0, size_, value);
103 Buffer(std::initializer_list<T> list): data_(allocate(list.
size())), size_(list.
size())
108 for (
const T& value : list) {
109 std::construct_at(data_ + i, value);
128 : data_(allocate(other.size_)), size_(other.size_)
130 if constexpr (std::is_trivially_copyable_v<T>) {
132 std::memcpy(data_, other.data_,
sizeof(T) * size_);
140 for (; i < size_; ++i) {
141 std::construct_at(data_ + i, other.data_[i]);
158 : data_(other.data_), size_(other.size_)
160 other.data_ =
nullptr;
205 other.data_ =
nullptr;
296 return data_[size_ - 1];
312 return data_[size_ - 1];
320 [[nodiscard]] T*
data() noexcept
330 [[nodiscard]]
const T*
data() const noexcept
350 [[nodiscard]]
const T*
begin() const noexcept
360 [[nodiscard]]
const T*
cbegin() const noexcept
370 [[nodiscard]] T*
end() noexcept
372 return data_ + size_;
380 [[nodiscard]]
const T*
end() const noexcept
382 return data_ + size_;
390 [[nodiscard]]
const T*
cend() const noexcept
392 return data_ + size_;
400 [[nodiscard]] std::reverse_iterator<T*>
rbegin() noexcept
402 return std::reverse_iterator<T*>(
end());
410 [[nodiscard]] std::reverse_iterator<const T*>
rbegin() const noexcept
412 return std::reverse_iterator<const T*>(
end());
420 [[nodiscard]] std::reverse_iterator<const T*>
crbegin() const noexcept
422 return std::reverse_iterator<const T*>(
cend());
430 [[nodiscard]] std::reverse_iterator<T*>
rend() noexcept
432 return std::reverse_iterator<T*>(
begin());
440 [[nodiscard]] std::reverse_iterator<const T*>
rend() const noexcept
442 return std::reverse_iterator<const T*>(
begin());
450 [[nodiscard]] std::reverse_iterator<const T*>
crend() const noexcept
452 return std::reverse_iterator<const T*>(
cbegin());
460 [[nodiscard]] std::size_t
size() const noexcept
470 [[nodiscard]]
bool empty() const noexcept
482 std::fill_n(data_, size_, value);
492 std::swap(data_, other.data_);
493 std::swap(size_, other.size_);
510 static T* allocate(std::size_t space)
515 if (space > std::numeric_limits<std::size_t>::max() /
sizeof(T)) {
516 throw std::bad_array_new_length();
519 return static_cast<T*
>(
522 std::align_val_t{Alignment}
532 static void deallocate(T* ptr)
noexcept
539 std::align_val_t{Alignment}
552 void construct_fill(std::size_t
begin, std::size_t
end,
const T& value)
555 std::uninitialized_fill_n(data_ +
begin,
end -
begin, value);
572 void construct_default(std::size_t
begin, std::size_t
end)
575 std::uninitialized_value_construct_n(data_ +
begin,
end -
begin);
590 void destroy(std::size_t
begin, std::size_t
end)
noexcept
592 if constexpr (!std::is_trivially_destructible_v<T>) {
593 for (std::size_t index =
begin; index <
end; ++index) {
594 std::destroy_at(data_ + index);
Signals an invalid index access.
std::reverse_iterator< const T * > rbegin() const noexcept
Returns a const reverse iterator to the last element.
std::size_t size() const noexcept
Returns the number of stored elements.
const T & operator[](std::size_t index) const noexcept
Returns a const element reference without bounds checking.
const T * data() const noexcept
Returns the raw data pointer as a const pointer.
Buffer & operator=(Buffer &&other) noexcept
Replaces this buffer by taking ownership from another buffer.
void swap(Buffer &other) noexcept
Swaps the contents of two buffers.
Buffer(const Buffer &other)
Creates a copy of another buffer.
void fill(const T &value)
Fills every element with the same value.
std::reverse_iterator< T * > rbegin() noexcept
Returns a reverse iterator to the last element.
Buffer(std::initializer_list< T > list)
Creates a buffer from an initializer list.
~Buffer()
Releases the owned storage.
Buffer(std::size_t size)
Creates a buffer with default-initialized elements.
Buffer(std::size_t size, const T &value)
Creates a buffer and fills every element with a value.
const T & back() const
Returns the last element as a const reference.
T & back()
Returns the last element.
static constexpr uninitialized_t uninitialized
bool empty() const noexcept
Returns whether the buffer contains no elements.
const T & front() const
Returns the first element as a const reference.
std::reverse_iterator< const T * > rend() const noexcept
Returns a const reverse iterator before the first element.
const T * end() const noexcept
Returns a const iterator one past the last element.
const T * begin() const noexcept
Returns a const iterator to the first element.
std::reverse_iterator< const T * > crend() const noexcept
Returns a const reverse iterator before the first element.
std::reverse_iterator< const T * > crbegin() const noexcept
Returns a const reverse iterator to the last element.
T * end() noexcept
Returns an iterator one past the last element.
std::reverse_iterator< T * > rend() noexcept
Returns a reverse iterator before the first element.
Buffer(std::size_t size, uninitialized_t uninitialized)
Creates a buffer with allocated but uninitialized storage.
Buffer(Buffer &&other) noexcept
Transfers ownership from another buffer.
const T * cbegin() const noexcept
Returns a const iterator to the first element.
Buffer() noexcept
Creates an empty buffer.
T * data() noexcept
Returns the raw data pointer.
const T * cend() const noexcept
Returns a const iterator one past the last element.
Buffer & operator=(const Buffer &other)
Replaces this buffer with a copy of another buffer.
T * begin() noexcept
Returns an iterator to the first element.
T & front()
Returns the first element.
T & operator[](std::size_t index) noexcept
Returns a mutable element reference without bounds checking.