12#ifndef __BOXES_LINKED_VECTOR_HPP__ 
   13#define __BOXES_LINKED_VECTOR_HPP__ 
   15#include "compiler.hpp" 
   47  using reference = T &;
 
   48  using const_reference = 
const T &;
 
   49  using size_type = std::size_t;
 
   50  using difference_type = std::ptrdiff_t;
 
   52  static constexpr std::size_t ChunkSize = ChunkSizeV;
 
   57    using reference = T &;
 
   59    using difference_type = std::ptrdiff_t;
 
   60    using iterator_category = std::random_access_iterator_tag;
 
   63        : cnt{cnt}, pos{pos} {}
 
   65    iterator &operator++() {
 
   66      if (pos != cnt->
size()) {
 
   72    iterator operator++(
int) {
 
   78    iterator &operator--() {
 
   85    iterator operator--(
int) {
 
   91    reference operator*() { 
return cnt->
at(pos); }
 
   93    pointer operator->() { 
return &cnt->
at(pos); }
 
   96      return cnt == other.cnt && pos == other.pos;
 
   99    bool operator!=(
const iterator &other)
 const { 
return !(*
this == other); }
 
  122      : chunks{std::move(other.chunks)},
 
  123        discardedChunks{std::move(other.discardedChunks)},
 
  124        frontChunk{other.frontChunk}, backChunk{other.backChunk} {
 
  125    other.frontChunk = 
nullptr;
 
  126    other.backChunk = 
nullptr;
 
  139    if (
this != &other) {
 
  154    std::swap(chunks, other.chunks);
 
  155    std::swap(discardedChunks, other.discardedChunks);
 
  156    std::swap(frontChunk, other.frontChunk);
 
  157    std::swap(backChunk, other.backChunk);
 
  175    frontChunk->
push_front(std::forward<Arg>(value));
 
  193    backChunk->
push_back(std::forward<Arg>(value));
 
  205    if (frontChunk == backChunk && frontChunk->
empty()) {
 
  222    if (frontChunk == backChunk && backChunk->
empty()) {
 
  239    if (frontChunk->
empty()) {
 
  240      throw std::out_of_range(
"LinkedVector::front");
 
  243    return frontChunk->
front();
 
  265    if (backChunk->
empty()) {
 
  266      throw std::out_of_range(
"LinkedVector::back");
 
  269    return backChunk->
back();
 
  288    if (
const auto &fs = frontChunk->
size(); pos < fs) {
 
  289      return frontChunk->operator[](pos);
 
  292      auto chunkIndex = pos / ChunkSizeV + 1;
 
  293      auto chunkOffset = pos % ChunkSizeV;
 
  295      auto it = chunks.begin();
 
  296      std::advance(it, chunkIndex);
 
  297      return it->get()->operator[](chunkOffset);
 
  312    return const_cast<LinkedVector *
>(
this)->
operator[](pos);
 
  324  T &
at(size_type pos) {
 
  326      throw std::out_of_range(
"LinkedVector::at");
 
  340  const T &
at(size_type pos)
 const {
 
  349  iterator 
begin() { 
return iterator(
this, 0); }
 
  358  iterator 
end() { 
return iterator(
this, 
size()); }
 
  389    for (
auto it = chunks.cbegin(), otherIt = other.chunks.cbegin();
 
  390         it != chunks.cend(); ++it, ++otherIt) {
 
  391      if (**it != **otherIt) {
 
  406    return !(*
this == other);
 
  414  std::size_t 
size() const BOXES_NOTHROW {
 
  415    switch (chunks.size()) {
 
  419      return frontChunk->
size();
 
  421      return frontChunk->
size() + backChunk->
size();
 
  423      return frontChunk->
size() + backChunk->
size() +
 
  424             (chunks.size() - 2) * ChunkSizeV;
 
  445    return chunks.size() * ChunkSizeV;
 
  453    discardedChunks.clear();
 
  462  bool empty() const BOXES_NOTHROW { 
return size() == 0; }
 
  466  std::list<std::unique_ptr<Chunk>> chunks;
 
  467  std::list<std::unique_ptr<Chunk>> discardedChunks;
 
  468  Chunk *frontChunk{
nullptr};
 
  469  Chunk *backChunk{
nullptr};
 
  472    if (frontChunk != backChunk && frontChunk->
empty()) {
 
  473      discardedChunks.
push_back(std::move(chunks.front()));
 
  475      frontChunk = chunks.
front().get();
 
  480    if (frontChunk != backChunk && backChunk->
empty()) {
 
  481      discardedChunks.push_back(std::move(chunks.back()));
 
  483      backChunk = chunks.
back().get();
 
  488    if (frontChunk->
full()) {
 
  490      frontChunk = c.get();
 
  496    if (backChunk->
full()) {
 
  503  std::unique_ptr<Chunk> getChunk() {
 
  504    if (discardedChunks.empty()) {
 
  505      return std::make_unique<Chunk>();
 
  508    auto c = std::move(discardedChunks.front());
 
  510    discardedChunks.pop_front();
 
  515    chunks.push_back(getChunk());
 
  516    frontChunk = chunks.
front().get();
 
  517    backChunk = chunks.
back().get();
 
Implements a vector-like container that uses a linked list of fixed-size chunks to store its elements...
 
const T & operator[](size_type pos) const
Returns a const reference to the element at the specified position.
 
bool operator!=(const LinkedVector< T, ChunkSizeV > &other) const
Returns true if the two containers are not equal.
 
T & front()
Returns a reference to the first element in the container.
 
iterator cbegin() const
Returns a const iterator to the first element of the container.
 
const T & front() const
Returns a const reference to the first element in the container.
 
LinkedVector(LinkedVector< T, ChunkSizeV > &&other)
Move constructor.
 
std::size_t size() const BOXES_NOTHROW
Returns the number of elements in the container.
 
std::size_t capacity() const BOXES_NOTHROW
Returns the maximum number of elements the container can hold without additional memory allocation.
 
T & back()
Returns a reference to the last element in the container.
 
bool operator==(const LinkedVector< T, ChunkSizeV > &other) const
Returns true if the two containers are equal.
 
void swap(LinkedVector< T, ChunkSizeV > &other)
Swaps the contents of this LinkedVector with another.
 
const T & back() const
Returns a const reference to the last element in the container.
 
void pop_front()
Removes the first element from the container.
 
void clear()
Removes all elements from the container.
 
LinkedVector< T, ChunkSizeV > & operator=(LinkedVector< T, ChunkSizeV > &&other)
Move assignment operator.
 
T & at(size_type pos)
Returns a reference to the element at the specified position.
 
iterator end()
Returns an iterator to the element following the last element of the container.
 
void pop_back()
Removes the last element from the container.
 
LinkedVector()
Constructs an empty container.
 
T & operator[](size_type pos)
Provides access to the element at the specified position.
 
iterator begin()
Returns an iterator to the first element of the container.
 
void push_front(Arg &&value)
Pushes a new element to the front of the container.
 
bool empty() const BOXES_NOTHROW
Returns true if the container is empty.
 
iterator cend() const
Returns a const iterator to the element following the last element.
 
void push_back(Arg &&value)
Pushes a new element to the back of the container.
 
const T & at(size_type pos) const
Returns a const reference to the element at the specified position.
 
Implements a fixed-size double ended queue.
 
bool pop_front()
Removes the first element from 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.
 
bool pop_back()
Removes the last element from the RingBuffer.
 
T & front()
Returns the first element in the queue.
 
T & back()
Returns the last element in the queue.
 
size_type size() const BOXES_NOTHROW
Returns the number of elements in the RingBuffer.
 
bool empty() const BOXES_NOTHROW
Returns true if the RingBuffer is empty.
 
bool push_front(Arg &&value)
Inserts a new element at the front of the RingBuffer.
 
Implements a fixed-size double-ended queue.