如何扩展std::array实现循环覆盖的固定大小数组?
复用std::array实现循环覆盖数组的简便方案
你不需要从头实现完整的类,直接复用std::array的所有功能,只添加循环覆盖的核心逻辑即可,下面是两种可行方案:
方案一:继承std::array(最简便)
通过继承std::array<T, N>,自动获得它的所有成员函数(比如size()、fill()、swap()等),仅重写下标运算符和添加push方法,再实现自定义迭代器支持逻辑顺序的遍历:
#include <array> #include <iterator> template <typename T, std::size_t N> class CircularArray : public std::array<T, N> { private: std::size_t head = 0; public: // 继承std::array的所有构造函数,支持各种初始化方式 using std::array<T, N>::array; // 重写下标运算符,实现循环逻辑访问 T& operator[](std::size_t i) { std::size_t pos = (head + i) % N; return std::array<T, N>::operator[](pos); } const T& operator[](std::size_t i) const { std::size_t pos = (head + i) % N; return std::array<T, N>::operator[](pos); } // 循环覆盖的push方法,支持左值和右值引用 void push(const T& val) { std::array<T, N>::operator[](head) = val; head = (head + 1) % N; } void push(T&& val) { std::array<T, N>::operator[](head) = std::move(val); head = (head + 1) % N; } // 自定义迭代器,支持范围for循环和标准库算法(按逻辑顺序遍历) class iterator { private: typename std::array<T, N>::iterator base_it; typename std::array<T, N>::iterator start_it; std::size_t remaining; public: using value_type = T; using reference = T&; using pointer = T*; using difference_type = std::ptrdiff_t; using iterator_category = std::forward_iterator_tag; iterator(typename std::array<T, N>::iterator it, typename std::array<T, N>::iterator start, std::size_t rem) : base_it(it), start_it(start), remaining(rem) {} reference operator*() const { return *base_it; } pointer operator->() const { return base_it.operator->(); } iterator& operator++() { if (remaining == 0) return *this; ++base_it; if (base_it == std::array<T, N>::end()) { base_it = std::array<T, N>::begin(); } --remaining; return *this; } iterator operator++(int) { auto temp = *this; ++(*this); return temp; } bool operator==(const iterator& other) const { return remaining == other.remaining && base_it == other.base_it; } bool operator!=(const iterator& other) const { return !(*this == other); } }; iterator begin() { return iterator(std::array<T, N>::begin() + head, std::array<T, N>::begin(), N); } iterator end() { return iterator(std::array<T, N>::begin() + head, std::array<T, N>::begin(), 0); } // const版本迭代器 class const_iterator { private: typename std::array<T, N>::const_iterator base_it; typename std::array<T, N>::const_iterator start_it; std::size_t remaining; public: using value_type = T; using reference = const T&; using pointer = const T*; using difference_type = std::ptrdiff_t; using iterator_category = std::forward_iterator_tag; const_iterator(typename std::array<T, N>::const_iterator it, typename std::array<T, N>::const_iterator start, std::size_t rem) : base_it(it), start_it(start), remaining(rem) {} reference operator*() const { return *base_it; } pointer operator->() const { return base_it.operator->(); } const_iterator& operator++() { if (remaining == 0) return *this; ++base_it; if (base_it == std::array<T, N>::cend()) { base_it = std::array<T, N>::cbegin(); } --remaining; return *this; } const_iterator operator++(int) { auto temp = *this; ++(*this); return temp; } bool operator==(const const_iterator& other) const { return remaining == other.remaining && base_it == other.base_it; } bool operator!=(const const_iterator& other) const { return !(*this == other); } }; const_iterator begin() const { return const_iterator(std::array<T, N>::cbegin() + head, std::array<T, N>::cbegin(), N); } const_iterator end() const { return const_iterator(std::array<T, N>::cbegin() + head, std::array<T, N>::cbegin(), 0); } const_iterator cbegin() const { return begin(); } const_iterator cend() const { return end(); } };
方案优势
- 零成本获得
std::array的所有功能,无需重复实现size()、fill()等方法 - 支持
std::array的所有初始化方式(聚合初始化、列表初始化等) - 自定义迭代器保证范围for循环和标准库算法按逻辑顺序遍历(从
head开始,循环绕回数组开头)
方案二:组合std::array(更安全)
如果担心继承聚合类的潜在问题(虽然std::array无虚函数,切片风险极低),可以将std::array作为成员变量,手动导入其成员函数:
#include <array> #include <iterator> #include <utility> template <typename T, std::size_t N> class CircularArray { private: std::array<T, N> arr; std::size_t head = 0; public: // 导入std::array的类型定义 using value_type = typename std::array<T, N>::value_type; using reference = typename std::array<T, N>::reference; using const_reference = typename std::array<T, N>::const_reference; using pointer = typename std::array<T, N>::pointer; using const_pointer = typename std::array<T, N>::const_pointer; using size_type = typename std::array<T, N>::size_type; using difference_type = typename std::array<T, N>::difference_type; // 构造函数 CircularArray() = default; CircularArray(const std::array<T, N>& other) : arr(other) {} CircularArray(std::array<T, N>&& other) : arr(std::move(other)) {} template <typename... Args> explicit CircularArray(Args&&... args) : arr(std::forward<Args>(args)...) {} // 导入std::array的核心成员函数 bool empty() const noexcept { return arr.empty(); } size_type size() const noexcept { return arr.size(); } size_type max_size() const noexcept { return arr.max_size(); } void fill(const T& val) { arr.fill(val); } void swap(CircularArray& other) noexcept(std::is_nothrow_swappable_v<T>) { arr.swap(other.arr); std::swap(head, other.head); } // 自定义循环访问和push T& operator[](std::size_t i) { std::size_t pos = (head + i) % N; return arr[pos]; } const T& operator[](std::size_t i) const { std::size_t pos = (head + i) % N; return arr[pos]; } void push(const T& val) { arr[head] = val; head = (head + 1) % N; } void push(T&& val) { arr[head] = std::move(val); head = (head + 1) % N; } // 同样添加自定义迭代器(代码同方案一,只需将std::array<T, N>::替换为arr.即可) class iterator { private: typename std::array<T, N>::iterator base_it; typename std::array<T, N>::iterator start_it; std::size_t remaining; public: using value_type = T; using reference = T&; using pointer = T*; using difference_type = std::ptrdiff_t; using iterator_category = std::forward_iterator_tag; iterator(typename std::array<T, N>::iterator it, typename std::array<T, N>::iterator start, std::size_t rem) : base_it(it), start_it(start), remaining(rem) {} reference operator*() const { return *base_it; } pointer operator->() const { return base_it.operator->(); } iterator& operator++() { if (remaining == 0) return *this; ++base_it; if (base_it == arr.end()) { base_it = arr.begin(); } --remaining; return *this; } iterator operator++(int) { auto temp = *this; ++(*this); return temp; } bool operator==(const iterator& other) const { return remaining == other.remaining && base_it == other.base_it; } bool operator!=(const iterator& other) const { return !(*this == other); } }; iterator begin() { return iterator(arr.begin() + head, arr.begin(), N); } iterator end() { return iterator(arr.begin() + head, arr.begin(), 0); } // const迭代器同理,此处省略 };
方案优势
- 完全避免继承可能带来的意外问题,代码更健壮
- 对
std::array的依赖更清晰,易于维护
注意事项
- 如果不需要按逻辑顺序遍历,仅保留
std::array的原始迭代器,可以省略自定义迭代器的实现,直接使用arr.begin()/arr.end()(继承方案则用std::array<T, N>::begin()) - 两种方案都支持C++17及以上的范围for循环,以及
std::sort、std::for_each等标准库算法
内容的提问来源于stack exchange,提问作者tst
相关产品推荐
相关产品推荐

