28 #include <type_traits>
50 template <
typename T,
size_t N = 512>
75 for (
const auto& elem : other) {
78 assert(
m_size == other.m_size);
79 assert(
m_blocks.size() == other.m_blocks.size());
80 assert(this->
capacity() == other.capacity());
97 for (
const auto& elem : other) {
100 assert(
m_size == other.m_size);
101 assert(
m_blocks.size() == other.m_blocks.size());
102 assert(this->
capacity() == other.capacity());
111 if (
this != &other) {
113 m_blocks = std::move(other.m_blocks);
114 std::swap(
m_size, other.m_size);
127 T&
at(std::size_t pos)
130 throw std::out_of_range(
"CompactStorage: index out of range.");
132 const size_t b = pos / N;
133 const size_t i = pos % N;
134 return *
static_cast<T*
>(
static_cast<void*
>(&(
m_blocks[b][i])));
138 const T&
at(std::size_t pos)
const
141 throw std::out_of_range(
"CompactStorage: index out of range.");
143 const size_t b = pos / N;
144 const size_t i = pos % N;
145 return *
static_cast<const T*
>(
static_cast<const void*
>(&(
m_blocks[b][i])));
154 return *
static_cast<const T*
>(
static_cast<const void*
>(&
m_blocks[(
m_size - 1) / N][(
m_size - 1) % N]));
158 T&
operator[](
size_t pos) {
return *
static_cast<T*
>(
static_cast<void*
>(&(
m_blocks[pos / N][pos % N]))); }
163 return *
static_cast<const T*
>(
static_cast<const void*
>(&(
m_blocks[pos / N][pos % N])));
223 while (req_blocks <
m_blocks.size()) {
231 for (
auto& i : *
this) {
242 template <
class... Args>
246 return new (memory) T(std::forward<Args>(args)...);
254 throw std::logic_error(
"CompactStorage::pop_back called on empty object.");
262 const size_t last_block_index =
m_blocks.size() - 1;
263 if (
m_size <= last_block_index * N) {
264 delete[]
m_blocks[last_block_index];
273 return new (memory) T(obj);
280 return new (memory) T(std::move(obj));
285 using Chunk =
typename std::aligned_storage<sizeof(T), std::alignment_of<T>::value>::type;
295 const size_t b =
m_size / N;
296 const size_t i =
m_size % N;
299 auto chunk =
new Chunk[N];
303 return static_cast<T*
>(
static_cast<void*
>(&((
m_blocks[b])[i])));
T * push_back(const T &obj)
Adds element to end.
std::size_t capacity() const
Returns number of elements that can be stored without allocating additional blocks.
const_iterator begin() const
Returns a const_iterator to the beginning of the container.
iterator end()
Returns an iterator to the end of the container.
T * emplace_back(Args &&...args)
Constructs element in-place at the end.
T * push_back(T &&obj)
Adds element to end.
typename std::aligned_storage< sizeof(T), std::alignment_of< T >::value >::type Chunk
POD type with same alignment requirement as for T's.
Interface/Implementation for Iterator.
const_iterator end() const
Returns a const_iterator to the end of the container.
const_iterator cend() const
Returns a const_iterator to the end.
const T & operator[](size_t pos) const
Access specified element (no bounds checking).
SVIterator< T, N > const_iterator
SegmentedVector & operator=(self_type &&other) noexcept
Move assignment (copies elements & capacity).
SegmentedVector & operator=(const self_type &other)
Copy assignment (copies elements & capacity).
void reserve(size_type new_capacity)
Allocates aditional blocks to achieve requested capacity.
bool empty() const
Checks whether container is empty.
Implementation of iterator for SegmentedVector.
const_iterator cbegin() const
Returns a const_iterator to the beginning of the container.
T & at(std::size_t pos)
Access specified element with bounds checking.
~SegmentedVector()
Destructor.
T & back()
Access the last element.
iterator begin()
Returns an iterator to the beginning of the container.
SegmentedVector()
Construct empty SegmentedVector.
std::size_t get_elements_per_block() const
Returns number of elements block (template parameter 'N').
std::size_t size() const
Returns the number of elements.
Container that stores objects "almost contiguously" and guarantees that pointers/iterators are not in...
std::vector< Chunk * > m_blocks
Vector registers pointers to blocks of chunks.
SVIterator< T, N, T *, T &, false > iterator
size_t m_size
Index of first free chunk when indexed contiguously.
std::size_t get_block_count() const
Returns number of currently allocated blocks.
SegmentedVector(self_type &&other) noexcept
Move constructor (moves elements & capacity).
void pop_back()
Removes the last element.
T & operator[](size_t pos)
Access specified element (no bounds checking).
const T & back() const
Access the last element.
T * get_chunk()
Get next available chunk for element construction with placement new.
SegmentedVector(const self_type &other)
Copy constructor (copies elements & capacity).
const T & at(std::size_t pos) const
Access specified element with bounds checking.
void clear()
Clears the content.
void shrink_to_fit()
Deallocates (empty) blocks to schrink capacity to fit current size.
static constexpr std::size_t m_end
One past the last element iterator position.