10

I have a std::bitset but now I want to use an STL algorithm on it.

I could have used std::vector<bool> instead, but I like std::bitset's constructor and I want std::bitset's bitwise operations.

Do I have to go through a loop and stuff everything in a std::vector<bool> to use STL algorithms, and then copy that back to the std::bitset, or is there a better way?

Jonathan Mee
  • 37,899
  • 23
  • 129
  • 288
  • 2
    What algorithm do you want to use on the bits of the bitset? – wilx Jan 07 '15 at 18:46
  • @VáclavZeman Well initially I wanted to use `std::reverse`, but then when I found out `std::bitset` wouldn't let me use STL algorithms on it, I just wanted to find a way to use them in general. – Jonathan Mee Jan 07 '15 at 18:52
  • 1
    You could write appropriate iterators and pair of freestanding `begin()` and `end()` functions. – milleniumbug Jan 07 '15 at 18:52
  • 4
    You might not use an std::algorithm on a bitset, see http://graphics.stanford.edu/~seander/bithacks.html#BitReverseObvious –  Jan 07 '15 at 19:00

2 Answers2

2

If you do not want to write loops using the operator[] of the bitset, then you might try using bitset::to_string() to convert the bitset to a string of '1' and '0'. Since C++11, you can actually choose different characters than those two, so you could actually choose '\0' and '\1'.

Are you sure bitset is the optimal type for your task?

wilx
  • 17,697
  • 6
  • 59
  • 114
  • Seems like a loop would be better than that solution... I'm not totally opposed to a loop it just seems like there should be something cleaner. As far as using `std::bitset`... I think so? The flexibility to convert back and forth between a number and an array is hard to beat. – Jonathan Mee Jan 07 '15 at 19:27
1

Matthew Austern wrote an iterator for bitset here: http://www.drdobbs.com/the-standard-librarian-bitsets-and-bit-v/184401382?pgno=2

It's over 100 lines so I feel just lifting it and putting it in this answer may be a bit out of bounds. But it works marvelously for STL algorithms.

Austern answers this exact question:

While bitset doesn’t have the STL container interface, it’s still a perfectly good (fixed-size) container. If it makes sense for you to use a bitset, and if you also need iterators, then you can define a simple “index iterator” adaptor that translates iterator notation like *i into array notation like b[n]. The implementation is straightforward: maintain an index and a pointer to a container.

He does warn of his iterator:

If we were willing to accept a slightly more cumbersome interface, we could define a class that worked with arbitrary array-like types. A general purpose index iterator adaptor is often useful when dealing with pre-STL container classes, and sometimes even when dealing with STL containers like vector.

It should also be noted that just as with a vector<bool>::iterator, Austern's bitset_iterator::operator* doesn't return a bool& but a proxy reference: bitset<>::reference.

Usage of bitset_iterator looks like this:

std::bitset<10> foo;
std::vector<bool> bar(begin(foo), end(foo));
Jonathan Mee
  • 37,899
  • 23
  • 129
  • 288
  • bitset doesn't seem to have iterators begin() and end(), so the above would not work. – Naveen Apr 19 '22 at 16:25
  • 1
    The point is to have a specialisation of begin() that returns a bitset_iterator which is exactly what the linked implementation contains. – Bruce Adams May 05 '23 at 19:10