/** * @file Vector.h * @brief 自定义动态数组容器实现。 * @details * 该容器提供接近 std::vector 的常用能力,并支持可选析构策略: * - 动态扩容、插入、删除与无序删除; * - 连续内存访问与迭代器接口; * - 在性能敏感场景下复用底层内存分配行为。 */ #pragma once #include "CommonHeader.h" namespace XEngine::utl { /** * @brief 自定义连续内存动态数组。 * @tparam T 元素类型。 * @tparam destruct 是否在删除时调用析构。 */ template class vector { public: // Default constructor. Doesn~t allocate memory. /** * @brief 构造空容器。 */ vector() = default; /** * @brief 构造并调整到指定元素数量。 * @param count 目标元素数量。 */ constexpr explicit vector(u64 count) { resize(count); } /** * @brief 构造并填充指定数量元素。 * @param count 目标元素数量。 * @param value 填充值。 */ constexpr explicit vector(u64 count, const T& value) { resize(count, value); } constexpr vector(const vector& o) { *this = o; } constexpr vector(vector&& o) :_capacity{o._capacity}, _size{o._size}, _data{o._data} { o.reset(); } constexpr vector& operator=(const vector& o) { assert(this != std::addressof(o)); if (this != std::addressof(o)) { clear(); reserve(o._size); for (auto& item : o) { emplace_back(item); } assert(_size == o._size); } return *this; } constexpr vector& operator=(vector&& o) { assert(this != std::addressof(o)); if (this != std::addressof(o)) { destroy(); move(o); } return *this; } ~vector() { destroy(); } /** * @brief 追加拷贝元素。 * @param value 元素值。 */ constexpr void push_back(const T& value) { emplace_back(value); } /** * @brief 追加右值元素。 * @param value 元素值。 */ constexpr void push_back(const T&& value) { emplace_back(std::move(value)); } /** * @brief 原位构造并追加元素。 * @tparam params 构造参数类型。 * @param p 构造参数。 * @return 新元素引用。 */ template constexpr decltype(auto) emplace_back(params&&... p) { if (_size == _capacity) { reserve(((_capacity + 1) * 3) >> 1); // reserve 50% more } assert(_size < _capacity); T *const item{ new (std::addressof(_data[_size])) T(std::forward(p)...) }; ++_size; return *item; } /** * @brief 调整元素数量,新增元素默认构造。 * @param new_size 新大小。 */ constexpr void resize(u64 new_size) { static_assert(std::is_default_constructible::value, "Type must be default-constructible."); if (new_size > _size) { reserve(new_size); while (_size < new_size) { emplace_back(); } } else if (new_size < _size) { if constexpr (destruct) { destruct_range(new_size, _size); } _size = new_size; } assert(new_size == _size); } /** * @brief 调整元素数量,新增元素使用给定值填充。 * @param new_size 新大小。 * @param value 填充值。 */ constexpr void resize(u64 new_size, const T& value) { static_assert(std::is_copy_constructible::value, "Type must be copy-constructible."); if (new_size > _size) { reserve(new_size); while (_size < new_size) { emplace_back(value); } } else if (new_size < _size) { if constexpr (destruct) { destruct_range(new_size, _size); } _size = new_size; } assert(new_size == _size); } /** * @brief 预留最小容量。 * @param new_capacity 目标容量。 */ constexpr void reserve(u64 new_capacity) { if (new_capacity > _capacity) { // NOTE: realoc() will automatically copy the data in the buffer // if a new region of memory iss allocated. void* new_buffer{ realloc(_data, new_capacity * sizeof(T)) }; assert(new_buffer); if (new_buffer) { _data = static_cast(new_buffer); _capacity = new_capacity; } } } /** * @brief 删除指定下标元素并保持顺序。 * @param index 删除下标。 * @return 指向删除位置的指针。 */ constexpr T *const erase(u64 index) { assert(_data && index < _size); return erase(std::addressof(_data[index])); } /** * @brief 删除指定位置元素并保持顺序。 * @param item 待删除元素指针。 * @return 指向删除位置的指针。 */ constexpr T *const erase(T *const item) { assert(_data && item >= std::addressof(_data[0]) && item < std::addressof(_data[_size])); if constexpr (destruct) item->~T(); --_size; if (item < std::addressof(_data[_size])) { memcpy(item, item + 1, (std::addressof(_data[_size]) - item) * sizeof(T)); } return item; } /** * @brief 无序删除指定下标元素。 * @param index 删除下标。 * @return 指向删除位置的指针。 */ constexpr T *const erase_unordered(u64 index) { assert(_data && index < _size); return erase_unordered(std::addressof(_data[index])); } /** * @brief 无序删除指定位置元素。 * @param item 待删除元素指针。 * @return 指向删除位置的指针。 */ constexpr T *const erase_unordered(T *const item) { assert(_data && item >= std::addressof(_data[0]) && item < std::addressof(_data[_size])); if constexpr (destruct) item->~T(); --_size; if (item < std::addressof(_data[_size])) { memcpy(item, std::addressof(_data[_size]), sizeof(T)); } return item; } /** * @brief 清空容器中的有效元素。 */ constexpr void clear() { if constexpr (destruct) { destruct_range(0, _size); } _size = 0; } /** * @brief 与另一个容器交换内容。 * @param o 目标容器。 */ constexpr void swap(vector& o) { if (this != std::addressof(o)) { auto temp(std::move(o)); o.move(*this); move(temp); } } /** * @brief 返回底层数据指针。 * @return 数据首地址。 */ [[nodiscard]] constexpr T* data() { return _data; } /** * @brief 返回只读底层数据指针。 * @return 数据首地址。 */ [[nodiscard]] constexpr T *const data() const { return _data; } /** * @brief 判断容器是否为空。 * @return 空返回 true。 */ [[nodiscard]] constexpr bool empty() const { return _size == 0; } /** * @brief 获取元素个数。 * @return 元素数量。 */ [[nodiscard]] constexpr u64 size() const { return _size; } /** * @brief 获取当前容量。 * @return 容量值。 */ [[nodiscard]] constexpr u64 capacity() const { return _capacity; } [[nodiscard]] constexpr T& operator [](u64 index) { assert(_data && index < _size); return _data[index]; } [[nodiscard]] constexpr const T& operator [](u64 index) const { assert(_data && index < _size); return _data[index]; } [[nodiscard]] constexpr T& front() { assert(_data && _size); return _data[0]; } [[nodiscard]] constexpr const T& front() const { assert(_data && _size); return _data[0]; } [[nodiscard]] constexpr T& back() { assert(_data && _size); return _data[_size -1]; } [[nodiscard]] constexpr const T& back() const { assert(_data && _size); return _data[_size - 1]; } [[nodiscard]] constexpr T* begin() { return std::addressof(_data[0]); } [[nodiscard]] constexpr const T* begin() const { return std::addressof(_data[0]); } [[nodiscard]] constexpr T* end() { assert(!(_data == nullptr && _size > 0)); return std::addressof(_data[_size]); } [[nodiscard]] constexpr const T* end() const { assert(!(_data == nullptr && _size > 0)); return std::addressof(_data[_size]); } private: constexpr void move(vector& o) { _capacity = o._capacity; _size = o._size; _data = o._data; o.reset(); } constexpr void reset() { _capacity = 0; _size = 0; _data = nullptr; } constexpr void destruct_range(u64 first, u64 last) { assert(destruct); assert(first <= _size && last <= _size && first <= last); if (_data) { for (; first != last; ++first) { _data[first].~T(); } } } constexpr void destroy() { assert([&] {return _capacity ? _data != nullptr : _data == nullptr; }()); clear(); _capacity = 0; if (_data) free(_data); _data = nullptr; } u64 _capacity{ 0 }; u64 _size{ 0 }; T* _data{ nullptr }; }; }