Prawidłowa ręczna logiczna implementacja XOR zależy od tego, jak ściśle chcesz naśladować ogólne zachowanie innych operatorów logicznych ( ||
i &&
) z twoim XOR. Są dwie ważne rzeczy na temat tych operatorów: 1) gwarantują ocenę zwarcia, 2) wprowadzają punkt sekwencyjny, 3) oceniają operandy tylko raz.
Jak można zrozumieć, oceny XOR nie można zwierać, ponieważ wynik zawsze zależy od obu argumentów. Więc 1 nie wchodzi w rachubę. Ale co z 2? Jeśli nie przejmujesz się 2, to przy znormalizowanych (tj. bool
) Wartościach operator !=
wykonuje zadanie XOR pod względem wyniku. W razie potrzeby operandy można łatwo znormalizować za pomocą unary !
. W ten sposób !A != !B
implementuje prawidłowy XOR w tym zakresie.
Ale jeśli zależy ci na dodatkowym punkcie sekwencyjnym, ani !=
ani bitowe nie ^
jest właściwym sposobem na wdrożenie XOR. Jeden z możliwych sposobów prawidłowego wykonania XOR (a, b) może wyglądać następująco
a ? !b : b
Jest to tak blisko, jak to tylko możliwe, aby domowej roboty XOR były „podobne” do ||
i &&
. Działa to oczywiście tylko wtedy, gdy zaimplementujesz swój XOR jako makro. Funkcja nie zadziała, ponieważ sekwencjonowanie nie będzie miało zastosowania do argumentów funkcji.
Ktoś może jednak powiedzieć, że jedynym powodem mający temperaturę w każdej sekwencji &&
i ||
jest wspieranie oceny zwarcia, a tym samym XOR nie potrzebuje. To ma sens. Warto jednak wziąć pod uwagę XOR z punktem sekwencyjnym pośrodku. Na przykład następujące wyrażenie
++x > 1 && x < 5
ma zdefiniowane zachowanie i określony wynik w C / C ++ (przynajmniej w odniesieniu do sekwencjonowania). Można więc zasadnie oczekiwać tego samego od logicznego XOR zdefiniowanego przez użytkownika , jak w
XOR(++x > 1, x < 5)
podczas gdy !=
oparty na XOR nie ma tej właściwości.