11#ifndef __BOXES_RING_BUFFER_HPP__ 
   12#define __BOXES_RING_BUFFER_HPP__ 
   14#include "compiler.hpp" 
   31template <
typename T, std::
size_t SizeV> 
class RingBuffer {
 
   34  using reference = T &;
 
   35  using const_reference = 
const T &;
 
   36  using size_type = std::size_t;
 
   37  using difference_type = std::ptrdiff_t;
 
   39  static constexpr size_type Size = SizeV;
 
   44    using reference = T &;
 
   46    using difference_type = std::ptrdiff_t;
 
   47    using iterator_category = std::random_access_iterator_tag;
 
   51    iterator &operator++() {
 
   52      if (pos != cnt->head) {
 
   58    iterator operator++(
int) {
 
   64    iterator &operator--() {
 
   65      if (pos != cnt->tail) {
 
   71    iterator operator--(
int) {
 
   77    reference operator*() { 
return cnt->buffer[pos]; }
 
   79    pointer operator->() { 
return &cnt->buffer[pos]; }
 
   82      return cnt == other.cnt && pos == other.pos;
 
   85    bool operator!=(
const iterator &other)
 const { 
return !(*
this == other); }
 
  100      : head{other.head}, tail{other.tail}, buffer{other.buffer} {}
 
  108      : head{other.head}, tail{other.tail}, buffer{std::move(other.buffer)} {
 
  120    if (
this != &other) {
 
  134    if (
this != &other) {
 
  149  iterator 
begin() { 
return iterator(
this, tail); }
 
  156  iterator 
end() { 
return iterator(
this, head); }
 
  177  bool empty() const BOXES_NOTHROW { 
return head == tail; }
 
  184  bool full() const BOXES_NOTHROW { 
return nextHead() == tail; }
 
  196      throw std::out_of_range(
"RingBuffer::front");
 
  198    return buffer[prevHead()];
 
  211      throw std::out_of_range(
"RingBuffer::back");
 
  243  T &
operator[](size_type pos) { 
return buffer[(tail + pos) % BuffSize]; }
 
  252    return const_cast<RingBuffer *
>(
this)->
operator[](pos);
 
  265  T &
at(size_type pos) {
 
  267      throw std::out_of_range(
"RingBuffer::at");
 
  278  const T &
at(size_type pos)
 const {
 
  295    for (size_type i = 0; i < 
size(); ++i) {
 
  296      if ((*
this)[i] != other[i]) {
 
  314    return !(*
this == other);
 
  325    std::swap(head, other.head);
 
  326    std::swap(tail, other.tail);
 
  327    buffer.swap(other.buffer);
 
  341    const size_type next = nextHead();
 
  343      buffer[head] = std::forward<Arg>(value);
 
  361    const size_type next = prevTail();
 
  364      buffer[tail] = std::forward<Arg>(value);
 
  384    buffer[head] = std::move(T{});
 
  401    buffer[tail] = std::move(T{});
 
  411  size_type 
size() const BOXES_NOTHROW {
 
  415    return BuffSize - tail + head;
 
  432  static constexpr size_type BuffSize = Size + 1;
 
  435  std::array<T, BuffSize> buffer;
 
  437  constexpr static size_type nextPos(size_type pos) BOXES_NOTHROW {
 
  438    return (pos + 1) % BuffSize;
 
  441  constexpr static size_type prevPos(size_type pos) BOXES_NOTHROW {
 
  442    return (pos + BuffSize - 1) % BuffSize;
 
  445  constexpr size_type prevHead() const BOXES_NOTHROW { 
return prevPos(head); }
 
  446  constexpr size_type nextHead() const BOXES_NOTHROW { 
return nextPos(head); }
 
  447  constexpr size_type nextTail() const BOXES_NOTHROW { 
return nextPos(tail); }
 
  448  constexpr size_type prevTail() const BOXES_NOTHROW { 
return prevPos(tail); }
 
Implements a fixed-size double ended queue.
 
bool pop_front()
Removes the first element from the RingBuffer.
 
RingBuffer< T, SizeV > & operator=(const RingBuffer< T, SizeV > &other)
Copy the contents of another RingBuffer into this one.
 
iterator cend() const
Returns a const iterator to the end of the RingBuffer.
 
void swap(RingBuffer< T, SizeV > &other)
Swaps the contents of this RingBuffer with another.
 
iterator cbegin() const
Returns a const iterator to the first element in the RingBuffer.
 
bool push_back(Arg &&value)
Inserts a new element at the end of the RingBuffer.
 
bool full() const BOXES_NOTHROW
Returns true if the RingBuffer is full.
 
const T & at(size_type pos) const
Const version of at
 
RingBuffer(const RingBuffer< T, SizeV > &other)
Copy constructs a RingBuffer from another.
 
bool pop_back()
Removes the last element from the RingBuffer.
 
T & front()
Returns the first element in the queue.
 
void clear()
Clears the contents of the RingBuffer.
 
const T & back() const
Version of back that can be used with const RingBuffers.
 
bool operator==(const RingBuffer< T, SizeV > &other) const
Returns true if the contents of this RingBuffer are equal to another.
 
const T & operator[](size_type pos) const
Returns a const reference to the element at position pos
 
T & operator[](size_type pos)
Allows for random access to the elements in the RingBuffer.
 
RingBuffer(RingBuffer< T, SizeV > &&other)
Move constructs a RingBuffer from another.
 
T & back()
Returns the last element in the queue.
 
size_type size() const BOXES_NOTHROW
Returns the number of elements in the RingBuffer.
 
iterator end()
Returns an iterator to the end of the RingBuffer.
 
bool empty() const BOXES_NOTHROW
Returns true if the RingBuffer is empty.
 
iterator begin()
Returns an iterator to the first element in the RingBuffer.
 
RingBuffer< T, SizeV > & operator=(RingBuffer< T, SizeV > &&other)
Moves the contents of another RingBuffer into this one.
 
T & at(size_type pos)
Allows for random access to the elements in the RingBuffer.
 
bool operator!=(const RingBuffer< T, SizeV > &other) const
Returns true if the contents of this RingBuffer are not equal to another.
 
const T & front() const
Version of front that can be used with const RingBuffers.
 
bool push_front(Arg &&value)
Inserts a new element at the front of the RingBuffer.