C Szablony Vademecum profesjonalisty 2

background image

Wydawnictwo Helion
ul. Chopina 6
44-100 Gliwice
tel. (32)230-98-63

e-mail: helion@helion.pl

PRZYK£ADOWY ROZDZIA£

PRZYK£ADOWY ROZDZIA£

IDZ DO

IDZ DO

ZAMÓW DRUKOWANY KATALOG

ZAMÓW DRUKOWANY KATALOG

KATALOG KSI¥¯EK

KATALOG KSI¥¯EK

TWÓJ KOSZYK

TWÓJ KOSZYK

CENNIK I INFORMACJE

CENNIK I INFORMACJE

ZAMÓW INFORMACJE

O NOWOCIACH

ZAMÓW INFORMACJE

O NOWOCIACH

ZAMÓW CENNIK

ZAMÓW CENNIK

CZYTELNIA

CZYTELNIA

FRAGMENTY KSI¥¯EK ONLINE

FRAGMENTY KSI¥¯EK ONLINE

SPIS TRECI

SPIS TRECI

DODAJ DO KOSZYKA

DODAJ DO KOSZYKA

KATALOG ONLINE

KATALOG ONLINE

C++. Szablony.
Vademecum
profesjonalisty

Autorzy: David Vandevoorde, Nicolai M. Josuttis
T³umaczenie: Przemys³aw Szeremiota
ISBN: 83-7361-175-4
Tytu³ orygina³u:

C++ Templates The Complete Guide

Format: B5, stron: 474

Choæ szablony s¹ czêci¹ definicji jêzyka C++ od ponad dziesiêciu lat, wci¹¿ s¹ ród³em
nieporozumieñ, omy³ek i kontrowersji. Z drugiej strony, ich popularnoæ jako
efektywnych instrumentów tworzenia bardziej eleganckiego, szybszego
i „inteligentniejszego” oprogramowania stale ronie. W rzeczy samej, szablony
osi¹gnê³y rangê kamieni wêgielnych dla kilku nowych modeli programowania
w jêzyku C++.

Ksi¹¿ka "C++. Szablony. Vademecum profesjonalisty." zawiera komplet informacji
niezbêdnych do rozpoczêcia korzystania z szablonów i pe³nego wykorzystania ich
mo¿liwoci, jak równie¿ wiedzy pomagaj¹cej dowiadczonym programistom
przekroczyæ granicê, za któr¹ programowanie z rzemios³a staje siê sztuk¹. Autorzy
za³o¿yli, ¿e znasz jêzyk C++ i potrafisz programowaæ z wykorzystaniem komponentów
biblioteki standardowej. Prezentowane w ksi¹¿ce przyk³ady znakomicie ilustruj¹
abstrakcyjne pojêcia i demonstruj¹ najlepsze praktyki programistyczne.

Poznasz:

• sposoby unikania pu³apek towarzysz¹cych stosowaniu szablonów,
• idiomy i techniki zwi¹zane z szablonami -- od technik najprostszych do takich,
które poza t¹ ksi¹¿k¹ nie zosta³y jeszcze nigdzie dokumentowane,
• sposoby wielokrotnego wykorzystywania tego samego kodu ród³owego
bez zmniejszania jego wydajnoci i bezpieczeñstwa,
• sposoby zwiêkszania efektywnoci programów w jêzyku C++,
• sposoby tworzenia oprogramowania bardziej elastycznego i ³atwiejszego
w utrzymaniu.

Niektóre z technik przestawionych w „C++. Szablony. Vademecum profesjonalisty”
nie doczeka³y siê jeszcze opracowania w innych publikacjach. Jeli w programowaniu
w C++ chcesz osi¹gn¹æ najwy¿szy poziom, nie obêdziesz siê bez tej ksi¹¿ki.

background image

5RKUVTGħEK

Rozdział 1.

1.1. Co należy wiedzieć przed przystąpieniem do lektury? ............................................. 16
1.2. Struktura ogólna książki ....................................................................................... 16
1.3. Jak czytać tę książkę?........................................................................................... 17
1.4. Uwagi do stosowanego w tekście stylu programowania ........................................... 17
1.5. Standard a rzeczywistość ...................................................................................... 19
1.6. Pliki przykładów i dodatkowe informacje............................................................... 20

Rozdział 2.

2.1. Szablony funkcji — wstęp .................................................................................... 23

2.1.1. Definiowanie szablonu ................................................................................. 23
2.1.2. Korzystanie z szablonu ................................................................................ 24

2.2. Dedukcja typu argumentów .................................................................................. 26
2.3. Parametry szablonu.............................................................................................. 27
2.4. Przeciążanie szablonów funkcji ............................................................................. 29
2.5. Podsumowanie .................................................................................................... 33

Rozdział 3.

3.1. Implementacja szablonu klasy Stack ...................................................................... 35

3.1.1. Deklarowanie szablonów klas ....................................................................... 36
3.1.2. Implementacja metod klasy .......................................................................... 37

3.2. Korzystanie z szablonu klasy Stack ....................................................................... 38
3.3. Specjalizacje szablonów klas................................................................................. 40
3.4. Specjalizacja częściowa........................................................................................ 42
3.5. Domyślne argumenty szablonu.............................................................................. 43
3.6. Podsumowanie .................................................................................................... 45

Rozdział 4.

! "#

4.1. Pozatypowe parametry szablonów klas .................................................................. 47
4.2. Pozatypowe parametry szablonów funkcji .............................................................. 50
4.3. Ograniczenia dla pozatypowych parametrów szablonów.......................................... 51
4.4. Podsumowanie .................................................................................................... 52

Rozdział 5.

$

5.1. Słowo kluczowe typename ................................................................................... 53
5.2. Zastosowanie odwołania this–

>............................................................................. 55

5.3. Szablony składowych ........................................................................................... 55

background image

6

C++. Szablony. Vademecum profesjonalisty

5.4. Szablony parametrów szablonów........................................................................... 59
5.5. Inicjalizacja zerowa.............................................................................................. 63
5.6. Literały łańcuchowe jako argumenty szablonów funkcji .......................................... 64
5.7. Podsumowanie .................................................................................................... 67

Rozdział 6.

! %&

6.1. Model włączania.................................................................................................. 69

6.1.1. Komunikaty o błędach konsolidacji ............................................................... 69
6.1.2. Szablony w plikach nagłówkowych ............................................................... 71

6.2. Konkretyzacja jawna............................................................................................ 72

6.2.1. Przykład konkretyzacji jawnej ...................................................................... 73
6.2.2. Połączenie modelu włączania i konkretyzacji jawnej....................................... 74

6.3. Model separacji ................................................................................................... 75

6.3.1. Słowo kluczowe export ................................................................................ 75
6.3.2. Ograniczenia modelu separacji...................................................................... 77
6.3.3. Przygotowanie do wykorzystania modelu separacji......................................... 78

6.4. Szablony a słowo kluczowe inline ......................................................................... 79
6.5. Wstępna kompilacja plików nagłówkowych ........................................................... 79
6.6. Diagnostyka szablonów ........................................................................................ 82

6.6.1. Dekodowanie elaboratu o błędzie .................................................................. 82
6.6.2. Konkretyzacja płytka ................................................................................... 84
6.6.3. Zbyt długie symbole .................................................................................... 86
6.6.4. Tropiciele ................................................................................................... 86
6.6.5. Wyrocznie .................................................................................................. 90
6.6.6. Archetypy................................................................................................... 91

6.7. Uwagi końcowe ................................................................................................... 91
6.8. Podsumowanie .................................................................................................... 92

Rozdział 7.

' &

7.1. „Szablon klasy” czy „klasa szablonowa”? .............................................................. 93
7.2. Konkretyzacja i specjalizacja ................................................................................ 94
7.3. Deklaracje i definicje............................................................................................ 94
7.4. Reguła pojedynczej definicji ................................................................................. 95
7.5. Parametry czy argumenty szablonów?.................................................................... 96

Rozdział 8.

() *

8.1. Deklaracje sparametryzowane............................................................................. 101

8.1.1. Wirtualne funkcje składowe........................................................................ 104
8.1.2. Łączenie szablonów................................................................................... 104
8.1.3. Szablony podstawowe................................................................................ 105

8.2. Parametry szablonów ......................................................................................... 105

8.2.1. Parametry typów ....................................................................................... 106
8.2.2. Parametry pozatypowe............................................................................... 106
8.2.3. Szablony parametrów szablonów ................................................................ 107
8.2.4. Domyślne argumenty szablonów................................................................. 108

8.3. Argumenty szablonu .......................................................................................... 109

8.3.1. Argumenty szablonów funkcji .................................................................... 110
8.3.2. Argumenty typów...................................................................................... 112
8.3.3. Argumenty pozatypowe ............................................................................. 113
8.3.4. Argumenty szablonów parametrów szablonów ............................................. 115
8.3.5. Równoważność argumentów ...................................................................... 117

background image

Spis treści

7

8.4. Deklaracje zaprzyjaźnione .................................................................................. 117

8.4.1. Funkcje zaprzyjaźnione.............................................................................. 118
8.4.2. Szablony jednostek zaprzyjaźnionych.......................................................... 120

8.5. Uwagi końcowe ................................................................................................. 121

Rozdział 9.

+,

9.1. Taksonomia nazw .............................................................................................. 123
9.2. Wyszukiwanie nazw........................................................................................... 125

9.2.1. Wyszukiwanie według argumentów ............................................................ 126
9.2.2. Wtrącanie nazw zaprzyjaźnionych .............................................................. 128
9.2.3. Wtrącane nazwy klas ................................................................................. 129

9.3. Analiza składniowa szablonów............................................................................ 130

9.3.1. Wrażliwość kontekstowa poza szablonami ................................................... 130
9.3.2. Zależne nazwy typów ................................................................................ 133
9.3.3. Zależne nazwy szablonów .......................................................................... 134
9.3.4. Nazwy zależne w deklaracjach używanych przestrzeni nazw i klas................. 136
9.3.5. ADL a jawne argumenty szablonu............................................................... 137

9.4. Szablony klas wyprowadzonych.......................................................................... 137

9.4.1. Klasy bazowe niezależne............................................................................ 138
9.4.2. Klasy bazowe zależne ................................................................................ 138

9.5. Uwagi końcowe ................................................................................................. 141

Rozdział 10. $ "

10.1. Konkretyzacja na żądanie ................................................................................. 143
10.2. Konkretyzacja opóźniona.................................................................................. 145
10.3. Model konkretyzacji z języku C++ .................................................................... 147

10.3.1. Wyszukiwanie dwufazowe ....................................................................... 148
10.3.2. Punkty konkretyzacji................................................................................ 148
10.3.3. Modele włączania i separacji..................................................................... 151
10.3.4. Wyszukiwanie pomiędzy jednostkami translacji ......................................... 152
10.3.5. Przykłady................................................................................................ 153

10.4. Schematy implementacji ................................................................................... 154

10.4.1. Konkretyzacja zachłanna .......................................................................... 156
10.4.2. Konkretyzacja z bazą danych.................................................................... 157
10.4.3. Konkretyzacja iterowana .......................................................................... 159

10.5. Konkretyzacja jawna........................................................................................ 161
10.6. Uwagi końcowe ............................................................................................... 165

Rozdział 11. -)! %#

11.1. Proces dedukcji................................................................................................ 167
11.2. Konteksty dedukowane .................................................................................... 169
11.3. Sytuacje wyjątkowe procesu dedukcji ................................................................ 171
11.4. Dopuszczalne konwersje argumentów................................................................ 172
11.5. Parametry szablonów klas................................................................................. 173
11.6. Domyślne argumenty wywołania ....................................................................... 173
11.7. Technika Bartona-Nackmana ............................................................................ 174
11.8. Uwagi końcowe ............................................................................................... 176

Rozdział 12. ##

12.1. Kiedy kod uogólniony nie jest odpowiedni?........................................................ 177

12.1.1. Przezroczystość dopasowania ................................................................... 178
12.1.2. Przezroczystość semantyczna ................................................................... 179

12.2. Przeciążanie szablonów funkcji ......................................................................... 180

12.2.1. Sygnatury ............................................................................................... 181
12.2.2. Porządkowanie częściowe przeciążonych szablonów funkcji ....................... 183

background image

8

C++. Szablony. Vademecum profesjonalisty

12.2.3. Formalne reguły porządkowania................................................................ 184
12.2.4. Szablony funkcji a funkcje zwykłe ............................................................ 186

12.3. Specjalizacja jawna .......................................................................................... 187

12.3.1. Pełna specjalizacja szablonu klasy ............................................................. 187
12.3.2. Pełna specjalizacja szablonu funkcji .......................................................... 191
12.3.3. Pełna specjalizacja składowej.................................................................... 193

12.4. Częściowa specjalizacja szablonu klasy.............................................................. 195
12.5. Uwagi końcowe ............................................................................................... 198

Rozdział 13. $ *

13.1. Problem nawiasów ostrych ............................................................................... 201
13.2. Luźne reguły deklaracji typename...................................................................... 202
13.3. Domyślne argumenty szablonów funkcji ............................................................ 203
13.4. Literały łańcuchowe i zmiennoprzecinkowe jako argumenty szablonów ................ 204
13.5. Luźne dopasowanie szablonów parametrów szablonów ....................................... 206
13.6. Szablony definicji typu ..................................................................................... 207
13.7. Specjalizacja częściowa szablonów funkcji......................................................... 209
13.8. Operator typeof ............................................................................................... 210
13.9. Nazwane argumenty szablonu ........................................................................... 212
13.10. Właściwości statyczne typów .......................................................................... 213
13.11. Własna diagnostyka konkretyzacji ................................................................... 213
13.12. Przeciążone szablony klas ............................................................................... 216
13.13. Parametry wielokrotne .................................................................................... 216
13.14. Kontrola rozmieszczenia w pamięci ................................................................. 218
13.15. Dedukcja typu na podstawie inicjalizatora ........................................................ 219
13.16. Wyrażenia funkcyjne...................................................................................... 220
13.17. Uwagi końcowe ............................................................................................. 222

Rozdział 14. . !

14.1. Polimorfizm dynamiczny .................................................................................. 225
14.2. Polimorfizm statyczny...................................................................................... 228
14.3. Polimorfizm statyczny kontra dynamiczny ......................................................... 230
14.4. Nowe formy wzorców projektowych ................................................................. 232
14.5. Programowanie ogólne ..................................................................................... 233
14.6. Uwagi końcowe ............................................................................................... 235

Rozdział 15. $,, #

15.1. Przykład — kumulowanie ciągu elementów........................................................ 237

15.1.1. Cechy ustalone ........................................................................................ 238
15.1.2. Cechy wartości ........................................................................................ 241
15.1.3. Parametryzacja cech ................................................................................ 244
15.1.4. Wytyczne i klasy wytycznych ................................................................... 246
15.1.5. Czym różnią się cechy i wytyczne? ........................................................... 248
15.1.6. Szablony składowe a szablony parametrów szablonów................................ 249
15.1.7. Łączenie wielu cech i wytycznych............................................................. 251
15.1.8. Kumulowanie za pomocą iteratorów ogólnych............................................ 251

15.2. Funkcje typów................................................................................................. 252

15.2.1. Określanie typu elementu ......................................................................... 253
15.2.2. Określanie typu definiowanego przez użytkownika ..................................... 255
15.2.3. Referencje i kwalifikatory......................................................................... 257
15.2.4. Cechy promocji ....................................................................................... 259

background image

Spis treści

9

15.3. Cechy wytycznych........................................................................................... 262

15.3.1. Parametry typów tylko do odczytu ............................................................ 263
15.3.2. Kopiowanie, wymiana i przenoszenie ........................................................ 266

15.4. Uwagi końcowe ............................................................................................... 270

Rozdział 16. #

16.1. Nazwane argumenty szablonów......................................................................... 271
16.2. Optymalizacja pustej klasy bazowej................................................................... 274

16.2.1. Zasady rozmieszczania klas w pamięci ...................................................... 275
16.2.2. Klasy bazowe w postaci składowych ......................................................... 277

16.3. Wzorzec CRTP................................................................................................ 279
16.4. Parametryzacja wirtualności metod.................................................................... 281
16.5. Uwagi końcowe ............................................................................................... 282

Rozdział 17. / ) 0

17.1. Metaprogram — pierwsza odsłona..................................................................... 285
17.2. Wartości wyliczeniowe a stałe statyczne ............................................................ 287
17.3. Przykład drugi — obliczanie pierwiastka kwadratowego...................................... 288
17.4. Zmienne indukowane ....................................................................................... 292
17.5. Zupełność obliczeniowa.................................................................................... 295
17.6. Konkretyzacja rekurencyjna a rekurencyjne argumenty szablonów ....................... 296
17.7. Metaprogramowanie w rozwijaniu pętli.............................................................. 297
17.8. Uwagi końcowe ............................................................................................... 300

Rozdział 18. 1 *

18.1. Obiekty tymczasowe i rozdzielanie pętli............................................................. 304
18.2. Kodowanie wyrażeń obliczeniowych za pomocą argumentów szablonów.............. 308

18.2.1. Operandy szablonów wyrażeń................................................................... 309
18.2.2. Typ Array ............................................................................................... 312
18.2.3. Operatory ............................................................................................... 314
18.2.4. Podsumowanie ........................................................................................ 315
18.2.5. Przypisania szablonów wyrażeń ................................................................ 317

18.3. Wydajność szablonów wyrażeń i ich ograniczenia............................................... 318
18.4. Uwagi końcowe ............................................................................................... 319

!"

Rozdział 19. $ !

19.1. Identyfikowanie typów podstawowych............................................................... 325
19.2. Identyfikowanie typów złożonych...................................................................... 327
19.3. Identyfikowanie typów funkcyjnych .................................................................. 329
19.4. Klasyfikacja typów wyliczeniowych przez rozstrzyganie przeciążenia .................. 333
19.5. Identyfikowanie typów definiowanych przez użytkownika................................... 335
19.6. Jak to wszystko połączyć? ................................................................................ 336
19.7. Uwagi końcowe ............................................................................................... 338

Rozdział 20. 2)3 "

20.1. Posiadacze i kuriery ......................................................................................... 341

20.1.1. Ochrona przed wyjątkami......................................................................... 342
20.1.2. Klasa posiadacza ..................................................................................... 343
20.1.3. Posiadacze jako składowe......................................................................... 346
20.1.4. Pozyskiwanie zasobów w inicjalizacji........................................................ 347
20.1.5. Ograniczenia klasy posiadacza .................................................................. 348

background image

10C++. Szablony. Vademecum profesjonalisty

20.1.6. Kopiowanie posiadaczy ............................................................................ 349
20.1.7. Kopiowanie obiektów posiadaczy pomiędzy wywołaniami funkcji ............... 350
20.1.8. Obiekty kurierów..................................................................................... 351

20.2. Zliczanie liczby odwołań .................................................................................. 353

20.2.1. Gdzie umieścić licznik?............................................................................ 354
20.2.2. Współbieżny dostęp do licznika ................................................................ 355
20.2.3. Niszczenie a zwalnianie............................................................................ 356
20.2.4. Szablon CountingPtr ................................................................................ 357
20.2.5. Prosty licznik nieinwazyjny ...................................................................... 360
20.2.6. Szablon prostego licznika inwazyjnego ...................................................... 361
20.2.7. Stałość.................................................................................................... 362
20.2.8. Konwersje niejawne................................................................................. 363
20.2.9. Porównania ............................................................................................. 366

20.3. Uwagi końcowe ............................................................................................... 367

Rozdział 21. $ %&

21.1. Duety.............................................................................................................. 369
21.2. Duety rekurencyjne.......................................................................................... 374

21.2.1. Liczba pól duetów rekurencyjnych ............................................................ 374
21.2.2. Typy pól duetów rekurencyjnych .............................................................. 375
21.2.3. Wartości pól duetów rekurencyjnych......................................................... 376

21.3. Konstruowanie krotek ...................................................................................... 380
21.4. Uwagi końcowe ............................................................................................... 384

Rozdział 22. 0

22.1. Wywołania bezpośrednie, pośrednie i rozwijane w miejscu wywołania ................. 386
22.2. Wskaźniki i referencje do funkcji ...................................................................... 389
22.3. Wskaźniki do metod......................................................................................... 391
22.4. Funktory typów definiowanych przez użytkownika ............................................. 394

22.4.1. Pierwszy przykład funktora typu definiowanego przez użytkownika............. 394
22.4.2. Typy funktorów typów definiowanych przez użytkownika........................... 395

22.5. Przekazywanie funktorów................................................................................. 397

22.5.1. Funktory jako argumenty typu szablonów .................................................. 397
22.5.2. Funktory jako argumenty wywołania funkcji .............................................. 398
22.5.3. Połączenie parametrów wywołania funkcji z parametrami typu szablonu ...... 399
22.5.4. Funktory jako pozatypowe argumenty szablonów ....................................... 399
22.5.5. Kapsułkowanie wskaźnika do funkcji ........................................................ 400

22.6. Introspekcja..................................................................................................... 403

22.6.1. Analiza typu funktora............................................................................... 403
22.6.2. Dostęp do parametrów typów ................................................................... 404
22.6.3. Kapsułkowanie wskaźników do funkcji...................................................... 406

22.7. Składanie obiektu funkcyjnego .......................................................................... 410

22.7.1. Złożenie proste ........................................................................................ 411
22.7.2. Składanie funktorów mieszanych typów .................................................... 414
22.7.3. Zmniejszanie liczby parametrów ............................................................... 417

22.8. Wiązania wartości ............................................................................................ 420

22.8.1. Wybór wiązania....................................................................................... 420
22.8.2. Sygnatura wiązania .................................................................................. 422
22.8.3. Wybór argumentów ................................................................................. 423
22.8.4. Funkcje pomocnicze ................................................................................ 428

22.9. Operacje na funktorach — pełna implementacja.................................................. 430
22.10. Uwagi końcowe ............................................................................................. 433

background image

Spis treści

11

# $%

Dodatek A

4). "#

A.1. Jednostki translacji ............................................................................................ 437
A.2. Deklaracje i definicje......................................................................................... 438
A.3. Reguła pojedynczej definicji z bliska .................................................................. 439

A.3.1. Jedna definicja w programie....................................................................... 439
A.3.2. Jedna definicja w jednostce translacji.......................................................... 441
A.3.3. Równoważność definicji pomiędzy jednostkami translacji ............................ 443

Dodatek B

4) ""&

B.1. Kiedy potrzebne jest rozstrzyganie przeciążenia? ................................................. 450
B.2. Uproszczone rozstrzyganie przeciążenia .............................................................. 450

B.2.1. Niejawny argument metod ......................................................................... 452
B.2.2. Doskonalenie idealnego dopasowania ......................................................... 454

B.3. Przeciążanie z bliska.......................................................................................... 455

B.3.1. Dyskryminacja szablonów ......................................................................... 455
B.3.2. Sekwencje konwersji................................................................................. 456
B.3.3. Konwersje wskaźników ............................................................................. 456
B.3.4. Funktory i funkcje zastępcze...................................................................... 458
B.3.5. Inne konteksty przeciążania ....................................................................... 459

Dodatek C

5) "%

Grupy dyskusyjne .................................................................................................... 461
Książki i witryny WWW........................................................................................... 462

"%

background image

Rozdział 2.

5\CDNQP[HWPMELK

W rozdziale tym wprowadzimy pojęcie szablonu funkcji. Szablony funkcji to funkcje
sparametryzowane tak, aby mogły reprezentować całe rodziny funkcji.

Szablony funkcji definiują kod, który może być realizowany dla różnych typów danych.
Innymi słowy, szablon funkcji reprezentuje rodzinę funkcji. Reprezentacja ta przypomi-
na zwykłą funkcję języka C++, pozbawioną tylko ścisłego określenia niektórych ele-
mentów. Elementy te są więc sparametryzowane. Najlepiej wytłumaczymy to na prostym
przykładzie.

Poniższy kod stanowi deklarację szablonu funkcji zwracającej większą z dwu przekaza-
nych do niej wartości:

!"# $% !"

% &'#

(

Szablon ten definiuje rodzinę funkcji, które zwracają większą z dwu przekazanych do
nich wartości (przekazanie odbywa się za pośrednictwem parametrów wywołania funk-
cji:

i

). Typ parametrów funkcji nie został jawnie określony i występuje w szablonie

jako parametr szablonu

. Przykład pokazuje, że parametry szablonów muszą zostać

podane w ramach następującej konstrukcji składniowej:

NKUVCRCTCOGVTÎYQFF\KGNCP[EJRT\GEKPMCOK

W prezentowanym przykładzie lista parametrów zawiera wyrażenie

. Cha-

rakterystyczne jest umieszczenie listy parametrów szablonu pomiędzy znakami mniej-
szości (

<

) i większości (

>

) — utworzone tak nawiasy nazywamy nawiasami ostrymi.

Słowo kluczowe

wprowadza do listy parametrów tzw. parametr typu (ang. type

background image

24

Część I

Podstawy

parameter). Jest to chyba najbardziej znany parametr szablonów języka C++ wykorzy-
stywany często w programach, nie jest jednak jedynym dopuszczalnym parametrem;
omówimy je nieco później (patrz rozdział 4.).

Nazwą parametru typu jest w naszym przykładzie

. Nazwa ta może być dowolnym

ciągiem dopuszczalnym z punktu widzenia zasad konstruowania identyfikatorów języka
C++, dla parametru typu przyjęło się jednak stosować nazwę

. Parametr typu reprezen-

tuje typ umowny precyzowany przez programistę dopiero w miejscu wywołania funkcji.
Wywołanie może określać dowolny typ (typ podstawowy, klasę itp.) pod warunkiem, że
dla tego typu zdefiniowane są wszystkie operacje wykorzystywane w szablonie funkcji.
W prezentowanym przykładzie typ ten musi więc obsługiwać operator relacji „mniejsze
niż” (

<

), ponieważ parametry przekazywane do funkcji są porównywane właśnie za

pomocą tego operatora.

Z przyczyn historycznych w określeniu parametru typu dopuszcza się stosowanie w miej-
sce

słowa kluczowego

. Słowo kluczowe

pojawiło się w defini-

cji języka C++ stosunkowo późno; wcześniej jedynym sposobem wprowadzenia do listy
parametrów szablonu parametru typu było zastosowanie właśnie słowa kluczowego

. Możliwość ta została podtrzymana również w ostatnich wersjach standardu C++.

Nasz szablon można więc równie dobrze zdefiniować jako:

!"# $% !"

% &'#

(

Definicja ta jest znaczeniowo tożsama z definicją prezentowaną jako pierwszą. Należy
przy tym pamiętać, że pomimo zastosowania słowa kluczowego

zakres dopusz-

czalnych typów parametrów szablonu nie jest redukowany do typów definiowanych
przez użytkownika (klas). Widać więc, że stosowanie słowa kluczowego

może

być mylące (

może przecież zostać zastąpione w wywołaniu również przez typ pod-

stawowy), dlatego w przypadkach wątpliwych zaleca się stosowanie słowa kluczowego

. W miejsce słowa kluczowego

nie można natomiast z dobrym skut-

kiem zastosować słowa kluczowego

(choć jest on w pewnym zakresie tożsamy

ze słowem kluczowym

).

Poniższy program ilustruje sposób wykorzystania zdefiniowanego wcześniej szablonu
funkcji

:

)%

)% *

)%++

,-.#

''%+/'+''/''#

background image

Rozdział 2.

Szablony funkcji

25

%01,2-#

%0.,34/#

''%+010.'+''010.''#

'' *1,+$+#

'' *.,++#

''%+1.'+''1.''#

(

W tym programie funkcja

została wywołana trzykrotnie: dla dwóch argumentów

typu

, dla dwóch argumentów typu

oraz dla dwóch argumentów typu

. Za każdym razem funkcja zwróciła większą z dwóch przekazanych wartości.

Wydruk programu powinien wyglądać następująco:

/'-.

010.'-.

1.'$

Zauważmy, że każde z wywołań funkcji

zostało opatrzone operatorem zasięgu

.

Dzięki niemu mamy gwarancję, że funkcja

będzie wyszukiwana w globalnej prze-

strzeni nazw programu. Istnieje bowiem również szablon funkcji

, który w pew-

nych warunkach mógłby zostać wywołany zamiast naszego szablonu

1

.

Zazwyczaj szablony nie są kompilowane do postaci jednostek obsługujących typ do-
wolny. Dla każdego nowego typu, dla którego wywołany zostanie szablon, generowana
jest osobna jednostka programowa

2

. Funkcja

zostanie więc skompilowana trzy-

krotnie, dla każdego z typów, z którym została wywołana. Dla przykładu, pierwsze
wywołanie funkcji

:

,-.#

5/5

oznacza takie odwołanie do szablonu funkcji, które określa parametr

jako

. Wy-

wołanie to odpowiada więc wywołaniu następującej funkcji:

!"# $% !"

% &'#

(

Proces zastępowania parametrów szablonu konkretnymi typami nazywamy konkretyza-
cją (ang. instantiation) szablonu. Jej efektem jest utworzenie egzemplarza (ang. instan-
ce) szablonu. Co prawda pojęcia egzemplarza i konkretyzacji w kontekście programo-
wania obiektowego stosowane są również w odniesieniu do obiektów klas, jednak ze
względu na tematykę niniejszej książki terminy te będziemy odnosić zawsze do szablo-
nów (o ile nie zaznaczymy inaczej).

1

Przykładowo, jeżeli typ jednego z parametrów wywołania zostanie zdefiniowany w przestrzeni nazw

(jak choćby typ

'' *

), reguły wyszukiwania języka C++ spowodują dopasowanie w miejscu

wywołania obu szablonów globalnego

i

''

.

2

Alternatywa, polegająca na generowaniu przez kompilator jednostek uniwersalnych, jest co prawda
do pomyślenia, ale w praktyce stosuje się ją rzadko. Wszystkie reguły języka oparte są na koncepcji
zakładającej generowanie osobnych jednostek dla różnych typów szablonów.

background image

26Część I

Podstawy

Istotne jest, że konkretyzację wyzwala samo zastosowanie szablonu funkcji — progra-
mista nie musi jawnie żądać utworzenia egzemplarza szablonu.

Pozostałe wywołania

konkretyzują szablon

dla typów

i

i są wykorzystywane dokładnie tak, jakby specjalnie dla tych wywołań zostały zdefi-
niowane i zaimplementowane funkcje:

%%%#

'' *'' *'' *#

Próba konkretyzacji szablonu dla typu, który nie obsługuje wszystkich operacji wyko-
rzystywanych w szablonie, sprowokuje błąd kompilacji. Przykład:

''01.#6%*%

5

1.#789:$

Jak widać, szablony są kompilowane dwukrotnie:

Pierwszy raz bez konkretyzacji: kod szablonu jest analizowany pod kątem
poprawności składniowej. Na tym etapie wykrywane są błędy składniowe,
takie jak brakujące średniki.

Drugi raz podczas konkretyzacji: kod szablonu jest weryfikowany pod kątem
poprawności wszystkich wywołań. Na tym etapie wykrywane są niepoprawne
wywołania, takie jak wywołania funkcji nieobsługujące danego typu.

W praktyce dwukrotna kompilacja jest przyczyną dość istotnego problemu: kiedy sza-
blon funkcji jest wykorzystywany w sposób prowokujący jego konkretyzację, kompi-
lator (w pewnym momencie) musi odwołać się do definicji szablonu. Powoduje to naru-
szenie uświęconej wieloletnią tradycją języka C separacji pomiędzy etapem kompilacji
a etapem konsolidacji kodu funkcji, gdyż normalnie do kompilacji wywołania funkcji
wystarczające jest jej uprzednie zadeklarowanie. W rozdziale 6. pokażemy, jak poradzić
sobie z tym problemem. Na razie zaś wykorzystamy metodę najprostszą: implementację
każdego szablonu w pliku nagłówkowym, za pomocą słowa kluczowego

.

Wywołując szablon funkcji (jak

) z pewnymi argumentami, określamy za ich po-

średnictwem parametry szablonu. Jeżeli jako parametry

przekazane zostaną

zmienne typu

, kompilator języka C++ założy, że typem

jest typ

. Zauważmy,

że taki sposób wnioskowania o typie parametrów wyklucza stosowanie automatycznej
konwersji typów w miejscu wywołania szablonu funkcji. Każdy typ

musi zostać okre-

ślony w sposób jawny. Oto przykład:

#

5

-/#:;7<=>'% *%!

--.#789:' *%% %*%%

background image

Rozdział 2.

Szablony funkcji

27

Błąd ten można wyeliminować na trzy sposoby:

Przez jawne rzutowanie parametrów do wspólnego typu:

?%--.#:;7<=>

Przez jawne określenie typu

w wywołaniu szablonu:

%--.#

Przez zdefiniowanie szablonu o dwóch różnych parametrach typu.

Szczegółowe omówienie każdej z trzech metod znajduje się w kolejnym podrozdziale.

!

Szablony funkcji można zdefiniować przy użyciu dwóch rodzajów parametrów:

Parametrów szablonu, deklarowanych wewnątrz nawiasów ostrych przed nazwą
szablonu funkcji:

%

Parametrów wywołania, deklarowanych wewnątrz nawiasów zwykłych
po nazwie szablonu funkcji:

5@ 6

Nie istnieje ograniczenie liczby parametrów szablonu. Niemniej jednak w szablonach
funkcji (w przeciwieństwie do szablonów klas) nie można zdefiniować domyślnych ar-
gumentów szablonu

3

. Definicja szablonu

taka, aby w wywołaniu przyjmowane

były argumenty różnych typów, wyglądałaby następująco:

1.

11.

% &'#

(

5

--.#:;7<=> * *%% % A

Metoda polegająca na dopuszczeniu w wywołaniu parametrów różnych typów wydaje
się skuteczna, ale skuteczność ta jest pozorna. Problem tkwi w typie wartości zwracanej
przez szablon funkcji. Jeżeli wartość ta będzie typu zgodnego z typem jednego z para-
metrów, argument drugiego typu będzie musiał zostać poddany konwersji do typu pierw-
szego, niezależnie od intencji programisty. Język C++ nie dysponuje bowiem metodami
pozwalającymi na wyznaczenie „lepszego” z dwóch typów (choć można tę możliwość
zaimplementować przy użyciu pewnych sztuczek z szablonami, prezentowanymi w punk-
cie 15.2.4). Dlatego kolejność przekazywania argumentów wywołania

jako mak-

simum z wartości 42 i 66.66 możemy otrzymać wartość 66.66 (typu

) bądź 66

3

Ograniczenie to jest rezultatem zaszłości związanych z projektowaniem szablonów funkcji. Wydaje się, że
nie ma technicznych przeciwwskazań do implementacji takiej możliwości w nowoczesnych kompilatorach
języka C++; w przyszłości możliwość ta będzie najprawdopodobniej dostępna (patrz podrozdział 13.3).

background image

28

Część I

Podstawy

(typu

). Inny problem to tworzenie lokalnego obiektu tymczasowego podczas kon-

wersji typu drugiego parametru — tak utworzonego obiektu nie można zwrócić przez
referencję

4

. W naszym przykładzie oznacza to konieczność modyfikacji definicji sza-

blonu tak, aby zwracał typ

zamiast

.

Typy parametrów wywołania tworzone są na podstawie parametrów szablonu, więc pa-
rametry szablonu i parametry wywołania można zazwyczaj ze sobą powiązać. Wiązanie
takie nazywamy dedukcją argumentów szablonu funkcji. Mechanizm ten pozwala na
wywoływanie szablonów funkcji dokładnie tak jak funkcji „zwykłych”.

Tym niemniej możliwa jest również jawna konkretyzacja szablonu dla wskazanych typów:

#

5

%--.#$$ %%%

W przypadkach, kiedy nie ma powiązania pomiędzy parametrami wywołania a parame-
trami szablonu i niemożliwe jest określenie parametrów szablonu, konieczne jest jawne
określenie argumentu szablonu w miejscu wywołania. Przykładowo, typ wartości zwra-
canej przez szablon funkcji można określić, wprowadzając do definicji szablonu trzeci
parametr szablonu:

1.<

<1.#

Niemniej jednak dedukcja typu argumentów nie obejmuje typu wartości zwracanej

5

, a

nie występuje na liście typów parametrów wywołania funkcji. Nie można więc wyde-
dukować typu

. W efekcie konieczne jest jawne określanie w miejscu wywołania peł-

nej listy parametrów szablonu. Przykład:

1.<

<1.#

5

%%--.#:;7<=>*

Pokazaliśmy jak dotąd przypadki, w których jawnie (w miejscu wywołania) określany
był albo każdy, albo żaden z argumentów szablonu. Możliwe jest również jawne określa-
nie jedynie pierwszych kilku argumentów — pozostałe zostaną wydedukowane. W ogól-
ności konieczne jest określenie wszystkich argumentów typów aż do ostatniego argu-
mentu, którego typ nie może zostać określony niejawnie (przez dedukcję). Jeżeli więc
zmienimy kolejność na liście parametrów przykładowego szablonu, będziemy mogli wy-
woływać funkcję szablonu, podając jawnie wyłącznie typ wartości zwracanej:

<1.

<1.#

5

%--.#:;7<=>' A %

4

Zwracanie wartości przez referencję nie jest dozwolone w przypadku obiektów lokalnych względem
funkcji, ponieważ po wyjściu z funkcji obiekt ten przestanie istnieć.

5

Dedukcję można postrzegać jako część procesu rozstrzygania przeciążenia — proces ten również ignoruje
typy wartości zwracanych. Jedynym wyjątkiem jest typ zwracany składowych operatorów konwersji klasy.

background image

Rozdział 2.

Szablony funkcji

29

W powyższym przykładzie wywołanie

określa w sposób jawny typ warto-

ści zwracanej przez funkcję; parametry

i

muszą zaś zostać wydedukowane na pod-

stawie argumentów wywołania (tu:

i

).

Zauważmy, że kolejne przeróbki szablonu funkcji

nie zmieniają zasadniczo jego

funkcjonalności. Już w przypadku wersji jednoparametrowej szablonu można określać
typ parametrów przekazywanych w wywołaniu (i typ wartości zwracanej), nawet w przy-
padku przekazania argumentów dwóch różnych typów. Zaleca się więc maksymalne
upraszczanie szablonów — w kolejnych podrozdziałach korzystać będziemy z jednopa-
rametrowego szablonu funkcji

.

Proces dedukcji parametrów został szczegółowo omówiony w rozdziale 11.

"!#$

Podobnie jak to ma miejsce w przypadku zwykłych funkcji, szablony funkcji mogą być
przeciążane. Przeciążanie oznacza możliwość korzystania z różnych definicji funkcji,
o tych samych nazwach. Kiedy nazwa ta zostanie wykorzystana w wywołaniu, kompi-
lator języka C++ podejmuje decyzję o wyborze funkcji do obsługi wywołania. Reguły
rządzące procesem decyzyjnym są dostatecznie skomplikowane i bez szablonów. W bie-
żącym podrozdziale omówimy przeciążanie wykorzystujące szablony funkcji. Czytelnicy,
którym podstawowe reguły rozstrzygania przeciążania bez szablonów nie są znane, po-
winni zapoznać się z dodatkiem B, gdzie zostały one opisane w dość szczegółowy sposób.

Ilustracją przeciążania szablonu funkcji może być następujący, prosty program:

.

$%! A%

% &'#

(

$%! A*%

% &'#

(

$% A*%

% #

(

''/-.4B#6% $ *%!

''/C-.C#6%%%$% *%!

background image

30

Część I

Podstawy

''DDDD#6%%%$% *%!

''/-.#60%$$6! *%!

''/-.#6%%$% *%!

''%/-.#6%%%$%

''DD-./#60%$$6! *%!

(

Jak widać, „zwykłe” funkcje mogą współistnieć z szablonami funkcji o tych samych na-
zwach i konkretyzowanych dla tych samych co owe zwykłe funkcje typów. Jeżeli wszyst-
kie pozostałe czynniki są identyczne, proces rozstrzygający przeciążenia preferuje funk-
cje „zwykłe” przed szablonami. Sytuację tę ilustruje czwarte z kolei wywołanie:

/-.# *%@0%$$6

Jeżeli na podstawie szablonu można wygenerować lepsze dopasowanie, wybierany jest
oczywiście szablon. Przypadek taki miał miejsce w wywołaniach drugim i trzecim:

/C-.C#6%%%$% *%!

DDDD#6% %$% *%!

Możliwe jest również jawne wskazanie pustej listy argumentów szablonu. W ten sposób
programista sygnalizuje konieczność wykorzystania szablonu, przy czym jego parame-
try powinny zostać wydedukowane na podstawie argumentów wywołania:

/-.#6%%$% *%!

Ponieważ w przypadku szablonów funkcji nie jest wykonywana automatyczna konwer-
sja typu parametrów wywołania, ale konwersja taka jest przeprowadzana dla zwykłych
funkcji, ostatnie wywołanie dopasowane zostanie do funkcji zwykłej (parametry

i

!

zostaną poddane konwersji do typu

):

DD-./#$$60%$% ! *%!6

Bardziej użytecznym przykładem będzie przeciążenie szablonu zwracającego maksi-
mum tak, aby obsługiwał on wskaźniki i ciągi znakowe języka C:

2

)%

)% *

)% *

$%! A*%

% &'#

(

$%!$E$!

FFF

% FF&'#

(

background image

Rozdział 2.

Szablony funkcji

31

$%!@*!G$H

F F F

% '' C&'#

(

,/#

,-.#

''#$%! A%

'' *,++#

'' *,++#

''#$%! A%'' *

F1,#

F.,#

''1.#$%!$E$!

F1,+:I+#

F.,+J+#

''1.#$%!@*!G$H

(

We wszystkich implementacjach przeciążonych argumenty były przekazywane przez
referencje, bowiem przeciążając szablony funkcji, warto ograniczać zmiany w stosunku
do funkcji zwykłych. Zmiany te powinny sprowadzać się do zmiany liczby parametrów
lub do jawnego określania parametrów szablonu. W przeciwnym przypadku należy przy-
gotować się na niespodzianki. Przykładowo, po przeciążeniu szablonu funkcji

(zakładającego przekazywanie argumentów przez referencję) dla dwóch ciągów języka
C przekazywanych przez wartość, nie można korzystać z trójargumentowej wersji

do wskazywania maksimum z trzech ciągów języka C:

2

)%

)% *

)% *

$%! A*% $ 0 G

% &'#

(

$%!@*!G$H $ A"

F F F

% '' C&'#

(

$% A*% $ 0 G

background image

32

Część I

Podstawy

% #6@$ $

A"

(

''/-.4B#:;7<=>

F1,+K +#

F.,+L+#

F2,+M%+#

''1.2#789:

(

Błąd pojawia się w miejscu wywołania

dla trzech ciągów języka C:

% #

Błąd spowodowany jest utworzeniem przez wywołanie

"

nowego, tymczaso-

wego lokalnego względem wywołania, obiektu, który nie może zostać zwrócony na ze-
wnątrz przez referencję.

To tylko jeden z możliwych przykładów kodu, który będzie się zachowywał niezgodnie
z oczekiwaniem programisty w wyniku zastosowania reguł rozstrzygania przeciążania.
Dla przykładu, dla poprawności działania programu znaczący może okazać się fakt wi-
doczności bądź niewidoczności wszystkich wersji przeciążonych w miejscu wywołania
funkcji. W rzeczy samej, definiowanie trójargumentowej wersji szablonu

poza

zakresem widoczności deklaracji zwykłej funkcji dwuargumentowej dla typu

może

spowodować preferowanie, zamiast funkcji zwykłej, szablonu:

-

$%! A*%

% &'#

(

$% A*%

% #$ %$$ %

%0%$$6

$

6!E

(

$%! A%

% &'#

(

background image

Rozdział 2.

Szablony funkcji

33

Szersze omówienie tego zagadnienia zamieściliśmy w rozdziale 12.; na razie należałoby
pamiętać o konieczności zdefiniowania wszystkich wersji przeciążanych funkcji i sza-
blonów przed pierwszym wywołaniem.

%!

Szablony funkcji definiują rodzinę funkcji dla różnych parametrów szablonu.

Przekazując w wywołaniu argumenty szablonu, konkretyzujemy szablon funkcji
dla wskazanych typów argumentów.

Możliwe jest jawne kwalifikowanie parametrów szablonu.

Możliwe jest przeciążanie szablonów funkcji.

Przeciążając szablony funkcji, należy ograniczać zmiany do jawnego określania
parametrów szablonu.

Zawsze warto sprawdzić, czy w miejscu wywołania znane są wszystkie wersje
przeciążonego szablonu funkcji.


Wyszukiwarka

Podobne podstrony:
C Szablony Vademecum profesjonalisty cpszav
C++ Szablony Vademecum profesjonalisty
C Szablony Vademecum profesjonalisty cpszav
C Szablony Vademecum profesjonalisty cpszav
C Szablony Vademecum profesjonalisty
C Szablony Vademecum profesjonalisty cpszav
C Szablony Vademecum profesjonalisty
Asembler dla procesorow Intel Vademecum profesjonalisty asinvp
CorelDRAW 11 Vademecum profesjonalisty Tom 2
Delphi dla NET Vademecum profesjonalisty
Firewalle i bezpieczenstwo w sieci Vademecum profesjonalisty firevp
Jezyk C Wskazniki Vademecum profesjonalisty cwskvp
PHP Programowanie w systemie Windows Vademecum profesjonalisty
Firewalle i bezpieczeństwo w sieci Vademecum profesjonalisty
Język C WskaĽniki Vademecum profesjonalisty
Protokoly SNMP i RMON Vademecum profesjonalisty
ASP NET Vademecum profesjonalisty
C++ Programowanie zorientowane obiektowo Vademecum profesjonalisty
helion windows 2000 server vademecum profesjonalisty 8 projektowanie domen windows 2000 YHNURPZ44

więcej podobnych podstron