Doxygen
Toggle main menu visibility
Loading...
Searching...
No Matches
growvector.h
Go to the documentation of this file.
1
/******************************************************************************
2
*
3
* Copyright (C) 1997-2022 by Dimitri van Heesch.
4
*
5
* Permission to use, copy, modify, and distribute this software and its
6
* documentation under the terms of the GNU General Public License is hereby
7
* granted. No representations are made about the suitability of this software
8
* for any purpose. It is provided "as is" without express or implied warranty.
9
* See the GNU General Public License for more details.
10
*
11
* Documents produced by Doxygen are derivative works derived from the
12
* input used in their production; they are not affected by this license.
13
*
14
*/
15
16
#ifndef GROWVECTOR_H
17
#define GROWVECTOR_H
18
19
#include <vector>
20
#include <memory>
21
#include <iterator>
22
23
#include "
construct.h
"
24
25
/** @brief std::vector like container optimized for pushing elements to the back.
26
*
27
* It differs from std::vector in that it can grow without invalidating
28
* pointers to its members just like std::deque and std::list.
29
*
30
* It differs from std::deque in that the value can be incomplete
31
* just like std::vector.
32
*
33
* It differs from std::list in that it does not need to allocate each node
34
* separately and provides random access to its members.
35
*
36
* It is implemented as a vector of chunks where each chunk is a fixed capacity vector of T.
37
*/
38
template
<
class
T>
39
class
GrowVector
40
{
41
private
:
42
static
const
size_t
chunkBits
= 4;
// a chunk holds 2^bits elements
43
static
const
size_t
chunkSize
= 1 <<
chunkBits
;
44
static
const
size_t
chunkMask
=
chunkSize
-1;
45
struct
Chunk
46
{
47
Chunk
() {
data
.reserve(
chunkSize
); }
48
std::vector<T>
data
;
49
};
50
using
ChunkPtr
= std::unique_ptr<Chunk>;
51
52
public
:
53
/// @brief bidirectional iterator
54
template
<
class
C,
class
I>
55
class
Iterator
56
{
57
public
:
58
using
iterator_category
= std::bidirectional_iterator_tag;
59
using
difference_type
= std::ptrdiff_t;
60
using
value_type
= I;
61
using
pointer
= I*;
62
using
reference
= I&;
63
64
Iterator
(C &vec,
size_t
pos) :
m_vec
(&vec),
m_pos
(pos) {}
65
DEFAULT_COPYABLE
(
Iterator
)
66
reference
operator*()
const
{
return
m_vec
->at(
m_pos
); }
67
pointer
operator->
() {
return
&
m_vec
->at(
m_pos
); }
68
Iterator
&
operator++
() {
m_pos
++;
return
*
this
; }
69
Iterator
operator++
(
int
) {
Iterator
tmp = *
this
; ++(*this);
return
tmp; }
70
Iterator
&
operator--
() {
m_pos
--;
return
*
this
; }
71
Iterator
operator--
(
int
) {
Iterator
tmp = *
this
; --(*this);
return
tmp; }
72
friend
bool
operator==
(
const
Iterator
& a,
const
Iterator
& b) {
return
a.
m_pos
== b.
m_pos
; }
73
friend
bool
operator!=
(
const
Iterator
& a,
const
Iterator
& b) {
return
a.
m_pos
!= b.
m_pos
; }
74
75
private
:
76
C *
m_vec
;
77
size_t
m_pos
;
78
};
79
using
iterator
=
Iterator<GrowVector,T>
;
80
using
const_iterator
=
Iterator<const GrowVector,const T>
;
81
82
/// returns an iterator to the beginning
83
iterator
begin
() {
return
iterator
(*
this
,0); }
84
/// returns an iterator to the beginning
85
const_iterator
begin
()
const
{
return
const_iterator
(*
this
,0); }
86
87
/// returns an iterator to the end
88
iterator
end
() {
return
iterator
(*
this
,
size
()); }
89
/// returns an iterator to the end
90
const_iterator
end
()
const
{
return
const_iterator
(*
this
,
size
()); }
91
92
/// returns the number of elements
93
size_t
size
()
const
94
{
95
return
m_chunks
.empty() ? 0 : (
m_chunks
.size()-1)*
chunkSize
+
96
m_chunks
.back()->data.size();
97
}
98
99
/// adds an element to the end
100
void
push_back
(T &&t)
101
{
102
make_room
();
103
m_chunks
.back()->data.push_back(std::move(t));
104
}
105
106
/// constructs an element in-place at the end
107
template
<
class
...Args>
108
void
emplace_back
(Args&&...args)
109
{
110
make_room
();
111
m_chunks
.back()->data.emplace_back(std::forward<Args>(args)...);
112
}
113
114
/// removes the last element
115
void
pop_back
()
116
{
117
m_chunks
.back()->data.pop_back();
118
if
(
m_chunks
.back()->data.size()==0)
// remove chunk if empty
119
{
120
m_chunks
.pop_back();
121
}
122
}
123
124
/// access specified element
125
T &
at
(
size_t
i) {
return
m_chunks
.at(i>>
chunkBits
)->data.at(i&
chunkMask
); }
126
/// access specified element
127
const
T &
at
(
size_t
i)
const
{
return
m_chunks
.at(i>>
chunkBits
)->data.at(i&
chunkMask
); }
128
129
/// access the first element
130
T &
front
() {
return
m_chunks
.front()->data.front(); }
131
/// access the first element
132
const
T &
front
()
const
{
return
m_chunks
.front()->data.front(); }
133
134
/// access the last element
135
T &
back
() {
return
m_chunks
.back()->data.back(); }
136
/// access the last element
137
const
T &
back
()
const
{
return
m_chunks
.back()->data.back(); }
138
139
/// checks whether the container is empty
140
bool
empty
()
const
{
return
m_chunks
.empty(); }
141
142
/// clears the contents
143
void
clear
() {
m_chunks
.clear(); }
144
145
private
:
146
void
make_room
()
147
{
148
if
(
m_chunks
.empty() ||
149
m_chunks
.back()->data.size()==
chunkSize
)
// add new chuck if needed
150
{
151
m_chunks
.push_back(std::make_unique<Chunk>());
152
}
153
}
154
std::vector<ChunkPtr>
m_chunks
;
155
};
156
157
#endif
GrowVector::Iterator
bidirectional iterator
Definition
growvector.h:56
GrowVector::Iterator::iterator_category
std::bidirectional_iterator_tag iterator_category
Definition
growvector.h:58
GrowVector::Iterator::operator!=
friend bool operator!=(const Iterator &a, const Iterator &b)
Definition
growvector.h:73
GrowVector::Iterator::difference_type
std::ptrdiff_t difference_type
Definition
growvector.h:59
GrowVector::Iterator::operator++
Iterator operator++(int)
Definition
growvector.h:69
GrowVector::Iterator::pointer
I * pointer
Definition
growvector.h:61
GrowVector::Iterator< GrowVector, T >::m_pos
size_t m_pos
Definition
growvector.h:77
GrowVector::Iterator::Iterator
Iterator(C &vec, size_t pos)
Definition
growvector.h:64
GrowVector::Iterator::operator++
Iterator & operator++()
Definition
growvector.h:68
GrowVector::Iterator::operator->
pointer operator->()
Definition
growvector.h:67
GrowVector::Iterator::operator--
Iterator operator--(int)
Definition
growvector.h:71
GrowVector::Iterator::value_type
I value_type
Definition
growvector.h:60
GrowVector::Iterator::operator--
Iterator & operator--()
Definition
growvector.h:70
GrowVector::Iterator< GrowVector, T >::m_vec
GrowVector * m_vec
Definition
growvector.h:76
GrowVector::Iterator::reference
I & reference
Definition
growvector.h:62
GrowVector::Iterator::operator==
friend bool operator==(const Iterator &a, const Iterator &b)
Definition
growvector.h:72
GrowVector
std::vector like container optimized for pushing elements to the back.
Definition
growvector.h:40
GrowVector::at
const T & at(size_t i) const
access specified element
Definition
growvector.h:127
GrowVector::clear
void clear()
clears the contents
Definition
growvector.h:143
GrowVector::push_back
void push_back(T &&t)
adds an element to the end
Definition
growvector.h:100
GrowVector::size
size_t size() const
returns the number of elements
Definition
growvector.h:93
GrowVector::end
iterator end()
returns an iterator to the end
Definition
growvector.h:88
GrowVector::back
T & back()
access the last element
Definition
growvector.h:135
GrowVector::front
const T & front() const
access the first element
Definition
growvector.h:132
GrowVector::make_room
void make_room()
Definition
growvector.h:146
GrowVector::const_iterator
Iterator< const GrowVector, const T > const_iterator
Definition
growvector.h:80
GrowVector::chunkSize
static const size_t chunkSize
Definition
growvector.h:43
GrowVector::pop_back
void pop_back()
removes the last element
Definition
growvector.h:115
GrowVector::empty
bool empty() const
checks whether the container is empty
Definition
growvector.h:140
GrowVector::at
T & at(size_t i)
access specified element
Definition
growvector.h:125
GrowVector::back
const T & back() const
access the last element
Definition
growvector.h:137
GrowVector::emplace_back
void emplace_back(Args &&...args)
constructs an element in-place at the end
Definition
growvector.h:108
GrowVector::iterator
Iterator< GrowVector, T > iterator
Definition
growvector.h:79
GrowVector::end
const_iterator end() const
returns an iterator to the end
Definition
growvector.h:90
GrowVector::m_chunks
std::vector< ChunkPtr > m_chunks
Definition
growvector.h:154
GrowVector::chunkBits
static const size_t chunkBits
Definition
growvector.h:42
GrowVector::begin
iterator begin()
returns an iterator to the beginning
Definition
growvector.h:83
GrowVector::chunkMask
static const size_t chunkMask
Definition
growvector.h:44
GrowVector::begin
const_iterator begin() const
returns an iterator to the beginning
Definition
growvector.h:85
GrowVector::front
T & front()
access the first element
Definition
growvector.h:130
GrowVector::ChunkPtr
std::unique_ptr< Chunk > ChunkPtr
Definition
growvector.h:50
construct.h
DEFAULT_COPYABLE
#define DEFAULT_COPYABLE(cls)
Macro to help implementing the rule of 5 for a default copyable & movable class.
Definition
construct.h:29
GrowVector::Chunk::Chunk
Chunk()
Definition
growvector.h:47
GrowVector::Chunk::data
std::vector< T > data
Definition
growvector.h:48
src
growvector.h
Generated by
1.17.0