In the following example i expected the swap of the bits. Instead the second bit becomes overwritten, but why and how could i achieve the expected behavior?
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
int main()
{
bitset<2> test(string("10"));
cout << test; // Prints "10"
swap(test[0], test[1]);
cout << test; // Prints "11", why not "01"?
}
This is pure nasty. First we have to look at the declaration of swap:
Now,
operator[]()onbitsethas two overloads:Here
referenceisbitset::reference, a nested class inbitsetthat effectively acts as a proxy reference to the one of the underlying bits. What it encapsulates is thebitsetand a position in thebitset. Because of the declaration ofswap, the second overload is chosen and we are swapping twobitset::references. Now here’s where it gets nasty. Let’s look at a typical implementation of swap:The problem is that
leftandrightare both references to abitset::reference. They have the same underlying data (because they are proxies; same meaning the both point to the samebitset!) they just encapsulate different positions in thatbitset. Thus, think of it like thisleftis position 0 in somebitsetandrightis position 1 in somebitsetand thatbitsetis the samebitsetasleft! Let’s forever refer to thisbitsetasBS(chosen intentionally).So,
says that
tempis position 0 inBS.sets position 0 in left to position 1 in
BS(which simultaneously changes position 0 intemp!)sets position 1 in right to position 0 in
BS(which was just set to position 1 inBS!). So at the end of this mess have that position 0 is whatever position 1 was and position 1 is unchanged! Now, because position 0 is the LSB and position 1 is the MSB we have that “10” becomes “11”. Ugly.You can get around this with a template specialization:
Then: