To jest bardzo nieprzyjemne. Najpierw musimy spojrzeć na deklaracji wymiany:
template<class T>
void swap(T &left, T &right);
Teraz operator[]()
na bitset
ma dwa przeciążeń:
bool operator[](size_type _Pos) const;
reference operator[](size_type _Pos);
Tutaj reference
jest bitset::reference
, zagnieżdżone klasy w bitset
który skutecznie działa jako serwer proxy odniesienie do jednego z podstawowych bitów. To, co obejmuje, to bitset
i pozycja w bitset
. Z powodu deklaracji swap
, drugie przeciążenie jest wybierane, a my zamieniamy dwa bitset::reference
s. Teraz jest tutaj, gdzie robi się nieprzyjemnie. Spójrzmy na typowy realizacji swapu:
template class<T> swap(T &left, T &right) {
T temp = left;
left = right;
right = temp;
}
Problemem jest to, że left
i right
są zarówno odniesienia do bitset::reference
. Mają te same podstawowe dane (ponieważ są one serwerami proxy, to samo oznacza, że oba wskazują na to samo bitset
!) Po prostu zawierają różne pozycje w tym bitset
.Dlatego myśl o tym tak: left
to pozycja 0 w niektórych bitset
i right
jest pozycja 1 w niektórych bitset
i że bitset
jest taki sam bitset
jak left
! Odwróćmy się na zawsze do tego bitset
jako BS
(wybrane celowo).
Więc
T temp = left;
mówi, że temp
jest pozycja 0 w BS
.
left = right;
zestawy pozycji 0 w lewo do pozycji 1 w BS
(co jednocześnie zmienia pozycję 0 w temp
!)
right = temp;
zestawy pozycji 1 w prawo do pozycji 0 w BS
(który został właśnie ustawiony pozycja 1 w BS
!). Tak więc na końcu tego bałaganu ma się ta pozycja 0, niezależnie od pozycji 1, a pozycja 1 pozostaje niezmieniona! Teraz, ponieważ pozycja 0 to LSB, a pozycja 1 to MSB, to "10" staje się "11". Brzydki.
Można to obejść za pomocą 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;
}
}
Następnie:
int main() {
bitset<2> test(string("10"));
cout << test; // Prints "10"
swap(test[0], test[1]);
cout << test; // Prints "01", hallelujah!
}
Dobra robota! Niewiarygodne, że nawet C++ 0x w ogóle wspomina o 'swap' w stosunku do bitsetów. – Potatoswatter
Czy to faktycznie się kompiluje? 'test [0]' jest tymczasowy, którego nie można odwołać się do ... – Barry