基于std::vector的循环旋转数组

实现了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
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值