简体   繁体   中英

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

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.

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

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 .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM