实现了boost/circular_buffer的主要功能。
circular_array.h:
#ifndef circular_array_H
#define circular_array_H
#include <algorithm>
#include <memory>
#include <type_traits>
#include <vector>
template <typename _Base, typename _Pointer> class _BaseIterator;
template <typename T, typename _Alloc = std::allocator<T>> class circular_array;
template <typename _Base, typename _Pointer> class _BaseIterator
{
static_assert(std::is_pointer<_Pointer>::value, "_Pointer must be pointer.");
protected:
using _Container = typename _Base::_Container;
using _Is_Const_Ptr = typename std::is_const<typename std::remove_pointer<_Pointer>::type>;
using _BaseIt = typename std::conditional<_Is_Const_Ptr::value, typename _Container::const_iterator,
typename _Container::iterator>::type;
using _MyBase = typename std::conditional<_Is_Const_Ptr::value, const _Base, _Base>::type;
using _Traits = std::iterator_traits<_BaseIt>;
public:
using iterator_type = _BaseIterator;
using iterator_category = typename _Traits::iterator_category;
using value_type = typename _Traits::value_type;
using difference_type = typename _Traits::difference_type;
using reference = typename _Traits::reference;
using pointer = typename _Traits::pointer;
protected:
_MyBase *_body;
_BaseIt _it;
public:
_BaseIterator(_MyBase *__body = nullptr, const _BaseIt &__baseIt = _BaseIt());
template <typename _RPointer> _BaseIterator(const _BaseIterator<_Base, _RPointer> &__r);
template <typename _RPointer> _BaseIterator &operator=(const _BaseIterator<_Base, _RPointer> &__r);
template <typename __Base, typename __Pointer> friend class _BaseIterator;
inline reference operator*() const noexcept;
inline pointer operator->() const noexcept;
inline _BaseIterator &operator++() noexcept;
inline _BaseIterator operator++(int) noexcept;
inline _BaseIterator &operator--() noexcept;
inline _BaseIterator operator--(int) noexcept;
inline reference operator[](difference_type __n) const noexcept;
inline _BaseIterator &operator+=(difference_type __n) noexcept;
inline _BaseIterator operator+(difference_type __n) const noexcept;
inline _BaseIterator &operator-=(difference_type __n) noexcept;
inline _BaseIterator operator-(difference_type __n) const noexcept;
inline difference_type operator-(const _BaseIterator &__r) const noexcept;
inline bool operator<(const _BaseIterator &__r) const noexcept;
inline bool operator==(const _BaseIterator &__r) const noexcept;
inline bool operator!=(const _BaseIterator &__r) const noexcept;
inline bool operator>(const _BaseIterator &__r) const noexcept;
inline bool operator<=(const _BaseIterator &__r) const noexcept;
inline bool operator>=(const _BaseIterator &__r) const noexcept;
};
template <typename _Base, typename _Pointer>
inline auto operator+(typename _BaseIterator<_Base, _Pointer>::difference_type __n,
const _BaseIterator<_Base, _Pointer> &__r);
template <typename T, typename _Alloc> class circular_array
{
protected:
using _Container = std::vector<T, _Alloc>;
public:
using value_type = T;
using reference = typename _Container::reference;
using const_reference = typename _Container::const_reference;
using pointer = typename _Container::pointer;
using const_pointer = typename _Container::const_pointer;
using size_type = typename _Container::size_type;
using difference_type = typename _Container::difference_type;
using allocator_type = typename _Container::allocator_type;
using iterator = _BaseIterator<circular_array, pointer>;
using const_iterator = _BaseIterator<circular_array, const_pointer>;
using reverse_iterator = std::reverse_iterator<iterator>;
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
friend class _BaseIterator<circular_array, pointer>;
friend class _BaseIterator<circular_array, const_pointer>;
protected:
_Container _c;
difference_type _offset;
public:
circular_array();
circular_array(size_type __size);
template <typename... _Args> circular_array(const _Args &... __args);
template <typename... _Args> void assign(const _Args &... __args);
void rotate_left(difference_type __d = 1) noexcept;
void rotate_right(difference_type __d = 1) noexcept;
void resize(size_type __new_size, const_reference __v = value_type());
inline reference at(size_type __n);
inline const_reference at(size_type __n) const;
inline reference operator[](size_type __n);
inline const_reference operator[](size_type __n) const;
inline iterator begin() noexcept;
inline const_iterator begin() const noexcept;
inline iterator end() noexcept;
inline const_iterator end() const noexcept;
inline const_iterator cbegin() const noexcept;
inline const_iterator cend() const noexcept;
inline reverse_iterator rbegin() noexcept;
inline const_reverse_iterator rbegin() const noexcept;
inline reverse_iterator rend() noexcept;
inline const_reverse_iterator rend() const noexcept;
inline const_reverse_iterator crbegin() const noexcept;
inline const_reverse_iterator crend() const noexcept;
inline size_type size() const noexcept;
std::vector<T, _Alloc> &base() noexcept;
};
#ifndef circular_array_CPP
#include "circular_array.cpp"
#endif // !circular_array_CPP
#endif // !circular_array_H
circular_array.cpp:
#ifndef circular_array_CPP
#define circular_array_CPP
#ifndef circular_array_H
#include "circular_array.h"
#endif // !circular_array_H
template <typename _Base, typename _Pointer>
_BaseIterator<_Base, _Pointer>::_BaseIterator(_MyBase *__body, const _BaseIt &__baseIt) : _body(__body), _it(__baseIt)
{
}
template <typename _Base, typename _Pointer>
template <typename _RPointer>
_BaseIterator<_Base, _Pointer>::_BaseIterator(const _BaseIterator<_Base, _RPointer> &__r)
: _body(__r._body), _it(__r._it)
{
}
template <typename _Base, typename _Pointer>
template <typename _RPointer>
_BaseIterator<_Base, _Pointer> &_BaseIterator<_Base, _Pointer>::operator=(const _BaseIterator<_Base, _RPointer> &__r)
{
_body = __r._body;
_it = __r._it;
}
template <typename _Base, typename _Pointer>
inline typename _BaseIterator<_Base, _Pointer>::reference _BaseIterator<_Base, _Pointer>::operator*() const noexcept
{
return *_it;
}
template <typename _Base, typename _Pointer>
inline typename _BaseIterator<_Base, _Pointer>::pointer _BaseIterator<_Base, _Pointer>::operator->() const noexcept
{
return _it.operator->();
}
template <typename _Base, typename _Pointer>
inline _BaseIterator<_Base, _Pointer> &_BaseIterator<_Base, _Pointer>::operator++() noexcept
{
auto &&_b = _body->_c.begin(), &&_e = _body->_c.end();
if (++_it - _b == _body->_offset)
{
_it = _e;
}
else if (bool(_body->_offset) && _it == _e)
{
_it = _b;
}
return *this;
}
template <typename _Base, typename _Pointer>
inline _BaseIterator<_Base, _Pointer> _BaseIterator<_Base, _Pointer>::operator++(int) noexcept
{
auto ret = *this;
++*this;
return ret;
}
template <typename _Base, typename _Pointer>
inline _BaseIterator<_Base, _Pointer> &_BaseIterator<_Base, _Pointer>::operator--() noexcept
{
auto &&_b = _body->_c.begin(), &&_e = _body->_c.end();
if (bool(_body->_offset) && _it == _e)
{
_it = _b + _body->_offset;
}
else if (_it == _b)
{
_it = _e;
}
--_it;
return *this;
}
template <typename _Base, typename _Pointer>
inline _BaseIterator<_Base, _Pointer> _BaseIterator<_Base, _Pointer>::operator--(int) noexcept
{
auto ret = *this;
--*this;
return ret;
}
template <typename _Base, typename _Pointer>
inline typename _BaseIterator<_Base, _Pointer>::reference _BaseIterator<_Base, _Pointer>::operator[](
difference_type __n) const noexcept
{
difference_type _sz = _body->_c.size();
difference_type tmp = _it - _body->_c.begin() + __n;
return _body->_c[tmp < 0 ? tmp + _sz : tmp];
}
template <typename _Base, typename _Pointer>
inline _BaseIterator<_Base, _Pointer> &_BaseIterator<_Base, _Pointer>::operator+=(difference_type __n) noexcept
{
auto &&_b = _body->_c.begin();
difference_type &&_sz = _body->_c.size();
difference_type tmp = _it - _body->_c.begin();
if (tmp != _sz)
{
tmp -= _body->_offset;
}
if (tmp < 0)
{
tmp += _sz;
}
tmp += __n;
if (tmp == _sz)
{
_it = _body->_c.end();
}
else
{
tmp += _body->_offset;
_it = _b + (tmp < _sz ? tmp : tmp - _sz);
}
return *this;
}
template <typename _Base, typename _Pointer>
inline _BaseIterator<_Base, _Pointer> _BaseIterator<_Base, _Pointer>::operator+(difference_type __n) const noexcept
{
auto ret = *this;
return ret += __n;
}
template <typename _Base, typename _Pointer>
inline _BaseIterator<_Base, _Pointer> &_BaseIterator<_Base, _Pointer>::operator-=(difference_type __n) noexcept
{
return *this += -__n;
}
template <typename _Base, typename _Pointer>
inline _BaseIterator<_Base, _Pointer> _BaseIterator<_Base, _Pointer>::operator-(difference_type __n) const noexcept
{
auto ret = *this;
return ret += -__n;
}
template <typename _Base, typename _Pointer>
inline typename _BaseIterator<_Base, _Pointer>::difference_type _BaseIterator<_Base, _Pointer>::operator-(
const _BaseIterator &__r) const noexcept
{
auto &&_b = _body->_c.begin();
auto &&_sz = _body->_c.size();
auto _lp = _it - _b, _rp = __r._it - _b;
if (_lp == _sz)
{
_lp += _body->_offset;
}
else if (_lp < _body->_offset)
{
_lp += _sz;
}
if (_rp == _sz)
{
_rp += _body->_offset;
}
else if (_rp < _body->_offset)
{
_rp += _sz;
}
return _lp - _rp;
}
template <typename _Base, typename _Pointer>
inline bool _BaseIterator<_Base, _Pointer>::operator<(const _BaseIterator &__r) const noexcept
{
return *this - __r < 0;
}
template <typename _Base, typename _Pointer>
inline bool _BaseIterator<_Base, _Pointer>::operator==(const _BaseIterator &__r) const noexcept
{
return _it == __r._it;
}
template <typename _Base, typename _Pointer>
inline bool _BaseIterator<_Base, _Pointer>::operator!=(const _BaseIterator &__r) const noexcept
{
return _it != __r._it;
}
template <typename _Base, typename _Pointer>
inline bool _BaseIterator<_Base, _Pointer>::operator>(const _BaseIterator &__r) const noexcept
{
return *this - __r > 0;
}
template <typename _Base, typename _Pointer>
inline bool _BaseIterator<_Base, _Pointer>::operator<=(const _BaseIterator &__r) const noexcept
{
return *this - __r <= 0;
}
template <typename _Base, typename _Pointer>
inline bool _BaseIterator<_Base, _Pointer>::operator>=(const _BaseIterator &__r) const noexcept
{
return *this - __r >= 0;
}
template <typename _Base, typename _Pointer>
inline auto operator+(typename _BaseIterator<_Base, _Pointer>::difference_type __n,
const _BaseIterator<_Base, _Pointer> &__r)
{
return __r + __n;
}
template <typename T, typename _Alloc> circular_array<T, _Alloc>::circular_array() : _c(), _offset()
{
}
template <typename T, typename _Alloc>
circular_array<T, _Alloc>::circular_array(size_type __size) : _c(__size), _offset()
{
}
template <typename T, typename _Alloc>
template <typename... _Args>
circular_array<T, _Alloc>::circular_array(const _Args &... __args) : _c(__args...), _offset()
{
}
template <typename T, typename _Alloc>
template <typename... _Args>
void circular_array<T, _Alloc>::assign(const _Args &... __args)
{
_c.assign(__args...);
_offset = 0;
}
template <typename T, typename _Alloc> void circular_array<T, _Alloc>::rotate_left(difference_type __d) noexcept
{
difference_type _sz = _c.size();
_offset = (_offset + __d) % _sz;
if (_offset < 0)
{
_offset += _sz;
}
}
template <typename T, typename _Alloc> void circular_array<T, _Alloc>::rotate_right(difference_type __d) noexcept
{
return rotate_left(-__d);
}
template <typename T, typename _Alloc> void circular_array<T, _Alloc>::resize(size_type __new_size, const_reference __v)
{
std::rotate(_c.begin(), _c.begin() + _offset, _c.end());
_c.resize(__new_size, __v);
_offset = 0;
}
template <typename T, typename _Alloc>
inline typename circular_array<T, _Alloc>::reference circular_array<T, _Alloc>::at(size_type __n)
{
return _c.at((__n + _offset) % difference_type(_c.size()));
}
template <typename T, typename _Alloc>
inline typename circular_array<T, _Alloc>::const_reference circular_array<T, _Alloc>::at(size_type __n) const
{
return _c.at((__n + _offset) % difference_type(_c.size()));
}
template <typename T, typename _Alloc>
inline typename circular_array<T, _Alloc>::reference circular_array<T, _Alloc>::operator[](size_type __n)
{
return at(__n);
}
template <typename T, typename _Alloc>
inline typename circular_array<T, _Alloc>::const_reference circular_array<T, _Alloc>::operator[](size_type __n) const
{
return at(__n);
}
template <typename T, typename _Alloc>
inline typename circular_array<T, _Alloc>::iterator circular_array<T, _Alloc>::begin() noexcept
{
return iterator(this, _c.begin() + _offset);
}
template <typename T, typename _Alloc>
inline typename circular_array<T, _Alloc>::const_iterator circular_array<T, _Alloc>::begin() const noexcept
{
return const_iterator(this, _c.begin() + _offset);
}
template <typename T, typename _Alloc>
inline typename circular_array<T, _Alloc>::iterator circular_array<T, _Alloc>::end() noexcept
{
return iterator(this, _c.end());
}
template <typename T, typename _Alloc>
inline typename circular_array<T, _Alloc>::const_iterator circular_array<T, _Alloc>::end() const noexcept
{
return const_iterator(this, _c.end());
}
template <typename T, typename _Alloc>
inline typename circular_array<T, _Alloc>::const_iterator circular_array<T, _Alloc>::cbegin() const noexcept
{
return begin();
}
template <typename T, typename _Alloc>
inline typename circular_array<T, _Alloc>::const_iterator circular_array<T, _Alloc>::cend() const noexcept
{
return end();
}
template <typename T, typename _Alloc>
inline typename circular_array<T, _Alloc>::reverse_iterator circular_array<T, _Alloc>::rbegin() noexcept
{
return reverse_iterator(end());
}
template <typename T, typename _Alloc>
inline typename circular_array<T, _Alloc>::const_reverse_iterator circular_array<T, _Alloc>::rbegin() const noexcept
{
return const_reverse_iterator(end());
}
template <typename T, typename _Alloc>
inline typename circular_array<T, _Alloc>::reverse_iterator circular_array<T, _Alloc>::rend() noexcept
{
return reverse_iterator(begin());
}
template <typename T, typename _Alloc>
inline typename circular_array<T, _Alloc>::const_reverse_iterator circular_array<T, _Alloc>::rend() const noexcept
{
return const_reverse_iterator(begin());
}
template <typename T, typename _Alloc>
inline typename circular_array<T, _Alloc>::const_reverse_iterator circular_array<T, _Alloc>::crbegin() const noexcept
{
return const_reverse_iterator(end());
}
template <typename T, typename _Alloc>
inline typename circular_array<T, _Alloc>::const_reverse_iterator circular_array<T, _Alloc>::crend() const noexcept
{
return const_reverse_iterator(begin());
}
template <typename T, typename _Alloc>
inline typename circular_array<T, _Alloc>::size_type circular_array<T, _Alloc>::size() const noexcept
{
return _c.size();
}
template <typename T, typename _Alloc> std::vector<T, _Alloc> &circular_array<T, _Alloc>::base() noexcept
{
return _c;
}
#endif // !circular_array_CPP