Questo è puro brutto. Per prima cosa dobbiamo guardare la dichiarazione di swap:
template<class T>
void swap(T &left, T &right);
Ora, operator[]()
su bitset
ha due overload:
bool operator[](size_type _Pos) const;
reference operator[](size_type _Pos);
Qui reference
è bitset::reference
, una classe annidata in bitset
che agisce in modo efficace come un proxy riferimento a uno dei bit sottostanti. Ciò che incapsula è il bitset
e una posizione nel bitset
. A causa della dichiarazione di swap
, il secondo overload viene scelto e stiamo scambiando due bitset::reference
s. Ora qui è dove diventa cattivo. Diamo un'occhiata a una tipica implementazione di swap:
template class<T> swap(T &left, T &right) {
T temp = left;
left = right;
right = temp;
}
Il problema è che left
e right
sono entrambi riferimenti a un bitset::reference
. Hanno gli stessi dati sottostanti (perché sono dei proxy, lo stesso significato che entrambi puntano allo stesso bitset
!) Incapsulano semplicemente diverse posizioni in quello bitset
.Quindi, pensa in questo modo left
è la posizione 0 in alcuni bitset
e right
è la posizione 1 in alcuni bitset
e che bitset
è lo stesso bitset
come left
! Facciamo sempre riferimento a questo bitset
come BS
(scelto intenzionalmente).
Quindi,
T temp = left;
dice che temp
è la posizione 0 in BS
.
left = right;
insiemi di posizione 0 in sinistra posizione 1 BS
(che cambia simultaneamente posizione 0 temp
!)
right = temp;
insiemi posizione 1 a destra per posizionare 0 a BS
(che è stato appena impostato posizione 1 in BS
!). Quindi alla fine di questo casino, la posizione 0 è quella che era la posizione 1 e la posizione 1 è invariata! Ora, poiché la posizione 0 è l'LSB e la posizione 1 è l'MSB, abbiamo che "10" diventa "11". Brutta.
È possibile aggirare il problema con un template specialization:
namespace std {
template<>
void swap<bitset<2>::reference>(
bitset<2>::reference &left,
bitset<2>::reference &right
) {
bool temp = (bool)left;
left = (bool)right;
right = (bool)temp;
}
}
Poi:
int main() {
bitset<2> test(string("10"));
cout << test; // Prints "10"
swap(test[0], test[1]);
cout << test; // Prints "01", hallelujah!
}
Bel lavoro! Incredibilmente nemmeno il C++ 0x menziona 'swap' affatto in relazione ai bitset. – Potatoswatter
Compilare questo in realtà? 'test [0]' è un temporaneo a cui non puoi fare riferimento per ... – Barry