NoSenseEtAl
NoSenseEtAl

Reputation: 30006

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?

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

Upvotes: 7

Views: 1112

Answers (3)

Ted Lyngmo
Ted Lyngmo

Reputation: 117288

Using a 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

Upvotes: 4

ecatmur
ecatmur

Reputation: 157324

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.

Upvotes: 3

AndyG
AndyG

Reputation: 41092

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.

Upvotes: 6

Related Questions