|
|
#pragma once
|
|
|
|
|
|
#include <vector>
|
|
|
#include <cstddef>
|
|
|
#include <utility>
|
|
|
#include <cassert>
|
|
|
|
|
|
/**
|
|
|
* @brief 固定容量的环形缓冲区
|
|
|
*
|
|
|
* 容量在编译期固定且必须为 2 的幂;head/tail 为无符号整数,下标通过 % Capacity 取模。
|
|
|
* 满时继续 push 会覆盖最旧元素。接口风格与 std::deque 类似(front/back/pop_front)。
|
|
|
*
|
|
|
* @tparam T 元素类型
|
|
|
* @tparam Capacity 缓冲区容量,必须大于 0 且为 2 的幂
|
|
|
*/
|
|
|
template<typename T, size_t Capacity>
|
|
|
class RingBuffer
|
|
|
{
|
|
|
static_assert(Capacity > 0 && (Capacity & (Capacity - 1)) == 0, "RingBuffer capacity must be a power of 2");
|
|
|
|
|
|
public:
|
|
|
/** @brief 默认构造,内部缓冲区预分配 Capacity 个元素。 */
|
|
|
RingBuffer() : m_data(Capacity) {}
|
|
|
|
|
|
/**
|
|
|
* @brief 在尾部写入一个元素(拷贝)
|
|
|
* @param value 要写入的值
|
|
|
* @note 若已满则覆盖最旧项,不报错。
|
|
|
*/
|
|
|
void push(const T& value)
|
|
|
{
|
|
|
if (m_size == Capacity)
|
|
|
{
|
|
|
m_head = (m_head + 1) % Capacity;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
++m_size;
|
|
|
}
|
|
|
m_data[m_tail] = value;
|
|
|
m_tail = (m_tail + 1) % Capacity;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* @brief 在尾部写入一个元素(移动)
|
|
|
* @param value 要写入的值(右值引用,调用后处于未指定状态)
|
|
|
* @note 若已满则覆盖最旧项,不报错。
|
|
|
*/
|
|
|
void push(T&& value)
|
|
|
{
|
|
|
if (m_size == Capacity)
|
|
|
{
|
|
|
m_head = (m_head + 1) % Capacity;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
++m_size;
|
|
|
}
|
|
|
m_data[m_tail] = std::move(value);
|
|
|
m_tail = (m_tail + 1) % Capacity;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* @brief 取队头(最旧元素)的常量引用
|
|
|
* @return 队头元素的 const 引用
|
|
|
* @pre 调用前须 !empty(),空时断言失败
|
|
|
*/
|
|
|
const T& front() const
|
|
|
{
|
|
|
assert(!empty() && "RingBuffer::front() on empty buffer");
|
|
|
return m_data[m_head];
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* @brief 取队头(最旧元素)的可写引用
|
|
|
* @return 队头元素的非 const 引用
|
|
|
* @pre 调用前须 !empty(),空时断言失败
|
|
|
*/
|
|
|
T& front()
|
|
|
{
|
|
|
assert(!empty() && "RingBuffer::front() on empty buffer");
|
|
|
return m_data[m_head];
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* @brief 取队尾(最新元素)的常量引用
|
|
|
* @return 队尾元素的 const 引用
|
|
|
* @pre 调用前须 !empty(),空时断言失败
|
|
|
*/
|
|
|
const T& back() const
|
|
|
{
|
|
|
assert(!empty() && "RingBuffer::back() on empty buffer");
|
|
|
return m_data[(m_tail + Capacity - 1) % Capacity];
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* @brief 取队尾(最新元素)的可写引用
|
|
|
* @return 队尾元素的非 const 引用
|
|
|
* @pre 调用前须 !empty(),空时断言失败
|
|
|
*/
|
|
|
T& back()
|
|
|
{
|
|
|
assert(!empty() && "RingBuffer::back() on empty buffer");
|
|
|
return m_data[(m_tail + Capacity - 1) % Capacity];
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* @brief 按逻辑下标取元素(只读)
|
|
|
* @param i 逻辑下标,0 为最旧,size()-1 为最新
|
|
|
* @return 下标 i 处元素的 const 引用
|
|
|
* @pre 调用前须 i < size(),越界时断言失败
|
|
|
*/
|
|
|
const T& operator[](size_t i) const
|
|
|
{
|
|
|
assert(i < m_size && "RingBuffer::operator[] index out of range");
|
|
|
return m_data[(m_head + i) % Capacity];
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* @brief 按逻辑下标取元素(可写)
|
|
|
* @param i 逻辑下标,0 为最旧,size()-1 为最新
|
|
|
* @return 下标 i 处元素的非 const 引用
|
|
|
* @pre 调用前须 i < size(),越界时断言失败
|
|
|
*/
|
|
|
T& operator[](size_t i)
|
|
|
{
|
|
|
assert(i < m_size && "RingBuffer::operator[] index out of range");
|
|
|
return m_data[(m_head + i) % Capacity];
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* @brief 弹出队头(最旧元素)
|
|
|
* @note 空时无操作,不修改状态、不断言。
|
|
|
*/
|
|
|
void pop_front()
|
|
|
{
|
|
|
if (empty())
|
|
|
return;
|
|
|
m_head = (m_head + 1) % Capacity;
|
|
|
--m_size;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* @brief 清空缓冲区,移除所有元素;容量不变,可继续 push。
|
|
|
*/
|
|
|
void clear()
|
|
|
{
|
|
|
m_head = 0;
|
|
|
m_tail = 0;
|
|
|
m_size = 0;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* @brief 是否存在等于 value 的元素
|
|
|
* @param value 要查找的值(要求 T 支持 operator==)
|
|
|
* @return 存在则 true,否则 false
|
|
|
* @note 线性扫描,时间复杂度 O(size())
|
|
|
*/
|
|
|
bool contains(const T& value) const
|
|
|
{
|
|
|
for (size_t i = 0; i < m_size; ++i)
|
|
|
{
|
|
|
size_t idx = (m_head + i) % Capacity;
|
|
|
if (m_data[idx] == value)
|
|
|
{
|
|
|
return true;
|
|
|
}
|
|
|
}
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
/** @brief 当前元素个数 */
|
|
|
size_t size() const
|
|
|
{
|
|
|
return m_size;
|
|
|
}
|
|
|
|
|
|
/** @brief 缓冲区容量(编译期常量)。 */
|
|
|
size_t capacity() const
|
|
|
{
|
|
|
return Capacity;
|
|
|
}
|
|
|
|
|
|
/** @brief 是否为空(无元素)。 */
|
|
|
bool empty() const
|
|
|
{
|
|
|
return m_size == 0;
|
|
|
}
|
|
|
|
|
|
/** @brief 是否已满(元素个数等于容量)。 */
|
|
|
bool full() const
|
|
|
{
|
|
|
return m_size == Capacity;
|
|
|
}
|
|
|
|
|
|
private:
|
|
|
std::vector<T> m_data; /**< 底层存储,大小为 Capacity */
|
|
|
size_t m_head = 0; /**< 最旧元素的下标 */
|
|
|
size_t m_tail = 0; /**< 下一个写入位置(尾后) */
|
|
|
size_t m_size = 0; /**< 当前元素个数 */
|
|
|
};
|