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  .

1  1.



 % &'#

(

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$!

   

F  FF



 % 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.