Rozdział 5...
Serwis znalezionych hasełOdnośniki
- Smutek to uczucie, jak gdyby się tonęło, jak gdyby grzebano cię w ziemi.
- Ogniem i mieczem - Tom I Rozdzial VI- Moci ksi - odpar Bychowiec - aska to wysoka waszej ksicej moci, e mogc rozkaza, na moj wol to zdajesz, ktrej aski nie...
- Przedstawiony w tym rozdziale projekt pomylany by jako opisowa analiza wywiadw przeprowadzanych przez kuratorw z podopiecznymi, oparta na badaniu aktw mowy...
- ROZDZIAŁ 38ODSIECZPomimo związanych na plecach nadgarstków, Perrin usiłował znaleźć wygodniejszą pozycję, aż wreszcie westchnął i poddał się...
- Jak wspomniano w poprzednim rozdziale, tworzenie aplikacji modularnej wymaga dodatkowych prac projektowych i podjęcia odpowiednich decyzji, ale w...
- ¨W każdym rozdziale poznajesz nowe sposoby lepszego rozumienia i pobudzania swoich manifestacyjnych sił...
- Rozdział 30 - Nigdy nie widziałeś czegoś takiego na własne oczy?Sam podskoczył z wrażenia...
- Rozdział 96Susan siedziała na sofie w Węźle nr 3, cała mokra i drżąca...
- Rozdział 7 Ażeby być sprawiedliwym, musze opowiedzieć także i o dobrych uczynkach Horemheba...
- Rozdział 11 ZAKOŃCZENIE Żyjemy w zadziwiającym świecie...
- Rozdzia 50Mary zmara o poranku...
Smutek to uczucie, jak gdyby się tonęło, jak gdyby grzebano cię w ziemi.
♦ Wszystko o szablonach
245
1.2=!
' * 4* A;*OA * 44
: 4
7
M4 %# /.!!/
& /
4 =
B =5-& / G /"
"
R4 9%# %4 %4+, /.
/
4 =.& /
B /."
"
<8D A;*A
4 P#
B "
"
4 Q4
B "
"
4 1
B "
"
=T& P# -.
=T& Q4 J.
=T& 1 -..
" E
Szablon główny Accumulate próbuje wyliczyć sumę F(n)+F(n – 1)...F(0). Warunek
końcowy uzyskujemy przez specjalizację częściową „zwracającą” F(0). Sam parametr F
jest szablonem i zachowuje się jak funkcja, jak w poprzednich przykładach przedstawio-
nych w tym punkcie. Szablony Identity, Square i Cube wyliczają odpowiednie funk-
cji dla swoich parametrów szablonów zgodnie ze swoimi nazwami (tożsamość, kwadrat
i sześcian). Pierwsze ukonkretnienie Accumulate w main() wylicza sumę 4 + 3 + 2 +
1 + 0, gdyż funkcja Identity po prostu „zwraca” swój parametr szablon. Drugi wiersz
funkcji main() powoduje dodanie kwadratów liczb (16 + 9 + 4 + 1 + 0), zaś ostatni
wylicza sumę sześcianów (64 + 27 + 8 + 1 + 0).
Zwijanie pętli
Projektanci algorytmów zawsze dążyli do optymalizacji swoich programów. Jedna
z uznanych metod optymalizacji, szczególnie przydatnych w programowaniu numerycz-
nym, to zwijanie pętli — technika minimalizująca narzut związany z pętlami. Kwinte-
sencją tej techniki jest mnożenie macierzy. Poniższa funkcja mnoży macierz i wektor
(załóżmy, że wcześniej zdefiniowano ROWS i COLS):
(
246
Część II ♦ Standardowa biblioteka C++
;4 * B . * 1Y6 GG*
#() GB ()(*)0(*)
"
"
Jeśli COLS jest liczbą parzystą, narzut związany z inkrementacją i porównywaniem
zmiennej kontrolnej pętli j można zredukować o połowę przez „zwinięcie” obliczeń
w pętli wewnętrznej w pary:
(
;4 * B . * 1Y6 * GB F
#() GB ()(*)0(*) G ()(*G-)0(*G-)
"
"
Ogólnie rzecz biorąc, jeśli COLS dzieli się przez k, w każdej iteracji pętli wewnętrznej
można wykonać k operacji, przez co znakomicie redukuje się narzut. Oszczędności będą
widoczne jedynie w przypadku dużych tablic, ale takie właśnie tablice występują w po-
ważnych obliczeniach matematycznych.
Także definiowanie funkcji jako funkcji inline stanowi pewną formę zwijania pętli.
Przyjrzyjmy się następującej metodzie obliczania potęg liczb całkowitych:
1.234!
M%* *%* O 4 ;*
: 4
7
%4
44 %45-
"
%4-
44
"
%4.
44 -
"
B T
%4J
" E
Kompilator musi wygenerować trzy specjalizacje power<>: jedną dla każdego z pa-
rametrów szablonu 3, 2 i 1. Kod każdej z tych funkcji może być zdefiniowany jako funkcja inline, kod faktycznie wstawiany do funkcji main() to wyrażenie m*m*m.
Wobec tego zwykła specjalizacja szablonu w połączeniu z funkcjami inline pozwala
całkowicie uniknąć narzutu związanego z kontrolą pętli.25
25Istnieje znacznie lepszy sposób obliczania potęg liczb całkowitych — algorytm rosyjskiego kmiecia (ang. Russian Peasant).
Rozdział 5. ♦ Wszystko o szablonach
247
Opisana metoda użycia zwijania pętli ograniczona jest przez możliwą głębokość defi-
niowania funkcji inline w konkretnym kompilatorze.
Instrukcje warunkowe na etapie kompilacji
Aby zasymulować instrukcje warunkowe na etapie kompilacji, można użyć w deklaracji
enum trójargumentowego operatora warunkowego. Poniższy program wykorzystuje
tę technikę do wyliczenia maksimum dwóch liczb całkowitych na etapie kompilacji:
1.2X0!
: 4
7
-& F
4 X0
B - F Z - F"
"
X0-.& F. F.
" E
Jeśli chcesz na etapie kompilacji użyć warunków do zdecydowania o sposobie gene-
rowania kodu, możesz wykorzystać specjalizację dla wartości true i false:
1.21 !
R4 %#4*N *
: 4
7
4 "
4
-
AR##% * 4* -\A
"
; - "
"
;
F
AR##% * 4* F\A
"
; F "
"
;
"
0 ; BB T
" E
248
Część II ♦ Standardowa biblioteka C++
Program ten jest równoważny:
;
-
F
za wyjątkiem tego, że wyrażenie cond jest wyznaczane podczas kompilacji, poza tym
to kompilator ukonkretnia odpowiednie wersje execute<>() i Select<>. Funkcja Select<>::f() jest wykonywana jako część programu. Instrukcję switch można symulować podobnie, ale zamiast true i false trzeba specjalizować wartości odpowia-
dające każdemu z możliwych przypadków.
Asercje na etapie kompilacji
W rozdziale 2. korzystaliśmy z asercji jako elementu programowania defensywnego.
Asercja to w zasadzie obliczenie wyrażenia logicznego i wykonanie stosownej akcji
— jeśli warunek jest prawdziwy, nierobienie niczego, natomiast jeśli warunek jest
fałszywy, przerwanie wykonywania programu i pokazanie stosownego komunikatu.
Jeśli możliwe jest wyznaczenie wartości wyrażenia już na etapie kompilacji, skorzy-
staj z asercji interpretowanej na tym etapie. Poniższy przykład pokazuje zastosowanie
techniki odwzorowującej wyrażenie logiczne na deklarację tablicy:
1.2 = 4-! 50"
L4 4O 4*N 4* *
:; =P1= `<0 \
#; (0 Z - 5-) " %.