I know that std::vector<bool>
is bad, but I have a really nice use case for it.
I would like to do something like this:
uint8_t data [] = {7,32};
std::vector<bool> vb/*...*/ ;
// now vb is size of 8 vector with this values:
// false, false, false, false, false, true, true, true, (7)
// false, false, true, false, false, false, false, false (32)
Note: I know I can manually disect every byte of input and make 8 inserts, but I am looking for something prebuilt in the standard
The vector<bool> class is a partial specialization of vector for elements of type bool . It has an allocator for the underlying type that's used by the specialization, which provides space optimization by storing one bool value per bit.
There is a general consensus among the C++ Standard Committee and the Library Working Group that vector<bool> should be deprecated and subsequently removed from the standard library, while the functionality will be reintroduced under a different name.
Following are different ways to create and initialize a vector in C++ STL. Initializing by one by one pushing values : // CPP program to create an empty vector. // and one by one push values. #include <bits/stdc++.h>. using namespace std; int main()
The manner in which std::vector<bool> is made space efficient (as well as whether it is optimized at all) is implementation defined. One potential optimization involves coalescing vector elements such that each element occupies a single bit instead of sizeof(bool) bytes.
A std::vector can be initialized in several ways while declaring it: A vector can be initialized from another container in several ways: Copy construction (from another vector only), which copies data from v2:
If the size of the bitset is known at compile time, std::bitset may be used, which offers a richer set of member functions. In addition, boost::dynamic_bitset exists as an alternative to std::vector<bool> . Since its representation may be optimized, std::vector<bool> does not necessarily meet all Container or SequenceContainer requirements.
std::vector<bool>
is a poor choice here, because you are thinking about it in terms of its implementation rather than its behavior.... just avoid vector<bool>
.
Use a boost::dynamic_bitset
instead. Anecdotally I have personally found it to be far more performant anyway:
std::array<std::uint8_t, 2> data {7,32};
boost::dynamic_bitset<std::uint8_t> vb(rbegin(data), rend(data));
std::cout << vb; // 0000011100100000
We have to reverse the input range because boost's dynamic bitset appends to the end where the most significant bit is (typically the left side), rather than the right side.
Using a boost container is most certainly the best way to go - but if that's not an option, you could create an iterator type to populate your vector<bool>
directly on construction.
Example:
struct biterator {
using value_type = bool;
using reference = bool;
using difference_type = std::ptrdiff_t;
using pointer = uint8_t*;
using iterator_category = std::forward_iterator_tag;
biterator(const uint8_t* c) : curr(c), bit(1U<<7) {}
biterator& operator++() { if(!(bit >>= 1)) { ++curr; bit = 1U<<7; } return *this; }
bool operator*() const { return *curr & bit; }
bool operator!=(const biterator& rhs) const { return curr != rhs.curr; }
private:
const uint8_t* curr;
uint8_t bit;
};
Usage:
uint8_t data [] = {7, 32};
std::vector<bool> vb(biterator(std::begin(data)), biterator(std::end(data)));
Demo
The proposal for this is P0237 Wording for fundamental bit manipulation utilities:
#include <bit>
#include <cstdint>
std::uint8_t data [] = {7,32};
std::vector<bool> vb(
std::bit_iterator(std::begin(data), 0)),
std::bit_iterator(std::end(data), 0)));
There is an implementation of P0237 (and N2050) called itsy.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With