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

PeterCDMcLean / BitLib / 14987214130

13 May 2025 03:02AM UTC coverage: 49.385% (-46.9%) from 96.333%
14987214130

Pull #7

github

web-flow
Merge aad228108 into 09dd4e61e
Pull Request #7: Add github workflow targets for warnings

5155 of 10638 branches covered (48.46%)

Branch coverage included in aggregate %.

39 of 70 new or added lines in 1 file covered. (55.71%)

128 existing lines in 10 files now uncovered.

5325 of 10583 relevant lines covered (50.32%)

3238286.52 hits per line

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

90.71
/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) {
60,537✔
48
    return ((num_bits + digits - 1) / digits);
60,537✔
49
  }
60,537✔
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>;
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;
60,240✔
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;
1,020✔
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) {}
289✔
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)
222
    : word_vector(word_count(count), static_cast<WordType>(bit_val == bit1 ? -1 : 0), alloc),
960✔
223
      length_(count)
960✔
224
      {}
960✔
225

226
template<class WordType, class Allocator>
227
constexpr bit_vector<WordType, Allocator>::bit_vector(size_type count, const Allocator& alloc)
228
    : word_vector(word_count(count), alloc), length_(count) {}
30,117✔
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)
235
    : word_vector(distance(first, last), alloc), length_(distance(first, last)) {
1✔
236
  copy(first, last, this->begin());
1✔
237
}
1✔
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)
242
    : bit_vector(rg.begin(), rg.end(), alloc) {
1✔
243
}
1✔
244

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

258
template<class WordType, class Allocator>
259
constexpr bit_vector<WordType, Allocator>::bit_vector(const bit_vector<WordType, Allocator>&& other) noexcept
260
    : word_vector(std::move(other.word_vector)), length_(other.length_) {}
55,000✔
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)
276
    : word_vector(alloc), length_(0) {
4✔
277
    for (const bool& b : init) {
48✔
278
        this->push_back(static_cast<bit_value>(b));
48✔
279
    }
48✔
280
}
4✔
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) {
624✔
291
    this->length_ = std::count(s.begin(), s.end(), '0') + std::count(s.begin(), s.end(), '1');
624✔
292
    this->word_vector = std::vector<WordType, Allocator>(this->length_);
624✔
293
    size_type i = 0;
624✔
294
    for (char c : s) {
44,576✔
295
        if (c == '0') {
44,576✔
296
            begin()[i++] = bit0;
41,552✔
297
        } else if (c == '1') {
41,552!
298
            begin()[i++] = bit1;
3,024✔
299
        }
3,024✔
300
    }
44,576✔
301
}
624✔
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(
314
        RandomAccessIt first,
315
        RandomAccessIt last,
316
        const Allocator& alloc) {
508✔
317
    word_vector = std::vector<WordType, Allocator>(std::distance(first, last), alloc);
508✔
318
    length_ = std::distance(first, last);
508✔
319
    std::transform(
508✔
320
            first,
508✔
321
            last,
508✔
322
            begin(),
508✔
323
            [](bool b) {return static_cast<bit_value>(b);}
1,353,984✔
324
    );
508✔
325
}
508✔
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(
337
        RandomAccessIt first,
338
        RandomAccessIt last,
339
        const Allocator& alloc) {
480✔
340
    word_vector = std::vector<WordType, Allocator>(first, last, alloc);
480✔
341
    length_ = digits * std::distance(first, last);
480✔
342
}
480✔
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() {
148,223✔
349
#endif
148,223✔
350
    length_ = 0;
148,223✔
351
}
148,223✔
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 {
3,056✔
360
    length_ = other.length_;
3,056✔
361
    word_vector = std::move(other.word_vector);
3,056✔
362
    other.length_ = 0;
3,056✔
363
    return *this;
3,056✔
364
}
3,056✔
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];}
4,107,300✔
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) {
1,444,900✔
381
    if (pos < length_) {
1,444,900✔
382
        return begin()[pos];
1,353,992✔
383
    } else {
1,353,992✔
384
        throw std::out_of_range("Position is out of range");
90,908✔
385
    }
90,908✔
386
}
1,444,900✔
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 {
6,377,593✔
441
    return iterator(word_vector.begin());
6,377,593✔
442
}
6,377,593✔
443

444
template<class WordType, class Allocator>
445
constexpr typename bit_vector<WordType, Allocator>::iterator
446
bit_vector<WordType, Allocator>::end() noexcept {
286,176✔
447
    return begin() + length_;
286,176✔
448
}
286,176✔
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 {
24,962✔
465
    return const_iterator(word_vector.begin());
24,962✔
466
}
24,962✔
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 {
12✔
480
    return length_ == 0;
12✔
481
}
12✔
482

483
template<class WordType, class Allocator>
484
constexpr typename bit_vector<WordType, Allocator>::size_type
485
bit_vector<WordType, Allocator>::size() const noexcept {
61,179✔
486
    return length_;
61,179✔
487
}
61,179✔
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) {
20✔
497
    word_vector.reserve(word_count(new_cap));
20✔
498
}
20✔
499

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

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

512

513

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

520
template<class WordType, class Allocator>
521
constexpr typename bit_vector<WordType, Allocator>::iterator
522
bit_vector<WordType, Allocator>::insert(
523
        const_iterator pos,
524
        const value_type& value) {
24,576✔
525
    const auto d = distance(cbegin(), pos);
24,576✔
526
    if (this->word_vector.size()*digits == length_) {
24,576✔
527
        word_vector.push_back(0U);
858✔
528
    }
858✔
529
    length_ += 1;
24,576✔
530
    shift_right(begin() + d, begin() + length_, 1);
24,576✔
531
    begin()[d] = value;
24,576✔
532
    return begin() + d;
24,576✔
533
}
24,576✔
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(
539
        const_iterator pos,
540
        size_type count,
541
        const bit_vector<WordType, Allocator>::value_type& value) {
192✔
542
    const auto d = distance(cbegin(), pos);
192✔
543
    if (count == 0) {
192!
544
        return begin() + d;
×
UNCOV
545
    }
×
546
    const float bits_available = word_vector.size() * digits;
192✔
547
    const bool need_to_add = length_ + count > bits_available;
192✔
548
    if (need_to_add) {
192!
549
        const auto words_to_add = word_count(length_ + count - bits_available);
189✔
550
        word_vector.resize(word_vector.size() + words_to_add);
189✔
551
    }
189✔
552
    length_ += count;
192✔
553
    shift_right(begin() + d, begin() + length_, count);
192✔
554
    fill(begin() + d, begin() + d + count, value);
192✔
555
    return begin() + d;
192✔
556
}
192✔
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(
562
    const_iterator pos,
563
    OtherIt first,
564
    OtherIt last) {
194✔
565
  const auto d = distance(cbegin(), pos);
194✔
566
  const size_t count = distance(first, last);
194✔
567
  if (count == 0) {
194!
568
    return begin() + d;
×
UNCOV
569
  }
×
570
  const float bits_available = word_vector.size() * digits;
194✔
571
  const auto need_to_add = length_ + count > bits_available;
194✔
572
  if (need_to_add) {
194!
573
    const auto words_to_add = word_count(length_ + count - bits_available);
181✔
574
    word_vector.resize(word_vector.size() + words_to_add);
181✔
575
  }
181✔
576
  length_ += count;
194✔
577
  shift_right(begin() + d, begin() + length_, count);
194✔
578
  copy(first, last, begin() + d);
194✔
579
  return begin() + d;
194✔
580
}
194✔
581

582
template<class WordType, class Allocator>
583
constexpr typename bit_vector<WordType, Allocator>::iterator
584
bit_vector<WordType, Allocator>::erase(iterator pos) {
192✔
585
    shift_left(pos, begin() + length_, 1);
192✔
586
    length_ -= 1;
192✔
587
    if (length_ % digits == 0) {
192!
588
        word_vector.pop_back();
9✔
589
    }
9✔
590
    return pos;
192✔
591
}
192✔
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) {
150✔
596
    const auto d = distance(begin(), first);
150✔
597
    auto count = distance(first, last);
150✔
598
    if (count == 0) {
150!
599
        return last;
36✔
600
    }
36✔
601
    shift_left(first, end(), count);
114✔
602
    length_ -= count;
114✔
603
    word_vector.resize(word_count(length_));
114✔
604
    return begin() + d;
114✔
605
}
150✔
606

607
template<class WordType, class Allocator>
608
constexpr void bit_vector<WordType, Allocator>::push_back(const value_type& value) {
90,449✔
609
    if (this->word_vector.size()*digits == length_) {
90,449✔
610
        word_vector.push_back(0U);
2,038✔
611
    }
2,038✔
612
    begin()[length_] = value;
90,449✔
613
    length_ += 1;
90,449✔
614
    return;
90,449✔
615
}
90,449✔
616

617
template<class WordType, class Allocator>
618
constexpr void bit_vector<WordType, Allocator>::pop_back() {
69,720✔
619
    length_ -= 1;
69,720✔
620
    if (length_ % digits == 0) {
69,720✔
621
        word_vector.pop_back();
1,820✔
622
    }
1,820✔
623
    return;
69,720✔
624
}
69,720✔
625

626
template<class WordType, class Allocator>
627
constexpr void bit_vector<WordType, Allocator>::resize(size_type count) {
28,956✔
628
    word_vector.resize(word_count(count));
28,956✔
629
    length_ = count;
28,956✔
630
    return;
28,956✔
631
}
28,956✔
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) {
2✔
654
  this->insert(this->end(), range.begin(), range.end());
2✔
655
}
2✔
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