@@ -52,21 +52,24 @@ class fragmented_vector {
52
52
53
53
// calculate the maximum number of elements per fragment while
54
54
// keeping the element count a power of two
55
- static constexpr size_t calc_elems_per_frag (size_t esize ) {
56
- size_t max = fragment_size_bytes / esize ;
55
+ static consteval size_t calc_elems_per_frag () {
56
+ size_t max = fragment_size_bytes / sizeof (T) ;
57
57
if constexpr (is_chunked_vector) {
58
- max = max_allocation_size / esize ;
58
+ max = max_allocation_size / sizeof (T) ;
59
59
}
60
- assert (max > 0 );
61
60
return std::bit_floor (max);
62
61
}
63
62
64
- static constexpr size_t elems_per_frag = calc_elems_per_frag(sizeof (T));
65
-
66
- static_assert (
67
- (elems_per_frag & (elems_per_frag - 1 )) == 0 ,
68
- " element count per fragment must be a power of 2" );
69
- static_assert (elems_per_frag >= 1 );
63
+ /* *
64
+ * The maximum number of bytes per fragment as specified in
65
+ * as part of the type. Note that for most types, the true
66
+ * number of bytes in a full fragment may as low as half
67
+ * of this amount (+1) since the number of elements is restricted
68
+ * to a power of two.
69
+ */
70
+ static consteval size_t calc_max_frag_bytes () {
71
+ return calc_elems_per_frag () * sizeof (T);
72
+ }
70
73
71
74
public:
72
75
using this_type = fragmented_vector<T, fragment_size_bytes>;
@@ -81,19 +84,6 @@ class fragmented_vector {
81
84
using pointer = T*;
82
85
using const_pointer = const T*;
83
86
84
- /* *
85
- * The maximum number of bytes per fragment as specified in
86
- * as part of the type. Note that for most types, the true
87
- * number of bytes in a full fragment may as low as half
88
- * of this amount (+1) since the number of elements is restricted
89
- * to a power of two.
90
- */
91
- static constexpr size_t max_frag_bytes = elems_per_frag * sizeof (T);
92
-
93
- static_assert (
94
- max_frag_bytes <= max_allocation_size,
95
- " max size of a fragment must be <= 128KiB" );
96
-
97
87
fragmented_vector () noexcept = default ;
98
88
explicit fragmented_vector (allocator_type alloc)
99
89
: _frags(alloc) {}
@@ -180,7 +170,7 @@ class fragmented_vector {
180
170
--_size;
181
171
if (_frags.back ().empty ()) {
182
172
_frags.pop_back ();
183
- _capacity -= std::min (elems_per_frag , _capacity);
173
+ _capacity -= std::min (calc_elems_per_frag () , _capacity);
184
174
}
185
175
update_generation ();
186
176
}
@@ -203,7 +193,7 @@ class fragmented_vector {
203
193
while (n >= _frags.back ().size ()) {
204
194
n -= _frags.back ().size ();
205
195
_frags.pop_back ();
206
- _capacity -= elems_per_frag ;
196
+ _capacity -= calc_elems_per_frag () ;
207
197
}
208
198
209
199
for (size_t i = 0 ; i < n; ++i) {
@@ -213,18 +203,22 @@ class fragmented_vector {
213
203
}
214
204
215
205
const_reference at (size_t index) const {
206
+ static constexpr size_t elems_per_frag = calc_elems_per_frag ();
216
207
return _frags.at (index / elems_per_frag).at (index % elems_per_frag);
217
208
}
218
209
219
210
reference at (size_t index) {
211
+ static constexpr size_t elems_per_frag = calc_elems_per_frag ();
220
212
return _frags.at (index / elems_per_frag).at (index % elems_per_frag);
221
213
}
222
214
223
215
const_reference operator [](size_t index) const {
216
+ static constexpr size_t elems_per_frag = calc_elems_per_frag ();
224
217
return _frags[index / elems_per_frag][index % elems_per_frag];
225
218
}
226
219
227
220
reference operator [](size_t index) {
221
+ static constexpr size_t elems_per_frag = calc_elems_per_frag ();
228
222
return _frags[index / elems_per_frag][index % elems_per_frag];
229
223
}
230
224
@@ -275,6 +269,7 @@ class fragmented_vector {
275
269
// For fixed size fragments we noop, as we already reserve the full size
276
270
// of vector
277
271
if constexpr (is_chunked_vector) {
272
+ static constexpr size_t elems_per_frag = calc_elems_per_frag ();
278
273
if (new_cap > _capacity) {
279
274
if (_frags.empty ()) {
280
275
auto & frag = _frags.emplace_back ();
@@ -310,7 +305,11 @@ class fragmented_vector {
310
305
/* *
311
306
* Returns the (maximum) number of elements in each fragment of this vector.
312
307
*/
313
- static constexpr size_t elements_per_fragment () { return elems_per_frag; }
308
+ static constexpr size_t elements_per_fragment () {
309
+ return calc_elems_per_frag ();
310
+ }
311
+
312
+ static constexpr size_t max_frag_bytes () { return calc_max_frag_bytes (); }
314
313
315
314
/* *
316
315
* Remove all elements from the vector.
@@ -499,6 +498,10 @@ class fragmented_vector {
499
498
}
500
499
501
500
void add_capacity () {
501
+ static constexpr size_t elems_per_frag = calc_elems_per_frag ();
502
+ static_assert (
503
+ calc_max_frag_bytes () <= max_allocation_size,
504
+ " max size of a fragment must be <= 128KiB" );
502
505
if constexpr (is_chunked_vector) {
503
506
if (
504
507
_frags.size () == 1 && _frags.back ().capacity () < elems_per_frag) {
@@ -510,7 +513,8 @@ class fragmented_vector {
510
513
} else if (_frags.empty ()) {
511
514
// At least one element or 32 bytes worth of elements for small
512
515
// items.
513
- constexpr size_t initial_cap = std::max (1UL , 32UL / sizeof (T));
516
+ static constexpr size_t initial_cap = std::max (
517
+ 1UL , 32UL / sizeof (T));
514
518
_capacity = initial_cap;
515
519
_frags.emplace_back (_frags.get_allocator ()).reserve (_capacity);
516
520
return ;
0 commit comments