• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

PeterCDMcLean / BitLib / 15696998807

17 Jun 2025 02:58AM UTC coverage: 54.11% (+0.6%) from 53.519%
15696998807

push

github

web-flow
Truncation policy (#17)

* Add draft policies for integer conversion

* Add allocator to Policy. Use policy to construct from integral

* Add convenience conversion pathway for literal -> bit_value

* Add algorithm accumulate and utility to_string

* template keyword only necessary if actually passing template args

* Better UX for accumulate policy

* small tweaks to to_string

* Add static_assert error to bit_literal.

* Consolidate from_integral code

* Fix accumulate, get_word doesn't mask

10137 of 18710 branches covered (54.18%)

Branch coverage included in aggregate %.

212 of 251 new or added lines in 13 files covered. (84.46%)

214 existing lines in 11 files now uncovered.

6062 of 11227 relevant lines covered (53.99%)

7736453.1 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

90.27
/include/bitlib/bit-containers/bit_vector.hpp
1
// ================================= BIT_VECTOR =================================== //
2
// Project:     The Experimental Bit Algorithms Library
3
// \file        bit_vector.hpp
4
// Description: Implementation of bit_vector
5
// Contributor: Bryce Kille
6
// License:     BSD 3-Clause License
7
// ========================================================================== //
8
#ifndef _BIT_VECTOR_HPP_INCLUDED
9
#define _BIT_VECTOR_HPP_INCLUDED
10
// ========================================================================== //
11

12

13

14
// ================================ PREAMBLE ================================ //
15
// C++ standard library
16
#include <algorithm>
17
#include <cmath>
18
#include <iostream>
19
#include <ranges>
20
#include <string>
21
#include <type_traits>
22
#include <vector>
23
// Project sources
24
#include "bitlib/bit-algorithms/bit_algorithm.hpp"
25
#include "bitlib/bit-containers/bit_span.hpp"
26
#include "bitlib/bit-iterator/bit.hpp"
27
#include "bitlib/bit_concepts.hpp"
28

29
// Third-party libraries
30
// Miscellaneous
31
namespace bit {
32
// ========================================================================== //
33

34

35

36
/* ****************************** BIT VECTOR ****************************** */
37
//! A bit-vector with a similar interface to std::vector<bool>
38
template <class WordType = uint8_t, class Allocator = std::allocator<WordType>>
39
class bit_vector {
40
 private:
41
  static constexpr size_t digits = binary_digits<WordType>::value;
42
  std::vector<WordType, Allocator> word_vector;
43
  size_t length_ = 0;
44

45
  // TODO are privates always inlined?
46
  // @brief Get the number of words needed to represet num_bits bits
47
  constexpr uint64_t word_count(unsigned int num_bits) {
286,279✔
48
    return ((num_bits + digits - 1) / digits);
286,279✔
49
  }
143,140✔
50

51
  // Iterator pair constructor specializations
52
  // Passing in iterator over bool
53
  template <class RandomAccessIt>
54
  typename std::enable_if<
55
      std::is_same<
56
          typename std::iterator_traits<RandomAccessIt>::value_type,
57
          bool>::value>::type constexpr range_constructor(RandomAccessIt first,
58
                                                          RandomAccessIt last,
59
                                                          const Allocator& alloc);
60

61
  // Passing in iterator over WordType constructs via whole words
62
  template <class RandomAccessIt>
63
  typename std::enable_if<
64
      std::is_same<
65
          typename std::iterator_traits<RandomAccessIt>::value_type,
66
          WordType>::value>::type constexpr range_constructor(RandomAccessIt first,
67
                                                              RandomAccessIt last,
68
                                                              const Allocator& alloc);
69

70
 public:
71
  /*
72
         * Types and typedefs
73
         */
74
  using value_type = bit_value;
75
  using base_type = WordType;
76
  using allocator_type = Allocator;
77
  using size_type = std::size_t;
78
  using difference_type = std::ptrdiff_t;
79
  using reference = bit_reference<WordType&>;  // typename std::vector<WordType>::reference>;
80
  using const_reference = const reference;
81
  using pointer = bit_pointer<WordType>;
82
  using iterator = bit_iterator<typename std::vector<WordType>::iterator>;
83
  using const_iterator = bit_iterator<typename std::vector<WordType>::const_iterator>;
84

85
  /*
86
         * Constructors, copies and moves...
87
         */
88
  constexpr bit_vector() noexcept(noexcept(Allocator()));
89
  constexpr explicit bit_vector(const Allocator& alloc) noexcept;
90
  constexpr bit_vector(
91
      size_type count,
92
      value_type bit_val,
93
      const Allocator& alloc = Allocator());
94
  constexpr explicit bit_vector(
95
      size_type count,
96
      const Allocator& alloc = Allocator());
97
  template <bit_iterator_c Iterator>
98
  constexpr bit_vector(Iterator first, Iterator last, const Allocator& alloc = Allocator());
99

100
  template <bit_range _Range>
101
  constexpr bit_vector(std::from_range_t, _Range&& rg, const Allocator& alloc = Allocator());
102

103
  template <class RandomAccessIt>
104
  constexpr bit_vector(
105
      RandomAccessIt first,
106
      RandomAccessIt last,
107
      const Allocator& alloc = Allocator());
108
  constexpr bit_vector(const bit_vector<WordType, Allocator>& other) = default;
570,496✔
109
  constexpr bit_vector(const bit_vector<WordType, Allocator>& other, const Allocator& alloc);
110
  constexpr bit_vector(const bit_vector<WordType, Allocator>&& other) noexcept;
111
  constexpr bit_vector(const bit_vector<WordType, Allocator>&& other, const Allocator& alloc);
112
  constexpr bit_vector(std::initializer_list<bit_value> init, const Allocator& alloc = Allocator());
113
  constexpr bit_vector(std::initializer_list<bool> init, const Allocator& alloc = Allocator());
114
  constexpr bit_vector(std::initializer_list<WordType> init, const Allocator& alloc = Allocator());
115
  constexpr bit_vector(std::string_view s);
116

117
#if __cplusplus == 201703L
118
        ~bit_vector();
119
#else
120
        constexpr ~bit_vector();
121
#endif
122

123

124
        /*
125
         * Assignment
126
         */
127
        constexpr bit_vector& operator=(const bit_vector<WordType, Allocator>& other) = default;
8,160✔
128
        constexpr bit_vector& operator=(bit_vector<WordType, Allocator>&& other) noexcept;
129

130

131
        /*
132
         * Element Access
133
         */
134
        constexpr reference operator[](size_type pos);
135
        constexpr reference operator[](size_type pos) const;
136
        constexpr reference at(size_type pos);
137
        constexpr const_reference at(size_type pos) const;
138
        constexpr reference front();
139
        constexpr const_reference front() const;
140
        constexpr reference back();
141
        constexpr const_reference back() const;
142
        constexpr WordType* data() noexcept;
143
        constexpr const WordType* data() const noexcept;
144

145
        /*
146
         * Iterators
147
         */
148
        constexpr iterator begin() noexcept;
149
        constexpr iterator end() noexcept;
150
        constexpr const_iterator begin() const noexcept;
151
        constexpr const_iterator end() const noexcept;
152
        constexpr const_iterator cbegin() const noexcept;
153
        constexpr const_iterator cend() const noexcept;
154

155

156
        /*
157
         * Capacity
158
         */
159
        constexpr bool empty() const noexcept;
160
        constexpr size_type size() const noexcept;
161
        constexpr size_type max_size() const noexcept;
162
        constexpr void reserve(size_type new_cap);
163
        constexpr size_type capacity() const noexcept;
164
        constexpr void shrink_to_fit();
165

166

167
        /*
168
         * Modifiers
169
         */
170
        constexpr void clear() noexcept;
171
        constexpr iterator insert(const_iterator pos, const value_type& value);
172
        constexpr iterator insert(const_iterator pos, size_type count, const value_type& value);
173
        template <bit_iterator_c OtherIt>
174
        constexpr iterator insert(const_iterator pos, OtherIt first, OtherIt last);
175
        constexpr iterator erase(iterator pos);
176
        constexpr iterator erase(iterator first, iterator last);
177
        constexpr void push_back(const value_type& value);
178
        constexpr void pop_back();
179
        constexpr void resize(size_type count);
180
        constexpr void resize(size_type count, const value_type& value);
181
        template <bit_range R>
182
        constexpr iterator insert_range(const_iterator pos, R&& range);
183
        template <bit_range R>
184
        constexpr void append_range(R&& range);
185

186
        /*
187
          * Slice
188
        */
189
        constexpr bit_array_ref<> operator()(size_type begin, size_type end) const noexcept;
190

191
        /*
192
         * Helper functions
193
         */
194
        constexpr std::string debug_string(const_iterator first, const_iterator end);
195
        constexpr std::string debug_string();
196

197
        // TODO Make constexpr
198
        //friend std::ostream& operator<<(std::ostream& os, bit_vector bv) {
199
            //return os << bv.debug_string(bv.cbegin(), bv.cend());;
200
        //}
201
};
202
static_assert(bit_range<bit_vector<uint8_t>>, "bit_vector<integral> does not satisfy bit_range concept!");
203
static_assert(bit_sized_range<bit_vector<uint8_t>>, "bit_vector<integral> does not satisfy bit_sized_range concept!");
204
#ifdef CONTIGUOUS_RANGE
205
static_assert(bit_contiguous_range<bit_vector<uint8_t>>, "bit_vector<integral> does not satisfy bit_contiguous_range concept!");
206
static_assert(bit_contiguous_sized_range<bit_vector<uint8_t>>, "bit_vector<integral> does not satisfy bit_contiguous_sized_range concept!");
207
#endif
208

209
/* ************************************************************************** */
210

211

212

213
// ------------------------ BIT VECTOR: LIFECYCLE ------------------------- //
214
template<class WordType, class Allocator>
215
constexpr bit_vector<WordType, Allocator>::bit_vector() noexcept(noexcept(Allocator())) : word_vector{}, length_(0) {}
1,729✔
216

217
template<class WordType, class Allocator>
218
constexpr bit_vector<WordType, Allocator>::bit_vector(const Allocator& alloc) noexcept : word_vector(alloc), length_(0) {}
219

220
template<class WordType, class Allocator>
221
constexpr bit_vector<WordType, Allocator>::bit_vector(size_type count, value_type bit_val, const Allocator& alloc)
1,920✔
222
    : word_vector(word_count(count), static_cast<WordType>(bit_val == bit1 ? -1 : 0), alloc),
3,840✔
223
      length_(count)
3,840✔
224
      {}
3,840✔
225

226
template<class WordType, class Allocator>
227
constexpr bit_vector<WordType, Allocator>::bit_vector(size_type count, const Allocator& alloc)
71,305✔
228
    : word_vector(word_count(count), alloc), length_(count) {}
213,915✔
229

230
//TODO needs to work for input iterators
231
template <class WordType, class Allocator>
232

233
template <bit_iterator_c Iterator>
234
constexpr bit_vector<WordType, Allocator>::bit_vector(Iterator first, Iterator last, const Allocator& alloc)
1✔
235
    : word_vector(distance(first, last), alloc), length_(distance(first, last)) {
2✔
236
  copy(first, last, this->begin());
2✔
237
}
2✔
238

239
template <class WordType, class Allocator>
240
template <bit_range _Range>
241
constexpr bit_vector<WordType, Allocator>::bit_vector(std::from_range_t, _Range&& rg, const Allocator& alloc)
1✔
242
    : bit_vector(rg.begin(), rg.end(), alloc) {
2✔
243
}
2✔
244

245
template<class WordType, class Allocator>
246
template<class RandomAccessIt>
247
constexpr bit_vector<WordType, Allocator>::bit_vector(
1,976✔
248
        RandomAccessIt first,
249
        RandomAccessIt last,
250
        const Allocator& alloc) {
3,952✔
251
    bit_vector<WordType, Allocator>::range_constructor(
3,952✔
252
        first,
1,976✔
253
        last,
1,976✔
254
        alloc
1,976✔
255
    );
1,976✔
256
}
3,952✔
257

258
template<class WordType, class Allocator>
259
constexpr bit_vector<WordType, Allocator>::bit_vector(const bit_vector<WordType, Allocator>&& other) noexcept
131,184✔
260
    : word_vector(std::move(other.word_vector)), length_(other.length_) {}
262,368✔
261

262
template<class WordType, class Allocator>
263
constexpr bit_vector<WordType, Allocator>::bit_vector(const bit_vector<WordType, Allocator>&& other, const Allocator& alloc)
264
    : word_vector(std::move(other.word_vector), alloc), length_(other.length_) {}
265

266
template<class WordType, class Allocator>
267
constexpr bit_vector<WordType, Allocator>::bit_vector(std::initializer_list<bit_value> init, const Allocator& alloc)
268
    : word_vector(alloc), length_(0) {
269
    for (const_reference b : init) {
270
        this->push_back(b);
271
    }
272
}
273

274
template<class WordType, class Allocator>
275
constexpr bit_vector<WordType, Allocator>::bit_vector(std::initializer_list<bool> init, const Allocator& alloc)
8✔
276
    : word_vector(alloc), length_(0) {
16✔
277
    for (const bool& b : init) {
200✔
278
        this->push_back(static_cast<bit_value>(b));
192✔
279
    }
96✔
280
}
16✔
281

282
template<class WordType, class Allocator>
283
constexpr bit_vector<WordType, Allocator>::bit_vector(
284
        std::initializer_list<WordType> init,
285
        const Allocator& alloc)
286
    : word_vector(init, alloc), length_(this->word_vector.size() * digits) {}
287

288
// Skip all characters that are not 0/1. This allows punctuation/spacing for byte/word boundaries
289
template<class WordType, class Allocator>
290
constexpr bit_vector<WordType, Allocator>::bit_vector(std::string_view s) {
3,744✔
291
    this->length_ = std::count(s.begin(), s.end(), '0') + std::count(s.begin(), s.end(), '1');
2,496✔
292
    this->word_vector = std::vector<WordType, Allocator>(this->length_);
4,992✔
293
    size_type i = 0;
2,496✔
294
    for (char c : s) {
179,552✔
295
        if (c == '0') {
178,304✔
296
            begin()[i++] = bit0;
116,320✔
297
        } else if (c == '1') {
121,792!
298
            begin()[i++] = bit1;
61,984✔
299
        }
14,672✔
300
    }
89,152✔
301
}
2,496✔
302

303
// Iterator pair constructor specializations
304
// Passing in iterator over bool
305
template<class WordType, class Allocator>
306
template<class RandomAccessIt>
307
typename std::enable_if<
308
    std::is_same<
309
        typename std::iterator_traits<RandomAccessIt>::value_type,
310
        bool
311
    >::value
312
>::type
313
constexpr bit_vector<WordType, Allocator>::range_constructor(
1,016✔
314
        RandomAccessIt first,
315
        RandomAccessIt last,
316
        const Allocator& alloc) {
1,016✔
317
    word_vector = std::vector<WordType, Allocator>(std::distance(first, last), alloc);
3,048✔
318
    length_ = std::distance(first, last);
2,032✔
319
    std::transform(
2,032✔
320
            first,
1,016✔
321
            last,
1,016✔
322
            begin(),
1,016✔
323
            [](bool b) {return static_cast<bit_value>(b);}
8,123,904✔
324
    );
1,016✔
325
}
2,032✔
326

327
// Passing in iterator over WordType constructs via whole words
328
template<class WordType, class Allocator>
329
template<class RandomAccessIt>
330
typename std::enable_if<
331
    std::is_same<
332
        typename std::iterator_traits<RandomAccessIt>::value_type,
333
        WordType
334
    >::value
335
>::type
336
constexpr bit_vector<WordType, Allocator>::range_constructor(
960✔
337
        RandomAccessIt first,
338
        RandomAccessIt last,
339
        const Allocator& alloc) {
960✔
340
    word_vector = std::vector<WordType, Allocator>(first, last, alloc);
1,920✔
341
    length_ = digits * std::distance(first, last);
1,920✔
342
}
1,920✔
343

344
template<class WordType, class Allocator>
345
#if __cplusplus == 201703L
346
bit_vector<WordType, Allocator>::~bit_vector() {
347
#else
348
constexpr bit_vector<WordType, Allocator>::~bit_vector() {
701,686✔
349
#endif
350,843✔
350
    length_ = 0;
701,686✔
351
}
701,686✔
352
// -------------------------------------------------------------------------- //
353

354

355

356
// ------------------------ BIT VECTOR: ASSIGNMENT ------------------------ //
357
template<class WordType, class Allocator>
358
constexpr bit_vector<WordType, Allocator>&
359
bit_vector<WordType, Allocator>::operator=(bit_vector<WordType, Allocator>&& other) noexcept {
12,224✔
360
    length_ = other.length_;
12,224✔
361
    word_vector = std::move(other.word_vector);
12,224✔
362
    other.length_ = 0;
12,224✔
363
    return *this;
12,224✔
364
}
6,112✔
365
// -------------------------------------------------------------------------- //
366

367

368

369
// -------------------------- BIT VECTOR: ACCESS -------------------------- //
370
template<class WordType, class Allocator>
371
constexpr typename bit_vector<WordType, Allocator>::reference
372
bit_vector<WordType, Allocator>::operator[](size_type pos) {return begin()[pos];}
32,858,336✔
373

374
template<class WordType, class Allocator>
375
constexpr typename bit_vector<WordType, Allocator>::reference
376
bit_vector<WordType, Allocator>::operator[](size_type pos) const {return begin()[pos];}
377

378
template<class WordType, class Allocator>
379
constexpr typename bit_vector<WordType, Allocator>::reference
380
bit_vector<WordType, Allocator>::at(size_type pos) {
5,779,600✔
381
    if (pos < length_) {
5,779,600✔
382
        return begin()[pos];
8,123,952✔
383
    } else {
2,707,984✔
384
        throw std::out_of_range("Position is out of range");
363,632✔
385
    }
181,816✔
386
}
2,889,800✔
387

388
template<class WordType, class Allocator>
389
constexpr typename bit_vector<WordType, Allocator>::const_reference
390
bit_vector<WordType, Allocator>::at(size_type pos) const {
391
    if (pos < length_) {
392
        return begin()[pos];
393
    } else {
394
        throw std::out_of_range("Position is out of range");
395
    }
396
}
397

398
template<class WordType, class Allocator>
399
constexpr typename bit_vector<WordType, Allocator>::reference
400
bit_vector<WordType, Allocator>::front() {
401
    return begin()[0];
402
}
403

404
template<class WordType, class Allocator>
405
constexpr typename bit_vector<WordType, Allocator>::const_reference
406
bit_vector<WordType, Allocator>::front() const {
407
    return begin()[0];
408
}
409

410
template<class WordType, class Allocator>
411
constexpr typename bit_vector<WordType, Allocator>::reference
412
bit_vector<WordType, Allocator>::back() {
413
    return begin()[length_ - 1];
414
}
415

416
template<class WordType, class Allocator>
417
constexpr typename bit_vector<WordType, Allocator>::const_reference
418
bit_vector<WordType, Allocator>::back() const {
419
    return begin()[length_ - 1];
420
}
421

422
template<class WordType, class Allocator>
423
constexpr WordType*
424
bit_vector<WordType, Allocator>::data() noexcept {
425
    return length_ ? &(word_vector[0]) : 0;
426
}
427

428
template<class WordType, class Allocator>
429
constexpr const WordType*
430
bit_vector<WordType, Allocator>::data() const noexcept {
431
    return word_vector.size() ? &(word_vector[0]) : 0;
432
}
433
// -------------------------------------------------------------------------- //
434

435

436

437
// ------------------------ BIT VECTOR: ITERATORS --------------------------- //
438
template<class WordType, class Allocator>
439
constexpr typename bit_vector<WordType, Allocator>::iterator
440
bit_vector<WordType, Allocator>::begin() noexcept {
25,736,399✔
441
    return iterator(word_vector.begin());
25,736,399✔
442
}
12,868,298✔
443

444
template<class WordType, class Allocator>
445
constexpr typename bit_vector<WordType, Allocator>::iterator
446
bit_vector<WordType, Allocator>::end() noexcept {
1,227,428✔
447
    return begin() + length_;
1,227,428✔
448
}
613,739✔
449

450
template<class WordType, class Allocator>
451
constexpr typename bit_vector<WordType, Allocator>::const_iterator
452
bit_vector<WordType, Allocator>::begin() const noexcept {
453
    return const_iterator(word_vector.begin());
454
}
455

456
template<class WordType, class Allocator>
457
constexpr typename bit_vector<WordType, Allocator>::const_iterator
458
bit_vector<WordType, Allocator>::end() const noexcept {
459
    return const_iterator(word_vector.cbegin()) + length_;
460
}
461

462
template<class WordType, class Allocator>
463
constexpr typename bit_vector<WordType, Allocator>::const_iterator
464
bit_vector<WordType, Allocator>::cbegin() const noexcept {
99,844✔
465
    return const_iterator(word_vector.begin());
99,844✔
466
}
49,922✔
467

468
template<class WordType, class Allocator>
469
constexpr typename bit_vector<WordType, Allocator>::const_iterator
470
bit_vector<WordType, Allocator>::cend() const noexcept {
471
    return const_iterator(word_vector.cbegin()) + length_;
472
}
473
// -------------------------------------------------------------------------- //
474

475

476

477
// ------------------------ BIT VECTOR: CAPACITY ---------------------------- //
478
template<class WordType, class Allocator>
479
constexpr bool bit_vector<WordType, Allocator>::empty() const noexcept {
48✔
480
    return length_ == 0;
48✔
481
}
24✔
482

483
template<class WordType, class Allocator>
484
constexpr typename bit_vector<WordType, Allocator>::size_type
485
bit_vector<WordType, Allocator>::size() const noexcept {
277,926✔
486
    return length_;
277,926✔
487
}
138,963✔
488

489
template<class WordType, class Allocator>
490
constexpr typename bit_vector<WordType, Allocator>::size_type
491
bit_vector<WordType, Allocator>::max_size() const noexcept {
492
    return word_vector.max_size() * digits;
493
}
494

495
template<class WordType, class Allocator>
496
constexpr void bit_vector<WordType, Allocator>::reserve(size_type new_cap) {
80✔
497
    word_vector.reserve(word_count(new_cap));
80✔
498
}
80✔
499

500
template<class WordType, class Allocator>
501
constexpr typename bit_vector<WordType, Allocator>::size_type
502
bit_vector<WordType, Allocator>::capacity() const noexcept {
4,144✔
503
    return word_vector.capacity() * digits;
4,144✔
504
}
2,072✔
505

506
template<class WordType, class Allocator>
507
constexpr void bit_vector<WordType, Allocator>::shrink_to_fit() {
2,064✔
508
    word_vector.shrink_to_fit();
2,064✔
509
}
2,064✔
510
// -------------------------------------------------------------------------- //
511

512

513

514
// ------------------------ BIT VECTOR: MODIFYING -------------------------- //
515
template<class WordType, class Allocator>
516
constexpr void bit_vector<WordType, Allocator>::clear() noexcept {
2,112✔
517
    word_vector.clear(); length_ = 0;
2,112✔
518
}
2,112✔
519

520
template<class WordType, class Allocator>
521
constexpr typename bit_vector<WordType, Allocator>::iterator
522
bit_vector<WordType, Allocator>::insert(
49,152✔
523
        const_iterator pos,
524
        const value_type& value) {
49,152✔
525
    const auto d = distance(cbegin(), pos);
98,304✔
526
    if (this->word_vector.size()*digits == length_) {
98,304✔
527
        word_vector.push_back(0U);
3,432✔
528
    }
1,716✔
529
    length_ += 1;
98,304✔
530
    shift_right(begin() + d, begin() + length_, 1);
98,304✔
531
    begin()[d] = value;
98,304✔
532
    return begin() + d;
147,456✔
533
}
49,152✔
534

535
// TODO should use std::insert to maintain the constant amortized time.
536
template<class WordType, class Allocator>
537
constexpr typename bit_vector<WordType, Allocator>::iterator
538
bit_vector<WordType, Allocator>::insert(
384✔
539
        const_iterator pos,
540
        size_type count,
541
        const bit_vector<WordType, Allocator>::value_type& value) {
384✔
542
    const auto d = distance(cbegin(), pos);
768✔
543
    if (count == 0) {
768!
UNCOV
544
        return begin() + d;
16✔
UNCOV
545
    }
546
    const float bits_available = word_vector.size() * digits;
752✔
547
    const bool need_to_add = length_ + count > bits_available;
752✔
548
    if (need_to_add) {
752!
549
        const auto words_to_add = word_count(length_ + count - bits_available);
716✔
550
        word_vector.resize(word_vector.size() + words_to_add);
716✔
551
    }
369✔
552
    length_ += count;
752✔
553
    shift_right(begin() + d, begin() + length_, count);
752✔
554
    fill(begin() + d, begin() + d + count, value);
752✔
555
    return begin() + d;
752✔
556
}
384✔
557

558
template <class WordType, class Allocator>
559
template <bit_iterator_c OtherIt>
560
constexpr typename bit_vector<WordType, Allocator>::iterator
561
bit_vector<WordType, Allocator>::insert(
386✔
562
    const_iterator pos,
563
    OtherIt first,
564
    OtherIt last) {
386✔
565
  const auto d = distance(cbegin(), pos);
772✔
566
  const size_t count = distance(first, last);
772✔
567
  if (count == 0) {
772!
568
    return begin() + d;
×
UNCOV
569
  }
570
  const float bits_available = word_vector.size() * digits;
772✔
571
  const auto need_to_add = length_ + count > bits_available;
772✔
572
  if (need_to_add) {
772!
573
    const auto words_to_add = word_count(length_ + count - bits_available);
732✔
574
    word_vector.resize(word_vector.size() + words_to_add);
732✔
575
  }
354✔
576
  length_ += count;
772✔
577
  shift_right(begin() + d, begin() + length_, count);
772✔
578
  copy(first, last, begin() + d);
772✔
579
  return begin() + d;
772✔
580
}
386✔
581

582
template<class WordType, class Allocator>
583
constexpr typename bit_vector<WordType, Allocator>::iterator
584
bit_vector<WordType, Allocator>::erase(iterator pos) {
677✔
585
    shift_left(pos, begin() + length_, 1);
677✔
586
    length_ -= 1;
677✔
587
    if (length_ % digits == 0) {
677!
588
        word_vector.pop_back();
41✔
589
    }
18✔
590
    return pos;
1,001✔
591
}
353✔
592

593
template<class WordType, class Allocator>
594
constexpr typename bit_vector<WordType, Allocator>::iterator
595
bit_vector<WordType, Allocator>::erase(iterator first, iterator last) {
579✔
596
    const auto d = distance(begin(), first);
579✔
597
    auto count = distance(first, last);
579✔
598
    if (count == 0) {
579!
599
        return last;
246✔
600
    }
120✔
601
    shift_left(first, end(), count);
333✔
602
    length_ -= count;
333✔
603
    word_vector.resize(word_count(length_));
333✔
604
    return begin() + d;
333✔
605
}
288✔
606

607
template<class WordType, class Allocator>
608
constexpr void bit_vector<WordType, Allocator>::push_back(const value_type& value) {
361,794✔
609
    if (this->word_vector.size()*digits == length_) {
361,794✔
610
        word_vector.push_back(0U);
8,150✔
611
    }
4,075✔
612
    begin()[length_] = value;
361,794✔
613
    length_ += 1;
361,794✔
614
    return;
542,691✔
615
}
180,897✔
616

617
template<class WordType, class Allocator>
618
constexpr void bit_vector<WordType, Allocator>::pop_back() {
278,880✔
619
    length_ -= 1;
278,880✔
620
    if (length_ % digits == 0) {
278,880✔
621
        word_vector.pop_back();
7,280✔
622
    }
3,640✔
623
    return;
278,880✔
624
}
139,440✔
625

626
template<class WordType, class Allocator>
627
constexpr void bit_vector<WordType, Allocator>::resize(size_type count) {
137,968✔
628
    word_vector.resize(word_count(count));
137,968✔
629
    length_ = count;
137,968✔
630
    return;
206,952✔
631
}
68,984✔
632

633
template<class WordType, class Allocator>
634
constexpr void bit_vector<WordType, Allocator>::resize(size_type count, const value_type& value) {
635
    auto old_length = length_;
636
    word_vector.resize(word_count(count));
637
    length_ = count;
638
    if (length_ > old_length) {
639
        fill(begin() + length_, end(), value);
640
    }
641
    return;
642
}
643
// -------------------------------------------------------------------------- //
644

645
template <class WordType, class Allocator>
646
template <bit_range R>
647
constexpr bit_vector<WordType, Allocator>::iterator bit_vector<WordType, Allocator>::insert_range(const_iterator pos, R&& range) {
648
  return this->insert(pos, range.begin(), range.end());
649
}
650

651
template <class WordType, class Allocator>
652
template <bit_range R>
653
constexpr void bit_vector<WordType, Allocator>::append_range(R&& range) {
4✔
654
  this->insert(this->end(), range.begin(), range.end());
4✔
655
}
4✔
656

657
/*
658
  * Slice
659
*/
660
template <class WordType, class Allocator>
661
constexpr bit_array_ref<> bit_vector<WordType, Allocator>::operator()(size_type begin, size_type end) const noexcept {
662
  return bit_array_ref<>(&this->at(begin), end - begin);
663
}
664

665
// ------------------------ BIT VECTOR: DEBUGGING -------------------------- //
666
template <class WordType, class Allocator>
667
constexpr std::string bit_vector<WordType, Allocator>::debug_string(const_iterator first, const_iterator end) {
668
  std::string ret = "";
669
  auto position = 0;
670
  for (const_iterator it = first; it != end; ++it) {
671
    if (position % digits == 0 && position != 0) {
672
      ret += " ";
673
    } else if (position % 8 == 0 && position != 0) {
674
      ret += '.';
675
    }
676
    ret += *it == bit1 ? '1' : '0';
677
    ++position;
678
  }
679
  return ret;
680
}
681

682
template<class WordType, class Allocator>
683
constexpr std::string bit_vector<WordType, Allocator>::debug_string() {
684
  return debug_string(begin(), end());
685
}
686
// -------------------------------------------------------------------------- //
687

688

689
// ========================================================================== //
690
} // namespace bit
691
#endif // _BIT_VECTOR_HPP_INCLUDED
692
// ========================================================================== //
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc