2011-02-05 6 views
7

Powiel możliwe:
Double Negation in C++ code.Jaki jest cel podwójnego negatywu w definicji makra, jak (!! (wyraż))?

Czytam kodu bazowego, a tu coś takiego:

#define uassert(msgid, msg, expr) (void)((!!(expr))||(uasserted(msgid, msg), 0)) 

Nie mogę zrozumieć, dlaczego (!! (wyra)) jest stosowany zamiast pojedynczego (wyra). W każdym razie podwójny negatyw oznacza pozytywny, prawda? Czy czegoś brakuje?

+0

Nie mogę nawet ustalić, jaki jest cel tego kodu! ;) – BlackBear

+0

Tak jak mówi R, jest to całkowicie bezużyteczne. – GManNickG

+0

jest zbędny w tym przypadku, jak sam prawidłowo wskazałeś. Może został właśnie dodany, aby uniknąć ostrzeżenia kompilatora. –

Odpowiedz

6

Jest to sposób na wyrażenie wyrażenia bool. W C++ jednak operator! może być przeciążony. Innym sposobem na C/C++:

C++ jedyny sposób:

static_cast<bool>(expr) 

[Edytuj] Myślenie więcej o C++ operatora przeciążenia, jest sens, aby uniknąć za pomocą operatorów. Biblioteki takie jak Boost.Spirit i Boost.Lambda używają szablonów wyrażeń i leniwej oceny, więc wyrażenia takie jak (expr) || call() mogą zachowywać się niezgodnie z oczekiwaniami. Najbardziej kuloodporne wersja tego makro wygląda następująco:

#define uassert(expr) if(expr) {} else { uasserted(...); } 

Tutaj tylko konwersja expr do Bool jest używany. Oddział else jest potrzebny do ochrony przed wyrażeniami takimi jak uassert(x) else something_else();.

+0

Zaakceptuj tę odpowiedź, ponieważ @Maxim podał oba wyjaśnienia i dalszą wiedzę. – fzhang

+1

A teraz 'uassert (expr)' nie jest już wyrażeniem; to jest oświadczenie. To znacznie ogranicza miejsce, w którym można z niego korzystać.Jeśli chcesz rzucić na 'bool', po prostu rzuć na' bool'. –

+0

Jest to wyrażenie assert, którego wartość jest typu bool w kompilacji debugowania i nieważne w wydaniu, jak zakładam. Czy możesz pokazać, jak bardzo ogranicza to użycie? –

1

Po prostu upewni się, że część makr expr zostanie przekonwertowana na wartość bool.

+0

Byłoby tak. – GManNickG

+0

@GMan, ogólnie tak, ale może nie. Możliwe, że nie ma żadnej niejawnej konwersji na 'bool', ale jest przeciążona negacja. –

+0

@Steven: Ktoś, kto pisze taką klasę, jest idiotą. Przepraszam, nie opieram swoich praktyk na tym, co ktoś głupi mógłby napisać. – GManNickG

1

Jest to idiom używany czasami w C++ do konwersji na typ boolowski.

0

W przykładzie, który nam pokazałeś, !! jest całkowicie bezużyteczny. Jednak generalnie jest on używany jako przybliżony do C99 przed rzutowaniem na _Bool, tj. 0 pozostaje 0, a każda inna wartość staje się 1.

+1

'!!' nie jest całkiem bezużyteczny. '(wyrażenie) || uasserted (...) 'może nie działać zgodnie z oczekiwaniami w C++, jeśli' || 'jest przeciążonym operatorem. Dlatego właśnie (wyrażenie) musi być jawnie rzutowane na wartość boolowską. –

+0

Dziękuję za przypomnienie mi, dlaczego nienawidzę języków z przeciążeniem operatora (lub przynajmniej takimi, w których operatorzy, którzy powinni mieć zdefiniowane definicje pod względem innych operatorów, mogą być przeciążeni). –

+1

@Maxim: Okropne argumenty. Uwaga: '!!' może nie działać zgodnie z oczekiwaniami w C++, jeśli '!' Jest przeciążonym operatorem. Twój argument jest samobójcze: tak, ktoś może być kretyński z operatorami, nie można wygodnie zignorować, mogą zrobić to samo na swoją pozycję. Nie ma sensu dla żadnego ortodoksyjnego programu, kogo obchodzi nieortodoksyjny pisarz? Oprzyj swoje praktyki na * dobrym * kodzie, dzięki czemu uzyskasz * dobre * praktyki programistyczne. – GManNickG