Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I initialize a std::vector<bool> from uint8_t (or std::byte) range so that every bit in input is treated as a boolean?

Tags:

c++

stdvector

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

like image 276
NoSenseEtAl Avatar asked Oct 05 '20 15:10

NoSenseEtAl


People also ask

What is vector bool in c++?

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.

Is vector bool deprecated?

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.

How to create and initialize a vector in C++ STL?

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()

How is the std::vector< bool> space efficient?

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.

How do you initialize a vector?

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:

Is there an alternative to std::vector< bool>?

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.


3 Answers

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

Live Demo

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.

like image 65
AndyG Avatar answered Oct 18 '22 04:10

AndyG


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

like image 4
Ted Lyngmo Avatar answered Oct 18 '22 02:10

Ted Lyngmo


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.

like image 3
ecatmur Avatar answered Oct 18 '22 03:10

ecatmur