Jeśli widzieliśmy już w swoim wystarczająco dużą ilość kodu w C lub C++, to istnieje pewna szansa, że natrafiliśmy na konstrukcję znaną jaką do-while(false)
. Występuje ona w dwóch wersjach. W pierwszej jest to właściwie goto
w przebraniu – dzięki otoczeniu jakiegoś fragmentu kodu taką “pętlą” sprawiamy, że instrukcja break
będzie powodowała skok tuż za nią. To pozwala na “wyjście” z danego fragmentu kodu np. wtedy, gdy wystąpi w nim jakiś błąd – oczywiście przy założeniu, że w środku nie ma kolejnej pętli lub switch
a ;)
O drugiej wersji pisałem kilkanaście miesięcy temu. Jej zastosowaniem są makra preprocesora zawierająca kilka instrukcji; zamknięcie ich w do-while(false)
zamiast w zwykły blok kodu ({ }
) gwarantuje nam brak błędów składniowych niezależnie od miejsca użycia takiego makra.
Widać więc, że pętla z zawsze fałszywym warunkiem ma – mimo wszystko – jakieś zastosowanie… A co z analogicznym if
em? Czy if(false)
ma jakieś sensowne zastosowanie poza ukazywaniem, że osoba używająca takiej konstrukcji do wyłączania kodu z kompilacji zapomniała o istnieniu dyrektywy #if
, że o komentarzach nie wspomnę?…
Okazuje się, że jednak ma – przynajmniej mi dało się takowe zastosowanie znaleźć. Chcąc je zaprezentować, zacznę od takiego oto ciągu if
ów:
który w założeniu może być oczywiście dowolnie długi i niekoniecznie musi też udawać switcha
dla string
ów. Rzecz w tym, aby każdy if
miał podobną formę – na tyle podobną, że aż prosi się o jej zmakrowanie:
To by wyszło gdyby nie feler w postaci pierwszego if
a, który bynajmniej nie zaczyna się wcale od else
‘a. Można jednak sprawdzić, żeby tak było. Jak?… Ano właśnie dzięki zawsze fałszywemu if(false)
:
Robi on dokładnie nic, ale jednocześnie sprawia, że następujące dalej, prawdziwe if
y mają dokładnie taką samą strukturę. Teraz już możemy je skrócić:
Naturalnie dla trzech wariantów taka zabawa nie ma specjalnego sensu, ale dla dłuższej listy – czemu nie? Sam użyłem tej sztuczki parę razy, m.in. w parserze wyrażeń matematycznych, gdzie ciąg if
ów wybierał wywołanie jednej z ponad 20 wbudowanych w niego funkcji. Nie jest to ładne – trzeba to przyznać – ale cóż, takie jest życie: czasami rozwiązania eleganckiego po prostu nie ma…
#define C(val,arg) else if (s==#arg) {code;}
a gdzie tu jest ‘code’?
Ups! Pomiąchały mi się coś te argumenty makr. Ale już poprawiłem :) Dzięki.
Ciekawe. Nie sadzilem ze taka instrukcje mozna jakos wykorzystac :)
Jedno o czym warto wspomniec to zeby koniecznie pisac takie makro zaraz nad kawalkiem kodu ktory z niego korzysta – tak jak zrobiles tutaj.
Pisanie tego w osobnym miejscu mogloby zaskutkowac co najmniej nie zrozumieniem kodu przez czytajacego ;)