SlideShare a Scribd company logo
1 of 84
Download to read offline
IDZ DO
         PRZYK£ADOWY ROZDZIA£

                           SPIS TRE CI   Thinking in C++.
                                         Edycja polska. Tom II
           KATALOG KSI¥¯EK
                                         Autor: Bruce Eckel, Chuck Allison
                      KATALOG ONLINE     T³umaczenie: Przemys³aw Szeremiota, Tomasz ¯mijewski
                                         ISBN: 83-7361-409-5
                                         Tytu³ orygina³u: Thinking in C++, Vol. 2:
       ZAMÓW DRUKOWANY KATALOG           Practical Programming, Second Edition
                                         Format: B5, stron: 688
              TWÓJ KOSZYK                Nauka jêzyka C++ i szczegó³owe poznanie jego mo¿liwo ci to powa¿ne wyzwanie
                    DODAJ DO KOSZYKA     nie tylko dla pocz¹tkuj¹cego, ale równie¿ dla zaawansowanego programisty.
                                         W ksi¹¿ce Thinking in C++. Edycja polska. Bruce Eckel w doskona³y sposób
                                         przedstawi³ podstawowe zagadnienia zwi¹zane z tym jêzykiem. Je li opanowa³e
         CENNIK I INFORMACJE             materia³ z tej ksi¹¿ki, mo¿esz rozpocz¹æ lekturê drugiego tomu.
                                         Ksi¹¿ka, któr¹ trzymasz w rêce — Thinking in C++. Edycja polska. Tom II to kolejny
                   ZAMÓW INFORMACJE      bestseller Bruce’a Eckela po wiêcony jêzykowi C++. Tym razem Bruce w typowy dla
                     O NOWO CIACH        siebie, prosty i zrozumia³y sposób opisuje zaawansowane aspekty programowania
                                         w C++. Dowiesz siê, jak korzystaæ z referencji, przeci¹¿ania operatorów, dziedziczenia
                       ZAMÓW CENNIK      i obiektów dynamicznych, a tak¿e poznasz zagadnienia zaawansowane — prawid³owe
                                         u¿ycie szablonów, wyj¹tków i wielokrotnego dziedziczenia. Wszystkie tematy opatrzone
                                         s¹ æwiczeniami.
                 CZYTELNIA                  • obs³uga wyj¹tków
                                            • programowanie defensywne
          FRAGMENTY KSI¥¯EK ONLINE          • standardowa biblioteka C++
                                            • strumienie wej cia-wyj cia
                                            • wzorce projektowe
                                            • zaawansowane metody programowania obiektowego
                                            • wspó³bie¿no æ
                                         Kody ród³owe znajduj¹ce siê w ksi¹¿ce s¹ zgodne z wieloma kompilatorami C++.
                                         Bruce Eckel jest prezesem MindView, Inc., firmy prowadz¹cej kursy i szkolenia zarówno
                                         otwarte, jak i zamkniête, a tak¿e zajmuj¹cej siê doradztwem i nadzorem nad projektami
                                         zwi¹zanymi z technologiami obiektowymi i wzorcami projektowymi. Jest autorem
                                         ksi¹¿ek Thinking in Java oraz pierwszego tomu Thinking in C++, a tak¿e wspó³autorem
                                         ksi¹¿ki Thinking in C#. Napisa³ tak¿e kilka innych ksi¹¿ek i ponad 150 artyku³ów.
Wydawnictwo Helion                       Od ponad 20 lat prowadzi wyk³ady i seminaria na ca³ym wiecie. By³ cz³onkiem
ul. Chopina 6                            Komitetu Standardów C++. Zdoby³ tytu³ naukowy w dziedzinie fizyki stosowanej
44-100 Gliwice                           i in¿ynierii oprogramowania.
tel. (32)230-98-63
                                         Chuck Allison jest matematykiem, pe³ni¹cym obecnie funkcjê wyk³adowcy na wydziale
e-mail: helion@helion.pl
                                         informatyki uniwersytetu stanowego Utah Valley. Do niedawna pe³ni³ funkcjê redaktora
                                         w magazynie C/C++ Users Journal. Jest tak¿e autorem ksi¹¿ki C&C++ Code Capsules:
                                         A Guide for Practitioners i kilkudziesiêciu artyku³ów po wiêconych programowaniu w C
                                         i C++. Bra³ udzia³ w tworzeniu standardu C++. Jego artyku³y i omówienia napisanych
                                         przez niego ksi¹¿ek mo¿na znale æ w witrynie WWW www.freshsources.com.
Spis treści
               Wstęp ............................................................................................. 11
               Cele....................................................................................................................................11
               Rozdziały...........................................................................................................................12
               Ćwiczenia ..........................................................................................................................14
                   Rozwiązania do ćwiczeń.............................................................................................14
               Kod źródłowy....................................................................................................................15
               Obsługiwane wersje języka...............................................................................................16
               Standardy językowe ..........................................................................................................17
               O okładce...........................................................................................................................17

Część I        Tworzenie niezawodnych systemów.................................19
Rozdział 1. Obsługa wyjątków............................................................................ 21
               Tradycyjna obsługa błędów ..............................................................................................22
               Wyrzucanie wyjątku..........................................................................................................24
               Przechwytywanie wyjątku.................................................................................................25
                   Blok try .......................................................................................................................25
                   Obsługa wyjątków ......................................................................................................25
                   Zakończenie i kontynuacja .........................................................................................26
               Dopasowywanie wyjątków ...............................................................................................27
                   Przechwytywanie dowolnych wyjątków.....................................................................29
                   Ponowne wyrzucanie wyjątku ....................................................................................29
                   Wyjątki nieprzechwycone...........................................................................................30
               Czyszczenie.......................................................................................................................32
                   Zarządzanie zasobami.................................................................................................33
                   Wszystko jest obiektem ..............................................................................................34
                   auto_ptr .......................................................................................................................36
                   Bloki try na poziomie funkcji .....................................................................................38
               Wyjątki standardowe.........................................................................................................39
               Specyfikacje wyjątków .....................................................................................................41
                   Jakieś lepsze specyfikacje wyjątków? ........................................................................45
                   Specyfikacja wyjątków i dziedziczenie ......................................................................45
                   Kiedy nie u ywać specyfikacji wyjątków?.................................................................46
               Bezpieczeństwo wyjątków ................................................................................................47
               Programowanie z u yciem wyjątków ...............................................................................50
                   Kiedy unikać wyjątków?.............................................................................................51
                   Typowe zastosowania wyjątków ................................................................................52
               Narzuty ..............................................................................................................................55
               Podsumowanie ..................................................................................................................57
               Ćwiczenia ..........................................................................................................................57
6                                                                                    Thinking in C++. Edycja polska. Tom 2


Rozdział 2. Programowanie defensywne ............................................................. 59
               Asercje...............................................................................................................................61
               Najprostszy system testów jednostkowych, który ma szansę zadziałać ...........................65
                  Automatyczne testowanie ...........................................................................................66
                  Szkielet TestSuite........................................................................................................70
                  Zestawy testowe..........................................................................................................73
                  Kod szkieletu testowego .............................................................................................74
               Techniki usuwania błędów................................................................................................79
                  Makra śledzące............................................................................................................79
                  Plik śladu.....................................................................................................................80
                  Znajdowanie wycieków pamięci.................................................................................81
               Podsumowanie ..................................................................................................................86
               Ćwiczenia ..........................................................................................................................86

Część II       Standardowa biblioteka C++...........................................91
Rozdział 3. Wszystko o łańcuchach.................................................................... 93
               Czym jest łańcuch?............................................................................................................94
               Tworzenie i inicjalizacja łańcuchów C++...........................................................................95
               Operacje na łańcuchach.....................................................................................................98
                  Dodawanie, wstawianie i łączenie łańcuchów............................................................98
                  Podmiana znaków łańcucha......................................................................................100
                  Sklejanie za pomocą przecią onych operatorów spoza klasy...................................103
               Szukanie w łańcuchach ...................................................................................................104
                  Znajdowanie od końca ..............................................................................................107
                  Znajdowanie pierwszego i ostatniego ze zbioru znaków..........................................109
                  Usuwanie znaków z łańcuchów ................................................................................111
                  Porównywanie łańcuchów ........................................................................................112
                  Łańcuchy a znaki ......................................................................................................116
               Przykład zastosowania łańcuchów ..................................................................................121
               Podsumowanie ................................................................................................................125
               Ćwiczenia ........................................................................................................................126
Rozdział 4. Strumienie wejścia-wyjścia............................................................. 129
               Po co nowa biblioteka? ...................................................................................................129
               Iostream przybywa z odsieczą.........................................................................................133
                   Wstawianie i pobieranie............................................................................................134
                   Typowe zastosowania ...............................................................................................137
                   Dane wejściowe pobierane wierszami ......................................................................139
               Obsługa błędów strumieni...............................................................................................140
               Strumienie związane z plikami .......................................................................................143
                   Przykład przetwarzania pliku....................................................................................143
                   Tryby otwarcia ..........................................................................................................145
               Buforowanie strumieni....................................................................................................146
               Przeszukiwanie strumieni wejścia-wyjścia .....................................................................148
               Strumienie powiązane z łańcuchami ...............................................................................151
                   Łańcuchowe strumienie wejściowe ..........................................................................152
                   Łańcuchowe strumienie wyjściowe ..........................................................................153
               Formatowanie strumieni wyjściowych............................................................................156
                   Flagi formatujące ......................................................................................................156
                   Pola formatujące .......................................................................................................158
                   Szerokość, wypełnienie, dokładność ........................................................................159
                   Kompletny przykład..................................................................................................160
Spis treści                                                                                                                                      7


               Manipulatory ...................................................................................................................162
                  Manipulatory z argumentami....................................................................................163
                  Tworzenie manipulatorów ........................................................................................166
                  Efektory.....................................................................................................................167
               Przykłady wykorzystujące iostream................................................................................169
                  Zarządzanie kodem źródłowym biblioteki klas ........................................................169
                  Wykrywanie błędów kompilatora.............................................................................173
                  Prosty rejestrator danych...........................................................................................175
               Obsługa wielu języków ...................................................................................................179
                  Strumienie znaków szerokich ...................................................................................179
                  Ustawienia lokalne....................................................................................................181
               Podsumowanie ................................................................................................................183
               Ćwiczenia ........................................................................................................................183
Rozdział 5. Wszystko o szablonach .................................................................. 187
               Parametry szablonów ......................................................................................................187
                   Parametry szablonów niebędące typami...................................................................188
                   Domyślne argumenty szablonów..............................................................................190
                   Szablony jako parametry szablonów ........................................................................191
                   Słowo kluczowe typename .......................................................................................196
                   U ycie słowa kluczowego template jako wskazówki...............................................198
                   Szablony składowe....................................................................................................199
               Szablony funkcji..............................................................................................................201
                   Dedukowanie typu argumentów szablonu funkcji....................................................202
                   Przecią anie szablonów funkcji................................................................................205
                   Pobieranie adresu wygenerowanej z szablonu funkcji .............................................206
                   Stosowanie funkcji do sekwencji STL......................................................................209
                   Częściowe uporządkowanie szablonów funkcji .......................................................212
               Specjalizacja szablonów..................................................................................................213
                   Specjalizacja jawna...................................................................................................214
                   Specjalizacja częściowa ............................................................................................215
                   Przykład praktyczny..................................................................................................217
                   Unikanie nadmiarowego kodu ..................................................................................220
               Odszukiwanie nazw.........................................................................................................224
                   Nazwy w szablonach.................................................................................................224
                   Szablony i funkcje zaprzyjaźnione ...........................................................................228
               Idiomy programowania za pomocą szablonów...............................................................233
                   Cechy charakterystyczne ..........................................................................................233
                   Reguły .......................................................................................................................238
                   Tajemniczo powtarzający się wzorzec szablonów ...................................................240
               Szablony i metaprogramowanie ......................................................................................242
                   Programowanie na poziomie kompilacji ..................................................................243
                   Szablony wyra eń .....................................................................................................251
               Modele kompilacji szablonów ........................................................................................256
                   Model włączania .......................................................................................................256
                   Ukonkretnianie jawne ...............................................................................................257
                   Model separacji.........................................................................................................259
               Podsumowanie ................................................................................................................260
               Ćwiczenia ........................................................................................................................261
Rozdział 6. Algorytmy uogólnione..................................................................... 265
               Algorytmy uogólnione — wprowadzenie ..........................................................................265
                  Predykaty ..................................................................................................................268
                  Iteratory strumieni.....................................................................................................270
                  Zło oność algorytmu ................................................................................................272
8                                                                                   Thinking in C++. Edycja polska. Tom 2


                Obiekty funkcyjne ...........................................................................................................274
                   Klasyfikacja obiektów funkcyjnych .........................................................................275
                   Automatyczne tworzenie obiektów funkcyjnych......................................................276
                   Adaptowalność obiektów funkcyjnych.....................................................................279
                   Więcej przykładów wykorzystania obiektów funkcyjnych ......................................281
                   Adaptery wskaźników do funkcji .............................................................................287
                   Pisanie własnych adapterów obiektów funkcyjnych ................................................293
                Katalog algorytmów STL................................................................................................297
                   Narzędzia przydatne w tworzeniu przykładów.........................................................299
                   Wypełnianie i generowanie sekwencji......................................................................303
                   Zliczanie....................................................................................................................304
                   Manipulowanie sekwencjami....................................................................................305
                   Wyszukiwanie i zastępowanie elementów................................................................310
                   Porównywanie sekwencji..........................................................................................316
                   Usuwanie elementów sekwencji ...............................................................................319
                   Sortowanie i operacje na sekwencjach posortowanych ............................................322
                   Operacje na stertach..................................................................................................331
                   Wykonywanie operacji na wszystkich elementach sekwencji..................................332
                   Algorytmy numeryczne ............................................................................................339
                   Narzędzia ..................................................................................................................342
                Tworzenie własnych algorytmów uogólnionych ............................................................343
                Podsumowanie ................................................................................................................345
                Ćwiczenia ........................................................................................................................345
Rozdział 7. Kontenery...................................................................................... 351
                Kontenery i iteratory .......................................................................................................351
                    Dokumentacja biblioteki STL...................................................................................353
                Wprowadzenie.................................................................................................................353
                    Kontenery przechowujące ciągi znakowe.................................................................358
                    Dziedziczenie po kontenerach STL ..........................................................................360
                Kraina iteratorów.............................................................................................................362
                    Iterator w kontenerach dwukierunkowych................................................................364
                    Kategorie iteratorów .................................................................................................365
                    Iteratory predefiniowane...........................................................................................367
                Kontenery sekwencyjne: vector, list i deque...................................................................373
                    Podstawowe operacje na kontenerach sekwencyjnych .................................................373
                    Kontener typu vector.................................................................................................376
                    Kontener typu deque .................................................................................................383
                    Konwersja sekwencji ................................................................................................385
                    Kontrolowany dostęp swobodny...............................................................................387
                    Kontener typu list......................................................................................................388
                    Wymienianie całych sekwencji.................................................................................393
                Kontener typu set ............................................................................................................394
                    Klasa iteratora słów...................................................................................................397
                Szablon stack...................................................................................................................402
                Szablon queue .................................................................................................................405
                Kolejki priorytetowe .......................................................................................................410
                Przechowywanie bitów ...................................................................................................418
                    Typ bitset<n> ............................................................................................................419
                    Typ vector<bool> .....................................................................................................422
                Kontenery asocjacyjne ....................................................................................................424
                    Generowanie elementów i wypełnianie kontenerów asocjacyjnych ........................428
                    Magia kontenerów typu map ....................................................................................431
                    Kontener typu multimap ...........................................................................................433
                    Kontener typu multiset..............................................................................................436
Spis treści                                                                                                                                         9


                Korzystanie z wielu kontenerów STL.............................................................................439
                Czyszczenie kontenera wskaźników ...............................................................................442
                Tworzenie własnych kontenerów....................................................................................444
                Rozszerzenia biblioteki STL ...........................................................................................446
                Kontenery spoza STL......................................................................................................448
                Podsumowanie ................................................................................................................452
                Ćwiczenia ........................................................................................................................453

Część III Zagadnienia zaawansowane .........................................457
Rozdział 8. Rozpoznawanie typu w czasie wykonania programu......................... 459
                Rzutowanie w czasie wykonania.....................................................................................459
                Operator typeid................................................................................................................464
                   Rzutowanie na pośrednie poziomy hierarchii klas ...................................................466
                   Wskaźniki na typ void ..............................................................................................467
                   RTTI a szablony........................................................................................................468
                Wielodziedziczenie .........................................................................................................469
                Zastosowania mechanizmu RTTI....................................................................................470
                   Sortownia odpadków ................................................................................................471
                Implementacja i narzuty mechanizmu RTTI...................................................................475
                Podsumowanie ................................................................................................................475
                Ćwiczenia ........................................................................................................................476
Rozdział 9. Wielodziedziczenie ......................................................................... 479
                Wprowadzenie do wielodziedziczenia ............................................................................479
                Dziedziczenie interfejsu ..................................................................................................481
                Dziedziczenie implementacji ..........................................................................................484
                Duplikaty podobiektów ...................................................................................................489
                Wirtualne klasy bazowe ..................................................................................................493
                Wyszukiwanie nazw........................................................................................................502
                Unikanie wielodziedziczenia...........................................................................................504
                Rozszerzanie interfejsu ...................................................................................................506
                Podsumowanie ................................................................................................................509
                Ćwiczenia ........................................................................................................................510
Rozdział 10. Wzorce projektowe ........................................................................ 513
                Pojęcie wzorca.................................................................................................................513
                    Wy szość kompozycji nad dziedziczeniem..............................................................515
                Klasyfikacja wzorców .....................................................................................................515
                    Właściwości, pojęcia, wzorce ...................................................................................516
                Upraszczanie pojęć..........................................................................................................516
                    Posłaniec ...................................................................................................................517
                    Parametr zbiorczy .....................................................................................................518
                Singleton..........................................................................................................................519
                    Odmiany Singletona..................................................................................................520
                Polecenie — wybór operacji ...........................................................................................524
                    Polecenia izolujące obsługę zdarzeń.........................................................................526
                Izolowanie obiektów .......................................................................................................529
                    Pośrednik — dostęp do innego obiektu ....................................................................529
                    Stan — modyfikowanie czynności obiektu ..............................................................531
                Adapter ............................................................................................................................532
                Metoda szablonowa.........................................................................................................535
                Strategia — dynamiczny wybór algorytmu ....................................................................536
                Łańcuch odpowiedzialności — wypróbowywanie sekwencji strategii ................................537
10                                                                                  Thinking in C++. Edycja polska. Tom 2


                Fabryki — hermetyzacja procesu tworzenia obiektu......................................................540
                    Fabryki polimorficzne...............................................................................................542
                    Fabryka abstrakcyjna ................................................................................................545
                    Konstruktory wirtualne .............................................................................................547
                Builder — tworzenie zło onych obiektów .........................................................................552
                Obserwator ......................................................................................................................558
                    Pojęcie klasy wewnętrznej........................................................................................561
                    Przykład zastosowania Obserwatora.........................................................................564
                Dyspozycja wielokrotna..................................................................................................567
                    Wielokrotna dyspozycja z wzorcem Wizytator ........................................................571
                Podsumowanie ................................................................................................................575
                Ćwiczenia ........................................................................................................................575
Rozdział 11. Współbieżność............................................................................... 579
                Motywacja.......................................................................................................................580
                Współbie ność w języku C++.........................................................................................582
                    Instalacja biblioteki ZThread ....................................................................................582
                Definiowanie zadań.........................................................................................................584
                Klasa Thread ...................................................................................................................585
                    Tworzenie interfejsu u ytkownika o krótkim czasie odpowiedzi.............................587
                    Uproszczenie kodu z wykorzystaniem Wykonawców .............................................589
                    Tymczasowe zawieszanie działania wątków ............................................................592
                    Usypianie wątków.....................................................................................................594
                    Priorytety wątków.....................................................................................................595
                Współdzielenie ograniczonych zasobów............................................................................597
                    Gwarantowanie istnienia obiektów...........................................................................597
                    Niewłaściwe odwołania do zasobów ........................................................................601
                    Kontrola dostępu.......................................................................................................603
                    Uproszczenie kodu z wykorzystaniem Stra ników ..................................................605
                    Pamięć lokalna wątku ...............................................................................................608
                Zatrzymywanie zadań .....................................................................................................610
                    Zapobieganie kolizji odwołań do strumieni wejścia-wyjścia ...................................610
                    Ogród botaniczny......................................................................................................611
                    Zatrzymywanie zadań zablokowanych .....................................................................616
                    Przerwanie.................................................................................................................617
                Współpraca wątków ........................................................................................................623
                    Oczekiwanie i nadawanie sygnałów .........................................................................623
                    Zale ności typu producent-konsument .....................................................................627
                    Rozwiązywanie problemów wielowątkowości przez kolejkowanie.........................630
                    Sygnalizacja rozgłoszeniowa ....................................................................................635
                Zakleszczenie ..................................................................................................................641
                Podsumowanie ................................................................................................................647
                Ćwiczenia ........................................................................................................................649

Dodatki .......................................................................................653
Dodatek A Zalecana lektura ........................................................................... 655
                Język C++........................................................................................................................655
                    Ksią ki Bruce’a Eckela.............................................................................................656
                    Ksią ki Chucka Allisona...........................................................................................657
                Zaawansowane omówienia języka C++..........................................................................658
                Ksią ki o wzorcach projektowych ..................................................................................660
Dodatek B Uzupełnienie .................................................................................. 661
                Skorowidz...................................................................................... 667
Rozdział 5.
Wszystko o szablonach
           Szablony C++ to zdecydowanie więcej ni „kontenery zmiennych typu T”. Wpraw-
           dzie początkowo chodziło o stworzenie bezpiecznych ze względu na typy, ogólnych
           kontenerów, ale we współczesnym C++ szablony słu ą te do generowania specjali-
           zowanego kodu i optymalizowania wykonania programu ju na etapie kompilacji po-
           przez u ycie specyficznych konstrukcji programistycznych.

           W niniejszym rozdziale Czytelnik będzie mógł się praktycznie zapoznać z mo liwo-
           ściami (i pułapkami) programowania za pomocą szablonów C++. Obszerniejszą
           analizę odpowiednich zagadnień języka oraz pułapek znaleźć mo na w doskonałej ksią ce
           Davida Vandevoorde’a i Nico Josuttisa1.



Parametry szablonów
           Jak ju powiedzieliśmy w pierwszym tomie, szablony mają dwie odmiany i występują
           jako: szablony funkcji i szablony klas. Jedne i drugie są w całości opisane swoimi pa-
           rametrami. Ka dy parametr szablonu sam mo e być:
             1. Typem (wbudowanym lub zdefiniowanym przez u ytkownika).
             2. Stałą w chwili kompilacji (na przykład liczby całkowite, wskaźniki i referencje
                danych statycznych; często określa się takie stałe jako parametry niebędące typami).
             3. Innym szablonem.

           Wszystkie przykłady z pierwszego tomu nale ą do pierwszej kategorii i takie parametry
           występują najczęściej. Klasycznym przykładem prostego szablonu będącego kontenerem
           jest klasa Stack (Stos). Jako kontener obiekt Stack nie dba o to, jakiego typu obiekty
           zawiera; sposób przechowywania tych obiektów nie zmienia się zale nie od ich typu.
           Z tego powodu mo na u yć parametru będącego typem do opisania typu obiektów prze-
           chowywanych na stosie:

1
    Vandevoorde i Josuttis, C++. Szablony. Vademecum profesjonalisty, Helion, 2003.
188                                                Część II ♦ Standardowa biblioteka C++


        VGORNCVGENCUU 6 ENCUU 5VCEM ]
          6
FCVC
          UKGAV EQWPV
        RWDNKE
          XQKF RWUJ
EQPUV 6 V
           KVF
        _

      Konkretny typ, który w danym stosie ma być u yty, podaje się jako argument odpo-
      wiadający parametrowi T:
        5VCEMKPV O[5VCEM  UVQU NKED EC MQYKV[EJ KPV

      Kompilator u ywa obiektu Stack dostosowanego do typu int przez podstawienie int
      pod T i wygenerowanie odpowiedniego kodu. Nazwa instancji klasy wygenerowanej
      na podstawie tego szablonu to Stackint.


Parametry szablonów niebędące typami
      Mo na te u ywać parametrów szablonów niebędących typami, o ile tylko odpowiadają
      one liczbom całkowitym znanym na etapie kompilacji. Mo na, na przykład, stworzyć stos
      o ustalonej wielkości, przekazując parametr niebędący typem, odpowiadający wielkości
      tablicy u ytej do implementacji tego stosu:
        VGORNCVGENCUU 6 UKGAV 0
        ENCUU 5VCEM ]
          6 FCVC=0?  0 VQ WUVCNQPC RQLGOPQ è
          UKGAV EQWPV
        RWDNKE
          XQKF RWUJ
EQPUV 6 V
           KVF
        _

      Podczas tworzenia instancji takiego szablonu musisz podać wartość stałą znaną pod-
      czas kompilacji, która będzie u yta jako wartość parametru N:
        5VCEMKPV  O[(KZGF5VCEM

      Wartość N jest znana ju na etapie kompilacji, więc tablica data mo e zostać umiesz-
      czona na stosie, a nie w pamięci wymagającej alokowania, co mo e przyspieszyć
      działanie programu dzięki uniknięciu opóźnień związanych z dynamiczną alokacją
      pamięci. Zgodnie z przedstawioną wcześniej zasadą, nazwą uzyskanej w ten sposób
      klasy będzie Stackint, 100. Oznacza to, e ka da kolejna wartość N powoduje
      utworzenie innego typu klasy. Na przykład klasa Stackint, 99 to klasa inna ni
      Stackint, 100.

      Szablon klasy bitset, szczegółowo omawiany w rozdziale 7., to jedyna klasa standar-
      dowej biblioteki C++, w której u ywany jest parametr szablonu niebędący typem; pa-
      rametr ten określa liczbę bitów, jakie mo e przechowywać obiekt bitset. Poni szy
      przykładowy generator liczb losowych u ywa obiektu bitset do śledzenia liczb tak,
      aby wszystkie liczby w danym zakresie były zwracane w losowej kolejności bez po-
      wtórzeń tak długo, a u yte zostaną wszystkie liczby. Poni szy przykład pokazuje
      tak e przecią enie funkcji operator() w celu uzyskania składni podobnej do wywoła-
      nia funkcji:
Rozdział 5. ♦ Wszystko o szablonach                                                     189


           %7TCPFJ
          ]DQT_
           .QUQYG IGPGTQYCPKG NKED DG RQYVÎTG
           KHPFGH 74#0A*
           FGHKPG 74#0A*
           KPENWFG DKVUGV
           KPENWFG EUVFFGH
           KPENWFG EUVFNKD
           KPENWFG EVKOG
          WUKPI UVFUKGAV
          WUKPI UVFDKVUGV

          VGORNCVGUKGAV 7RRGT$QWPF
          ENCUU 7TCPF ]
            DKVUGV7RRGT$QWPF WUGF
          RWDNKE
            7TCPF
 ]
              UTCPF
VKOG
  .QUQYQ
            _
            UKGAV QRGTCVQT

  (WPMELC IGPGTCVQT
          _

          VGORNCVGUKGAV 7RRGT$QWPF
          KPNKPG UKGAV 7TCPF7RRGT$QWPF QRGTCVQT

 ]
            KH
WUGFEQWPV
  7RRGT$QWPF
              WUGFTGUGV
  K QF PQYC 
Y[E[ è DKVUGV
            UKGAV PGYXCN
            YJKNG
WUGF=PGYXCN  TCPF
 7RRGT$QWPF?
                C FQ PCNGKGPKC PKGRQYVCTCNPGL YCTVQ EK
            WUGF=PGYXCN?  VTWG
            TGVWTP PGYXCN
          _
           GPFKH  74#0A* `

       Niepowtarzalność w klasie Urand uzyskujemy dzięki śledzeniu w zbiorze bitset
       wszystkich liczb, jakie występują w zakresie (górne ograniczenie tego zakresu poda-
       wane jest jako argument szablonu) i rejestrując u ycie ka dej liczby przez ustawienie
       odpowiedniego bitu w strukturze used. Kiedy wszystkie liczby zostaną u yte, zbiór
       bitset jest czyszczony i losowanie odbywa się od nowa. Oto prosty przykład u ycia
       obiektu Urand:
           %7TCPF6GUVERR
          ]DQT_
           KPENWFG KQUVTGCO
           KPENWFG 7TCPFJ
          WUKPI PCOGURCEG UVF

          KPV OCKP
 ]
            7TCPF W
            HQT
KPV K   K   

K
              EQWV  W
     
          _ `

       Jak jeszcze powiemy dalej, argumenty szablonów niebędące typami są wa ne w przypadku
       optymalizowania obliczeń numerycznych.
190                                                  Część II ♦ Standardowa biblioteka C++


Domyślne argumenty szablonów
      Parametrom szablonu klasy mo na przypisać argumenty domyślne (niedopuszczalne
      jest ich stosowanie w przypadku szablonów funkcji). Tak jak w przypadku argumen-
      tów domyślnych funkcji powinno się je definiować tylko raz, w pierwszej deklaracji
      lub definicji widzianej przez kompilator. Kiedy jakiś argument domyślny zostanie ju
      zdefiniowany, wszystkie dalsze szablony te muszą mieć wartości domyślne. Aby
      pokazana powy ej klasa stosu o ustalonej wielkości była łatwiejsza w u yciu, mo na
      dodać do niej argument domyślny:
        VGORNCVGENCUU 6 UKGAV 0  
        ENCUU 5VCEM ]
          6 FCVC=0?  0 VQ WUVCNQPC RQLGOPQ è
          UKGAV EQWPV
        RWDNKE
          XQKF RWUJ
EQPUV 6 V
           KVF
        _

      Teraz, jeśli podczas deklarowania obiektu Stack pominięty zostanie drugi argument
      szablonu, wartość N domyślnie będzie równa 100.

      Mo na te podać wartości domyślne dla wszystkich argumentów, ale wtedy i tak podczas
      deklarowania instancji szablonu trzeba będzie u yć pustej pary nawiasów, aby kompilator
      „wiedział”, e chodzi o szablon klasy:
        VGORNCVGENCUU 6  KPV UKGAV 0    QDC CTIWOGPV[ FQO[ NPG
        ENCUU 5VCEM ]
          6 FCVC=0?  0 VQ WUVCNQPC RQLGOPQ è
          UKGAV EQWPV
        RWDNKE
          XQKF RWUJ
EQPUV 6 V
           KVF
        _

        5VCEM O[5VCEM  TÎYPQYC PG 5VCEMKPV 

      Argumenty domyślne są intensywnie wykorzystywane w standardowej bibliotece C++.
      Przykładowo szablon klasy vector zadeklarowany został następująco:
        VGORNCVG ENCUU 6 ENCUU #NNQECVQT  CNNQECVQT6
        ENCUU XGEVQT

      Zwróć uwagę na spację między dwoma zamykającymi nawiasami kątowymi. Dzięki niej
      kompilator nie zinterpretuje tych dwóch znaków () jako operatora przesunięcia w prawo.

      Z powy szej deklaracji wynika, e szablon vector tak naprawdę ma dwa argumenty: typ
      przechowywanych obiektów oraz typ odpowiadający alokatorowi u ywanemu w wektorze
      (więcej o alokatorach powiemy w rozdziale 7.) Jeśli drugi argument zostanie pominięty,
      u yty zostanie standardowy szablon allocator sparametryzowany pierwszym parametrem
      szablonu. Z deklaracji wynika te , e w kolejnych parametrach szablonów mo na u ywać
      parametrów poprzednich — tutaj tak u yto parametru T.
Rozdział 5. ♦ Wszystko o szablonach                                                    191


       Wprawdzie w szablonach funkcji nie mo na u ywać domyślnych argumentów sza-
       blonu, ale parametrów szablonów mo na u ywać jako argumentów domyślnych zwy-
       kłych funkcji. Poni szy szablon funkcji sumuje elementy sekwencji:
           %(WPEGHERR
           KPENWFG KQUVTGCO
          WUKPI PCOGURCEG UVF

          VGORNCVGENCUU 6
          6 UWO
6
D 6
G 6 KPKV  6
 ]
            YJKNG
D  G
              KPKV
D


            TGVWTP KPKV
          _

          KPV OCKP
 ]
            KPV C=?  ]_
            EQWV  UWO
C C 
 UKGQH C  UKGQH C=?  GPFN  
          _ `

       Trzeci argument sum() jest wartością początkową dla sumy elementów. Argument ten jest
       pominięty, więc domyślnie wynosi T(); w przypadku typu int i innych typów wbudowa-
       nych pseudokonstruktor realizuje inicjalizację zerem.


Szablony jako parametry szablonów
       Trzeci rodzaj parametrów, jakich mo na u yć w szablonie, to inny szablon klasy. Mo e
       to wydawać się dziwne, gdy szablony są typami, a parametry będące typami są dozwolo-
       ne; jeśli jednak w kodzie szablonu jako parametr ma być u yty inny szablon, kompi-
       lator musi najpierw „wiedzieć”, e parametrem jest właśnie szablon. Poni szy przy-
       kład pokazuje u ycie szablonu jako parametru innego szablonu:
           %6GOR6GORERR
           2QMCWLG W [EKG UCDNQPW LCMQ RCTCOGVTW UCDNQPW
           KPENWFG EUVFFGH
           KPENWFG KQUVTGCO
          WUKPI PCOGURCEG UVF

          VGORNCVGENCUU 6
          ENCUU #TTC[ ]  Y[M [ EKæI FCLæE[ UKú RTGF W Cè
            GPWO ]+0+6  _
            6
FCVC
            UKGAV ECRCEKV[
            UKGAV EQWPV
          RWDNKE
            #TTC[
 ]
              EQWPV  
              FCVC  PGY 6=ECRCEKV[  +0+6?
            _
            `#TTC[
 ] FGNGVG =? FCVC _
            XQKF RWUJADCEM
EQPUV 6 V ]
              KH
EQWPV  ECRCEKV[ ]
                 2QYKúMUGPKG VCDNKE[ DCQYGL
                UKGAV PGY%CR
ECRCEKV[
192                                                  Część II ♦ Standardowa biblioteka C++


              6
PGYCVC  PGY 6=PGY%CR?
              HQT 
UKGAV K   K  EQWPV 

K
                PGYCVC=K?  FCVC=K?
              FGNGVG FCVC
              FCVC  PGYCVC
              ECRCEKV[  PGY%CR
            _
            FCVC=EQWPV

?  V
          _
          XQKF RQRADCEM
 ]
            KH
EQWPV 
              EQWPV
          _
          6
DGIKP
 ]
            TGVWTP FCVC
          _
          6
GPF
 ]
            TGVWTP FCVC 
 EQWPV
          _
        _

        VGORNCVGENCUU 6 VGORNCVGENCUU ENCUU 5GS
        ENCUU %QPVCKPGT ]
          5GS6 UGS
        RWDNKE
          XQKF CRRGPF
EQPUV 6 V ]
            UGSRWUJADCEM
V
          _
          6
DGIKP
 ]
            TGVWTP UGSDGIKP

          _
          6
GPF
 ]
            TGVWTP UGSGPF

          _
        _

        KPV OCKP
 ]
          %QPVCKPGTKPV #TTC[ EQPVCKPGT
          EQPVCKPGTCRRGPF

          EQPVCKPGTCRRGPF

          KPV
R  EQPVCKPGTDGIKP

          YJKNG
R  EQPVCKPGTGPF

            EQWV
R

  GPFN
        _ `

      Szablon klasy Array to najzwyklejszy kontener zawierający sekwencję elementów.
      Szablon Container ma dwa parametry: typ przechowywanych obiektów oraz struktu-
      rę danych słu ącą do przechowywania danych. Poni szy wiersz implementacji klasy
      Container wymusza poinformowanie kompilatora, e parametr Seq jest szablonem:
        5GS6 UGS

      Gdybyśmy nie zadeklarowali Seq jako parametru będącego szablonem, kompilator zgłosi
      błąd, twerdząc, e Seq nie jest szablonem, a jako takiego go u ywamy. W funkcji main()
      tworzona jest instancja szablonu Container w ten sposób, w klasie Array przecho-
      wywane były liczby całkowite — zatem w tym przykładzie Seq oznacza Array.
Rozdział 5. ♦ Wszystko o szablonach                                                   193


       Zauwa , e w tym wypadku nie jest konieczne nazywanie parametru Seq w deklaracji
       Container. Odpowiedni wiersz to:
          VGORNCVGENCUU 6 VGORNCVGENCUU ENCUU 5GS

       Wprawdzie moglibyśmy zapisać:
          VGORNCVGENCUU 6 VGORNCVGENCUU 7 ENCUU 5GS

       lecz parametr U nie jest w ogóle potrzebny. Wszystko, co istotne, to to, e Seq jest
       szablonem klasy mającym pojedynczy parametr będący typem. Jest to analogia do
       pomijania nazw parametrów funkcji, kiedy nie są potrzebne, na przykład przy prze-
       cią aniu operatora postinkrementacji:
          6 QRGTCVQT

KPV

       Słowo kluczowe int jest potrzebne jedynie ze względów formalnych, więc odpowia-
       dający mu argument nie musi mieć nazwy.

       Poni szy program korzysta z tablicy o ustalonej wielkości mającej dodatkowy para-
       metr szablonu odpowiadający wielkości tej tablicy:
           %6GOR6GORERR
           9KGNQOKGPP[ UCDNQP LCMQ RCTCOGVT UCDNQPW
           KPENWFG EUVFFGH
           KPENWFG KQUVTGCO
          WUKPI PCOGURCEG UVF

          VGORNCVGENCUU 6 UKGAV 0
          ENCUU #TTC[ ]
            6 FCVC=0?
            UKGAV EQWPV
          RWDNKE
            #TTC[
 ] EQWPV   _
            XQKF RWUJADCEM
EQPUV 6 V ]
              KH
EQWPV  0
                FCVC=EQWPV

?  V
            _
            XQKF RQRADCEM
 ]
              KH
EQWPV 
                EQWPV
            _
            6
DGIKP
 ] TGVWTP FCVC _
            6
GPF
 ] TGVWTP FCVC 
 EQWPV _
          _

          VGORNCVGENCUU 6UKGAV 0VGORNCVGENCUUUKGAV ENCUU 5GS
          ENCUU %QPVCKPGT ]
            5GS60 UGS
          RWDNKE
            XQKF CRRGPF
EQPUV 6 V ] UGSRWUJADCEM
V _
            6
DGIKP
 ] TGVWTP UGSDGIKP
 _
            6
GPF
 ] TGVWTP UGSGPF
 _
          _

          KPV OCKP
 ]
            EQPUV UKGAV 0  
            %QPVCKPGTKPV 0 #TTC[ EQPVCKPGT
194                                                Część II ♦ Standardowa biblioteka C++


          EQPVCKPGTCRRGPF

          EQPVCKPGTCRRGPF

          KPV
R  EQPVCKPGTDGIKP

          YJKNG
R  EQPVCKPGTGPF

            EQWV
R

  GPFN
        _ `

      Znowu nazwy parametrów w deklaracji Seq wewnątrz deklaracji Containter są zbędne,
      ale potrzebne są dwa dodatkowe parametry do zadeklarowania pola seq, stąd na najwy -
      szym poziomie pojawia się parametr N niebędący typem.

      Łączenie argumentów domyślnych z parametrami szablonów będących szablonami jest
      nieco bardziej problematyczne. Kiedy kompilator sprawdza parametr wewnętrzny
      parametru szablonu, nie są uwzględniane argumenty domyślne, wobec czego w celu
      uzyskania dokładnego dopasowania konieczne jest powtórzenie wartości domyślnych.
      Poni szy przykład wykorzystuje argument domyślny do szablonu Array o stałej wielko-
      ści, pokazuje te , jak sobie z tym dziwactwem języka radzić:
         %6GOR6GORERR
        ]DQT_
        ]OUE_
         æEGPKG RCTCOGVTÎY UCDNQPÎY DúFæE[EJ UCDNQPCOK
          CTIWOGPVCOK FQO[ NP[OK
         KPENWFG EUVFFGH
         KPENWFG KQUVTGCO
        WUKPI PCOGURCEG UVF

        VGORNCVGENCUU 6 UKGAV 0    #TIWOGPV FQO[ NP[
        ENCUU #TTC[ ]
          6 FCVC=0?
          UKGAV EQWPV
        RWDNKE
          #TTC[
 ] EQWPV   _
          XQKF RWUJADCEM
EQPUV 6 V ]
            KH
EQWPV  0
              FCVC=EQWPV

?  V
          _
          XQKF RQRADCEM
 ]
            KH
EQWPV 
              EQWPV
          _
          6
DGIKP
 ] TGVWTP FCVC _
          6
GPF
 ] TGVWTP FCVC 
 EQWPV _
        _

        VGORNCVGENCUU 6 VGORNCVGENCUU UKGAV   ENCUU 5GS
        ENCUU %QPVCKPGT ]
          5GS6 UGS  7 [VQ CTIWOGPVW FQO[ NPGIQ
        RWDNKE
          XQKF CRRGPF
EQPUV 6 V ] UGSRWUJADCEM
V _
          6
DGIKP
 ] TGVWTP UGSDGIKP
 _
          6
GPF
 ] TGVWTP UGSGPF
 _
        _

        KPV OCKP
 ]
          %QPVCKPGTKPV #TTC[ EQPVCKPGT
          EQPVCKPGTCRRGPF
Rozdział 5. ♦ Wszystko o szablonach                                                     195


            EQPVCKPGTCRRGPF

            KPV
R  EQPVCKPGTDGIKP

            YJKNG
R  EQPVCKPGTGPF

              EQWV
R

  GPFN
          _ `

       W poni szym wierszu trzeba włączyć domyślną wielkość równą 10:
          VGORNCVGENCUU 6 VGORNCVGENCUU UKGAV   ENCUU 5GS

       Obie definicje, seq w Container i container, w main() wykorzystują wartości do-
       myślne. Jedynym sposobem u ycia czegokolwiek innego ni wartość domyślna jest sko-
       rzystanie z metody z poprzedniego programu, TempTemp2.cpp. Jest to jedyny wyją-
       tek od podanej wcześniej zasady mówiącej, e argumenty domyślne powinny pojawiać
       się w danej jednostce kompilacji tylko raz.

       Wobec faktu, e wszystkie standardowe kontenery przechowujące elementy w formie
       sekwencji (vector, list oraz deque omówiono dokładnie w rozdziale 7.) mają domyślny
       argument allocator, powy sza technika jest przydatna, jeśli trzeba jedną z tych trzech
       metod uporządkowania przekazać jako parametr szablonu. W poni szym programie
       vector i list są przekazywane do dwóch instancji szablonu Container.
           %6GOR6GORERR
          ]DQT_
          ]OUE_
           2TGMCCPKG UVCPFCTFQY[EJ UGMYGPELK LCMQ CTIWOGPVÎY UCDNQPW
           KPENWFG KQUVTGCO
           KPENWFG NKUV
           KPENWFG OGOQT[  GMNCTCELC CNNQECVQT6
           KPENWFG XGEVQT
          WUKPI PCOGURCEG UVF

          VGORNCVGENCUU 6 VGORNCVGENCUU 7 ENCUU  CNNQECVQT7
                              ENCUU 5GS
          ENCUU %QPVCKPGT ]
            5GS6 UGS  0KGLCYPKG UVQUQYCPG LGUV FQO[ NPG CNNQECVQT6
          RWDNKE
            XQKF RWUJADCEM
EQPUV 6 V ] UGSRWUJADCEM
V _
            V[RGPCOG 5GS6 KVGTCVQT DGIKP
 ] TGVWTP UGSDGIKP
 _
            V[RGPCOG 5GS6 KVGTCVQT GPF
 ] TGVWTP UGSGPF
 _
          _

          KPV OCKP
 ]
             7 [L YGMVQTC
            %QPVCKPGTKPV XGEVQT X%QPVCKPGT
            X%QPVCKPGTRWUJADCEM

            X%QPVCKPGTRWUJADCEM

            HQT
XGEVQTKPV KVGTCVQT R  X%QPVCKPGTDGIKP

                R  X%QPVCKPGTGPF
 

R ]
              EQWV
R  GPFN
            _
             7 [L NKUV[
            %QPVCKPGTKPV NKUV N%QPVCKPGT
            N%QPVCKPGTRWUJADCEM

            N%QPVCKPGTRWUJADCEM
196                                                  Część II ♦ Standardowa biblioteka C++


          HQT
NKUVKPV KVGTCVQT R  N%QPVCKPGTDGIKP

              R  N%QPVCKPGTGPF
 

R ]
            EQWV
R  GPFN
          _
        _ `

      W tym wypadku nazwaliśmy pierwszy parametr szablonu wewnętrznego Seq (ta na-
      zwa to U), gdy alokatory w standardowych sekwencjach muszą być sparametryzo-
      wane tym samym typem, co obiekt ich u ywający. Poza tym, skoro domyślna wartość
      parametru allocator jest znana, mo emy ją pominąć w dalszych odwołaniach do SeqT,
      jak w poprzednim programie. Jednak dokładne omówienie tego przykładu wymaga
      objaśnienia znaczenia słowa kluczowego typename.


Słowo kluczowe typename
      Niech będzie dany program:
         %6[RGPCOGF+ERR
        ]DQT_
         5 QYQ V[RGPCOG W [YCPG LGUV LCMQ RTGHKMU V[RÎY CIPKG F QP[EJ

        VGORNCVGENCUU 6 ENCUU : ]
           )F[D[ PKG D[ Q V[RGPCOG RQYUVC D[ VW D æF
          V[RGPCOG 6KF K
        RWDNKE
          XQKF H
 ] KI
 _
        _

        ENCUU ; ]
        RWDNKE
          ENCUU KF ]
          RWDNKE
            XQKF I
 ]_
          _
        _

        KPV OCKP
 ]
          :; Z[
          Z[H

        _ `

      W definicji szablonu zakłada się, e klasa T musi mieć pewnego rodzaju zagnie d ony
      identyfikator id. Jednak id mo e być te statycznym polem T (a wtedy mo na byłoby
      na id wykonywać operacje bezpośrednio), natomiast nie mo na „tworzyć obiektu typu id”.
      Jednak właśnie to się tu dzieje — identyfikator id jest traktowany tak, jakby był typem
      zagnie d onym w T. W przypadku klasy Y id jest faktycznie typem zagnie d onym,
      ale bez słowa kluczowego typename kompilator nie wiedziałby o tym w chwili kompi-
      lowania X.

      Jeśli kompilator umo liwia traktowanie identyfikatora występującego w szablonie jako
      typu lub jako czegoś innego ni typ, przyjmie, e identyfikator jest czymś innym ni
      typ, czyli zało y, e identyfikator odnosi się do obiektu (przy czym dane typów pro-
      stych te są traktowane jako obiekty), wyliczenia lub czegoś podobnego. Jednak kompilator
      nie zało y, i nie mo e zało yć, e jest to typ.
Rozdział 5. ♦ Wszystko o szablonach                                                     197


       Wobec tego, e domyślne działanie kompilatora powoduje, e we wskazanych wy ej
       dwóch miejscach nie chodzi o typ, trzeba u yć słowa kluczowego typename dla nazw
       zagnie d onych (wyjątkiem są listy inicjalizujące konstruktora, gdzie nie jest to ani
       potrzebne, ani dozwolone). W powy szym przykładzie kompilator widząc typename
       T::id, „wie” (dzięki słowu kluczowemu typename), e id odnosi się do typu zagnie d o-
       nego, więc mo e stworzyć obiekt tego typu.

       Cała ta zasada w formie skróconej brzmi: jeśli typ odnoszący się do kodu wewnątrz
       szablonu jest kwalifikowany parametrem szablonu będącym typem, powinien być po-
       przedzony słowem kluczowym typename, chyba e występuje w specyfikacji klasy
       bazowej lub na liście inicjalizacyjnej w tym samym zakresie (w obu tych przypadkach
       słowa tego nie mo na u yć).

       Powy sza dyskusja całkowicie objaśnia u ycie słowa kluczowego typename w pro-
       gramie TempTemp4.cpp. Bez tego słowa kluczowego kompilator zało yłby, e wy-
       ra enie SeqT::iterator nie jest typem, podczas gdy dalej u ywane jest ono do zde-
       finiowania wartości zwracanej przez funkcje begin() i end().

       W następnym przykładzie, zawierającym szablon funkcji pozwalający wydrukować
       dowolną standardową sekwencję C++, pokazano podobny sposób u ycia typename:
           %2TKPV5GSERR
          ]OUE_
           (WPMELC FTWMWLæEC V[RQYG UGMYGPELG %

           KPENWFG KQUVTGCO
           KPENWFG NKUV
           KPENWFG OGOQT[
           KPENWFG XGEVQT
          WUKPI PCOGURCEG UVF

          VGORNCVGENCUU 6 VGORNCVGENCUU 7 ENCUU  CNNQECVQT7
                            ENCUU 5GS
          XQKF RTKPV5GS
5GS6 UGS ]
            HQT 
V[RGPCOG 5GS6 KVGTCVQT D  UGSDGIKP

                 D  UGSGPF

              EQWV
D

  GPFN
          _

          KPV OCKP
 ]
             2TGVYCTCPKG YGMVQTC
            XGEVQTKPV X
            XRWUJADCEM

            XRWUJADCEM

            RTKPV5GS
X
             2TGVYCTCPKG NKUV[
            NKUVKPV NUV
            NUVRWUJADCEM

            NUVRWUJADCEM

            RTKPV5GS
NUV
          _ `

       Znowu, gdyby nie słowo kluczowe typename, kompilator zinterpretowałby iterator
       jako statyczne pole nale ące do SeqT, czyli byłby to błąd składniowy — przecie
       typ jest wymagany.
198                                                  Część II ♦ Standardowa biblioteka C++


Typedef i typename
      Nie wolno zakładać, e słowo kluczowe typename utworzy nową nazwę typu. Celem
      stosowania tego słowa jest wskazanie kompilatorowi, e tak zakwalifikowany identy-
      fikator ma być zinterpretowany jako typ. Wiersz:
        V[RGPCOG 5GS6 KVGTCVQT +V

      mówi, e zmienna It jest zmienną typu SeqT::iterator. Jeśli nale ałoby stworzyć
      nazwę nowego typu, jak zwykle trzeba u yć typedef:
        V[RGFGH V[RGPCOG 5GS+V KVGTCVQT +V


Użycie typename zamiast class
      Innym zastosowaniem słowa kluczowego typename jest mo liwość u ycia typename
      zamiast class na liście argumentów szablonu. Czasami powstający kod jest dzięki temu
      czytelniejszy:
         %7UKPI6[RGPCOGERR
         7 [EKG V[RGPCOG PC NK EKG CTIWOGPVÎY UCDNQPW

        VGORNCVGV[RGPCOG 6 ENCUU : ] _

        KPV OCKP
 ]
          :KPV Z
        _ `

      Prawdopodobnie nieczęsto spotkasz się z takim u yciem słowa kluczowego typename,
      gdy słowo to zostało dodane do języka dość długo po zdefiniowaniu szablonów.


Użycie słowa kluczowego template jako wskazówki
      Tak jak słowo kluczowe typename pomaga kompilatorowi w sytuacjach, kiedy nie
      spodziewa się on identyfikatora typu, istnieje te potencjalna trudność związana z lekse-
      mami niebędącymi identyfikatorami, jak znaki  i ; czasami oznaczają one symbole
      mniejszości i większości, a czasami ograniczają listy parametrów szablonu. W ramach
      przykładu skorzystajmy jeszcze raz z klasy bitset:
         %QV6GORNCVGERR
         2QMCWLG W [EKG MQPUVTWMELK VGORNCVG
         KPENWFG DKVUGV
         KPENWFG EUVFFGH
         KPENWFG KQUVTGCO
         KPENWFG UVTKPI
        WUKPI PCOGURCEG UVF

        VGORNCVGENCUU EJCT6 UKGAV 0
        DCUKEAUVTKPIEJCT6 DKVUGV6Q5VTKPI
EQPUV DKVUGV0 DU ]
          TGVWTP DU VGORNCVG VQAUVTKPIEJCT6 EJCTAVTCKVUEJCT6 
                                        CNNQECVQTEJCT6 

        _
Rozdział 5. ♦ Wszystko o szablonach                                                                 199


              KPV OCKP
 ]
                DKVUGV DU
                DUUGV

                DUUGV

                EQWV  DU  GPFN  
                UVTKPI U  DKVUGV6Q5VTKPIEJCT 
DU
                EQWV  U  GPFN  
              _ `

           Klasa bitset realizuje konwersję na obiekt-łańcuch za pomocą funkcji składowej to_st-
           ring. Aby obsłu yć ró ne klasy łańcuchów, to_string sama jest szablonem, zgodnie
           z definicją szablonu basic_string omawianą w rozdziale 3. Deklaracja to_string w ramach
           bitset wygląda następująco:
              VGORNCVG ENCUU EJCT6 ENCUU VTCKVU ENCUU #NNQECVQT
              DCUKEAUVTKPIEJCT6 VTCKVU #NNQECVQT VQAUVTKPI
 EQPUV

           Nasz pokazany powy szej szablon funkcji bitsetToString() pozwala zwracać obiekty
           bitset jako ró nego rodzaju łańcuchy znaków. Aby uzyskać, na przykład, łańcuch z szero-
           kimi znakami, nale y wywołanie zapisać następująco:
              YUVTKPI U  DKVUGV6Q5VTKPIYEJCTAV 
DU

           Zauwa , e basic_string korzysta z domyślnych argumentów szablonu, więc nie mu-
           simy powtarzać argumentów char_traits i allocator w wartości zwracanej. Niestety,
           bitset::to_string nie u ywa argumentów domyślnych. U ycie bitsetToStringchar(bs)
           jest wygodniejsze ni pisanie za ka dym razem całego bs.template to_stringchar,
           char_traits, allocatorchar ().

           Instrukcja return w funkcji bitsetToString() zawiera słowo kluczowe template w dość
           dziwnym miejscu — zaraz po operatorze „kropka” zastosowanym do obiektu bs typu
           bitset. Wynika to stąd, e kiedy analizowany jest szablon, znak  znajdujący się za
           napisem to_string zostałby interpretowany jako operator mniejszości, a nie początek
           lub lista argumentów szablonu. W punkcie „Odszukiwanie nazw” w dalszej części roz-
           działu słowo kluczowe template u yte w tym kontekście informuje kompilator, e dalej
           następuje nazwa szablonu; dzięki temu znak  zostanie zinterpretowany prawidłowo.
           Takie samo rozumowanie dotyczy operatorów - i :: stosowanych do szablonów. Tak
           jak w przypadku słowa kluczowego template opisana technika unikania wieloznaczności
           mo e być u ywana jedynie w szablonach2.


Szablony składowe
           Szablon funkcji bitset::to_string() jest przykładem szablonu składowego czyli szablonu
           zadeklarowanego w innej klasie lub szablonie klasy. Dzięki temu mo na tworzyć rozmaite
           kombinacje niezale nych argumentów szablonów. Praktyczny przykład znaleźć mo na
           w szablonie klas complex w standardowej bibliotece C++. Szablon complex ma pa-
           rametr będący typem, który pozwala zadeklarować typ zmiennoprzecinkowy słu ący

2
    Komitet standaryzacyjny C++ rozwa a rezygnację z klauzuli „jedynie w szablonach”, jeśli chodzi
    o unikanie wieloznaczności. Niektóre kompilatory ju teraz pozwalają na stosowanie takich podpowiedzi
    poza szablonami.
200                                                 Część II ♦ Standardowa biblioteka C++


      do przechowywania części rzeczywistej i urojonej liczby zespolonej. Poni szy frag-
      ment kodu z biblioteki standardowej pokazuje konstruktor szablonu składowego sza-
      blonu klasy complex:
        VGORNCVGV[RGPCOG 6
        ENCUU EQORNGZ ]
        RWDNKE
          VGORNCVGENCUU : EQORNGZ
EQPUV EQORNGZ: 

      Standardowy szablon complex ma ju gotowe specjalizacje z parametrem T o warto-
      ściach float, double oraz long double. Pokazany powy ej konstruktor szablonu skła-
      dowego pozwala stworzyć nową liczbę zespoloną wykorzystującą inny typ zmienno-
      przecinkowy jako typ bazowy, jak poni ej:
        EQORNGZHNQCV 
 
        EQORNGZFQWDNG Y


      W deklaracji w parametr T szablonu complex ma wartość double, zaś X to float.
      Szablony składowe bardzo ułatwiają tego typu konwersje.

      Wobec tego, e definiowanie szablonu w szablonie jest operacją zagnie d enia,
      przedrostki oznaczające szablony muszą to zagnie d anie odzwierciedlać, jeśli tylko
      szablon składowy zostanie zdefiniowany poza definicją klasy zewnętrznej. Jeśli, na
      przykład, mamy zaimplementować szablon klasy complex i nale y zdefiniować kon-
      struktor szablonu składowego poza definicją klasy opartej na szablonie complex, trzeba
      byłoby zrobić to tak:
        VGORNCVGV[RGPCOG 6
        VGORNCVGV[RGPCOG :
        EQORNGZ6 EQORNGZ
EQPUV EQORNGZ:   E ]
VWVCL VTG è
_

      Inne zastosowanie szablonów funkcji składowych w bibliotece standardowej to ini-
      cjalizacja kontenerów takich jak vector. Załó my, e mamy vector zawierający dane
      typu int i chcemy tym wektorem zainicjalizować nowy wektor z liczbami double:
        KPV FCVC=?  ]    _
        XGEVQTKPV X
FCVC FCVC

        XGEVQTFQWDNG X
XDGIKP
 XGPF


      O ile tylko elementy v1 są zgodne co do przypisania z elementami v2 (a double i int
      w tym sensie są zgodne), wszystko działa prawidłowo. Szablon klasy vector ma na-
      stępujący konstruktor szablonu składowego:
        VGORNCVGENCUU +PRWV+VGTCVQT
        XGEVQT
+PRWV+VGTCVQT HKTUV +PRWV+VGTCVQT NCUV
            EQPUV #NNQECVQT  #NNQECVQT


      Taka konstrukcja tak naprawdę w deklaracjach wektora jest u yta dwukrotnie. Kiedy
      v1 jest inicjalizowane na podstawie tablicy liczb int, InputIterator jest typu int*.
      Kiedy v2 jest inicjalizowane na podstawie v1, InputIterator w instancji konstruktora
      szablonu składowego jest typu vectorint::iterator.

      Szablony składowe mogą być tak e klasami (nie muszą być funkcjami, choć zwykle
      to właśnie jest potrzebne). W następnym przykładzie pokazano szablon klasy składowej
      znajdujący się wewnątrz szablonu klasy zewnętrznej:
Rozdział 5. ♦ Wszystko o szablonach                                                       201


           %/GODGT%NCUUERR
           5CDNQP MNCU[ UM CFQYGL
           KPENWFG KQUVTGCO
           KPENWFG V[RGKPHQ
          WUKPI PCOGURCEG UVF

          VGORNCVGENCUU 6
          ENCUU 1WVGT ]
          RWDNKE
            VGORNCVGENCUU 4
            ENCUU +PPGT ]
            RWDNKE
              XQKF H

            _
          _

          VGORNCVGENCUU 6 VGORNCVG ENCUU 4
          XQKF 1WVGT6 +PPGT4 H
 ]
            EQWV  1WVGT   V[RGKF
6PCOG
  GPFN
            EQWV  +PPGT   V[RGKF
4PCOG
  GPFN
            EQWV  2G PC +PPGT   V[RGKF
VJKUPCOG
  GPFN
          _

          KPV OCKP
 ]
            1WVGTKPV +PPGTDQQN KPPGT
            KPPGTH

          _ `

       Omawiany w rozdziale 8. operator typeid zwraca obiekt, którego funkcja składowa
       name() podaje zapisany jako łańcuch jego typ lub typ zmiennej. Wprawdzie dokładna
       postać tego łańcucha jest ró na w ró nych kompilatorach, ale wynik działania powy -
       szego programu będzie podobny do:
          1WVGT  KPV
          +PPGT  DQQN
          2G PC +PPGT  1WVGTKPV +PPGTDQQN

       Deklaracja zmiennej inner w programie głównym powoduje ukonkretnienie Innerbool
       i Outerint.

       Szablony funkcji składowych nie mogą być deklarowane jako wirtualne. Stosowane
       obecnie kompilatory „spodziewają się”, e będą w stanie określić wielkość tablicy
       funkcji wirtualnych klasy w chwili analizowania tej klasy. Umo liwienie stosowania
       wirtualnych szablonów funkcji składowych wymagałoby znajomości wszystkich wywołań
       takich funkcji składowych w programie, co jest niemo liwe, szczególnie w przypadku
       projektów zawierających wiele plików.



Szablony funkcji
       Tak jak szablon klasy opisuje rodzinę klas, tak szablon funkcji opisuje rodzinę funkcji.
       Składnia tworzenia szablonów jednych i drugich jest w zasadzie identyczna, a ró nice
       dotyczą głównie sposobu u ycia. Podczas tworzenia instancji szablonu klas zawsze
202                                                  Część II ♦ Standardowa biblioteka C++


      trzeba stosować nawiasy kątowe i podawać wszystkie niedomyślne argumenty sza-
      blonu. Z kolei w przypadku szablonów funkcji często mo na pomijać argumenty sza-
      blonu, zaś domyślne argumenty szablonu są niedopuszczalne. Przyjrzyjmy się typo-
      wej implementacji szablonu funkcji min() zadeklarowanego w pliku nagłówkowym
      algorithm:
        VGORNCVGV[RGPCOG 6
        EQPUV 6 OKP
EQPUV 6 C EQPUV 6 D ]
          TGVWTP
C  D ! C  D
        _

      Szablon taki mo na wywołać, podając typ argumentów w nawiasach kątowych, tak
      jak w przypadku szablonów klas:
        KPV   OKPKPV 
K L

      U ycie takiej składni informuje kompilator, e potrzebny jest szablon funkcji min
      z typem int u ytym zamiast parametru T, więc kompilator wygeneruje odpowiedni kod.
      Zgodnie z konwencją nazewniczą dotyczącą klas generowanych przez szablony klas
      mo na się spodziewać, e nazwą tak wywołanej funkcji będzie minint.


Dedukowanie typu argumentów szablonu funkcji
      Zawsze mo na u yć jawnej specyfikacji szablonu funkcji jak powy ej, ale często wy-
      godnie byłoby pominąć argumenty szablonu i pozwolić kompilatorowi wywniosko-
      wać ich wartości na podstawie argumentów funkcji, na przykład tak:
        KPV   OKP
K L

      Jeśli i i j są liczbami int, kompilator „wie”, e potrzebna jest funkcja minint(), i do-
      konuje automatycznie odpowiedniego zastąpienia. Typy muszą być identyczne, gdy
      szablon pierwotnie zdefiniowany jest z jednym tylko argumentem określającym typ,
      u ywanym dla obu parametrów funkcji. W przypadku argumentów funkcji, których
      typ wynika z parametru szablonu, nie są wykonywane adne standardowe konwersje.
      Jeśli, na przykład, trzeba byłoby znaleźć mniejszą z liczb int i double, poni sza próba
      wywołania nie powiodłaby się:
        KPV   OKP
Z L  Z LGUV V[RW FQWDNG

      Zmienne x i j mają ró ne typy, więc aden pojedynczy parametr T w szablonie min
      nie mo e zostać u yty, a wobec tego wywołanie jest niezgodne z deklaracją szablonu.
      Mo na tego problemu uniknąć, rzutując jeden argument na typ argumentu drugiego
      albo stosując wywołanie z pełną specyfikacją, na przykład:
        KPV   OKPFQWDNG 
Z L

      W ten sposób kompilator „wie”, e ma wygenerować funkcję min() korzystającą z typu
      double, a wtedy ju zmienna j mo e w sposób standardowy przekształcona na typ
      double (gdy funkcja mindouble(const double, const double) mo e zostać
      wygenerowana).
Rozdział 5. ♦ Wszystko o szablonach                                                      203


       Kuszące byłoby za ądanie u ycia w przypadku szablonu min u ycia dwóch parametrów,
       dzięki czemu typy argumentów mogłyby być dowolne:
          VGORNCVGV[RGPCOG 6 V[RGPCOG 7
          EQPUV 6 OKP
EQPUV 6 C EQPUV 7 D ]
            TGVWTP 
C  D ! C  D
          _

       Często jest to dobre rozwiązanie, choć w tym wypadku jego zastosowanie jest dyskusyjne:
       min() musi zwrócić wartość, a nie ma jednoznacznie dobrej metody określenia typu tej
       wartości — czy powinien to być typ T albo U.

       Jeśli typ wartości zwracanej przez funkcję jest niezale nym parametrem szablonu, zawsze
       w chwili wywołania funkcji trzeba podać ten typ jawnie, gdy nie ma adnych podstaw
       do wywnioskowania tego typu. Taka sytuacja występuje w przypadku szablonu fromS-
       tring pokazanego poni ej:
           %5VTKPI%QPXJ
           KHPFGH 564+0)%108A*
           FGHKPG 564+0)%108A*
           5CDNQP[ HWPMELK RTGMUVC ECLæE[EJ PC C EWEJ[ K  C EWEJÎY
           KPENWFG UVTKPI
           KPENWFG UUVTGCO

          VGORNCVGV[RGPCOG 6
          6 HTQO5VTKPI
EQPUV UVFUVTKPI U ]
            UVFKUVTKPIUVTGCO KU
U
            6 V
            KU    V
            TGVWTP V
          _

          VGORNCVGV[RGPCOG 6
          UVFUVTKPI VQ5VTKPI
EQPUV 6 V ]
            UVFQUVTKPIUVTGCO U
            U  V
            TGVWTP UUVT

          _
           GPFKH  564+0)%108A* `

       Podane szablony funkcji obsługują konwersje na typ std::string oraz z tego typu
       dla dowolnych typów mających odpowiednio operatory wstawiania i pobierania da-
       nych ze strumienia. Oto program testowy pokazujący u ycie typu complex z biblioteki
       standardowej:
           %5VTKPI%QPX6GUVERR
           KPENWFG 5VTKPI%QPXJ
           KPENWFG KQUVTGCO
           KPENWFG EQORNGZ
          WUKPI PCOGURCEG UVF

          KPV OCKP
 ]
            KPV K  
            EQWV  K    VQ5VTKPI
K   P 
            HNQCV Z  
            EQWV  Z    VQ5VTKPI
Z   P
204                                                        Część II ♦ Standardowa biblioteka C++


                EQORNGZHNQCV E
 
                EQWV  E    VQ5VTKPI
E   P 
                EQWV  GPFN

                K  HTQO5VTKPIKPV 
UVTKPI
  
                EQWV  K   K  GPFN
                Z  HTQO5VTKPIHNQCV 
UVTKPI
  
                EQWV  Z   Z  GPFN
                E  HTQO5VTKPI EQORNGZHNQCV 
UVTKPI
 
 
                EQWV  E   E  GPFN
              _ `

           Wynik działania tego programu będzie następujący:
              K  
              Z  
              E  


              K  
              Z  
              E  


           Zauwa , e w ka dej instancji fromString parametr szablonu jest podawany w wy-
           wołaniu. Jeśli masz szablon funkcji z parametrami szablonu zarówno dla parametrów
           funkcji jak i wartości zwracanej, konieczne jest zadeklarowanie najpierw parametru
           odpowiadającego wartości zwracanej; w przeciwnym przypadku niemo liwe będzie
           pomijanie parametrów szablonu odpowiadających parametrom funkcji. W ramach przy-
           kładu przyjrzyjmy się takiemu oto dobrze znanemu szablonowi funkcji3:
               %+ORNKEKV%CUVERR
              VGORNCVGV[RGPCOG 4 V[RGPCOG 2
              4 KORNKEKVAECUV
EQPUV 2 R ]
                TGVWTP R
              _

              KPV OCKP
 ]
                KPV K  
                HNQCV Z  KORNKEKVAECUVHNQCV 
K
                KPV L  KORNKEKVAECUVKPV 
Z
                 EJCT
R  KORNKEKVAECUVEJCT
K
              _ `

           Jeśli zamienisz znajdujące się na początku pliku parametry R i P miejscami, niemo -
           liwe będzie skompilowanie takiego programu, gdy typ wartości zwracanej nie będzie
           podany (po takiej zmianie pierwszy parametr odpowiadałby typowi parametru funk-
           cji). Ostatni wiersz (zakomentowany) jest niedopuszczalny, gdy nie istnieje standar-
           dowa konwersja typu int na char*; implicit_cast słu y do realizacji tych konwersji,
           które są dopuszczalne.

           Zachowując pewną ostro ność, mo na nawet wydedukować wielkość tablicy. Poni szy
           przykład zawiera wykonujący to szablon funkcji inicjalizującej tablicę, init2:


3
    Zobacz: Stroustrup, The C++ Programming Language, 3rd Edition, Addison Wesley, strony 335 – 336.
Rozdział 5. ♦ Wszystko o szablonach                                                       205


           %#TTC[5KGERR
           KPENWFG EUVFFGH
          WUKPI UVFUKGAV

          VGORNCVGUKGAV 4 UKGAV % V[RGPCOG 6
          XQKF KPKV
6 C=4?=%? ]
            HQT 
UKGAV K   K  4 

K
              HQT 
UKGAV L   L  % 

L
                C=K?=L?  6

          _

          VGORNCVGUKGAV 4 UKGAV % ENCUU 6
          XQKF KPKV
6 
 C=4?=%? ]  RCTCOGVT DúFæE[ TGHGTGPELæ
            HQT 
UKGAV K   K  4 

K
              HQT 
UKGAV L   L  % 

L
                C=K?=L?  6

          _

          KPV OCKP
 ]
            KPV C=?=?
            KPKV 
C  RQFCPKG MQPKGEPG
            KPKV
C         TQOKCT QUVCPKG QMTG NQP[ RTG MQORKNCVQT
          _ `

       Wymiary tablicy nie są przekazywane jako część typu parametru funkcji, chyba e
       parametr ten jest przekazywany przez wskaźnik lub referencję. Szablon funkcji init2
       zawiera deklarację a jako referencji tablicy dwuwymiarowej, więc wymiary R i C zo-
       staną wyznaczone przez mechanizm szablonów, przez co init2 staje się wygodnym
       narzędziem do inicjalizowania dwuwymiarowych tablic dowolnej wielkości. Szablon
       init1 nie przekazuje tablicy przez referencję, wobec czego tutaj wielkość tablicy musi
       być jawnie podawana, choć typ parametru mo e być nadal wywnioskowany.


Przeciążanie szablonów funkcji
       Tak jak w przypadku zwykłych funkcji, mo na przecią ać szablony funkcji mające
       takie same nazwy. Kiedy kompilator przetwarza w programie wywołanie funkcji, musi
       zdecydować, który szablon lub zwykła funkcje będzie „najlepiej pasować” do danego
       wywołania.

       Jeśli istnieje opisany wcześniej szablon funkcji min(), dodajmy jeszcze zwykłe funkcje:
           %/KP6GUVERR
           KPENWFG EUVTKPI
           KPENWFG KQUVTGCO
          WUKPI UVFUVTEOR
          WUKPI UVFEQWV
          WUKPI UVFGPFN

          VGORNCVGV[RGPCOG 6 EQPUV 6 OKP
EQPUV 6 C EQPUV 6 D ]
            TGVWTP 
C  D ! C  D
          _
          EQPUV EJCT
OKP
EQPUV EJCT
C EQPUV EJCT
D ]
            TGVWTP 
UVTEOR
C D   ! C  D
          _
206                                                           Część II ♦ Standardowa biblioteka C++


              FQWDNG OKP
FQWDNG Z FQWDNG [ ]
                TGVWTP 
Z  [ ! Z  [
              _

              KPV OCKP
 ]
                EQPUV EJCT
U  OÎYKæ  0K
U  T[EGTG MVÎT[ 
                EQWV  OKP
   GPFN            
UCDNQP
                EQWV  OKP
   GPFN        
FQWDNG
                EQWV  OKP
   GPFN          
FQWDNG
                EQWV  OKP
U U  GPFN         T[EGTG MVÎT[ 
EQPUV
                                                                    EJCT
EQWV  OKP 
U U  GPFN       OÎYKæ 0K
                                                       
UCDNQP
              _ `

           Teraz oprócz szablonu funkcji mamy zdefiniowane dwie zwykłe funkcje: wersję min()
           u ywającą łańcuchów języka C oraz wersję z double. Gdyby nie istniał szablon, wy-
           wołanie w wierszu 1. wywoływałoby wersję double funkcji min(), a to z uwagi na
           konwersję standardową typu int na double. Jednak istniejący szablon pozwala wygenero-
           wać wersję int, która jest uwa ana za lepiej dopasowaną, więc ten szablon zostanie
           u yty. Wywołanie w wierszu 2. odpowiada wersji z double, zaś wywołanie z wiersza 3.
           wywołuje tę samą funkcję, niejawnie konwertując 1 na 1.0. W wierszu 4. bezpośrednio
           wywoływana wersja const char* funkcji min(). W wierszu 5. wymuszamy na kompila-
           torze u ycie szablonu, gdy do nazwy funkcji dodajemy pustą parę nawiasów kąto-
           wych; wobec tego z szablonu generowana jest wersja const char* i jest ona u ywana
           (widać to po nieprawidłowej odpowiedzi — nastąpiło najzwyklejsze porównanie ad-
           resów!)4. Jeśli zastanawiasz się, czemu zamiast dyrektywy using namespace std;
           u yliśmy deklaracji using, wiedz, e niektóre kompilatory niejawnie dołączają pliki
           nagłówkowe deklarujące std::min(), które mogłyby spowodować konflikt z naszymi
           deklaracjami nazw min().

           Jak powiedziano wy ej, mo na przecią ać szablony mające tę samą nazwę, o ile tylko
           kompilator będzie w stanie je od siebie odró nić. Mo na byłoby, na przykład, zadeklaro-
           wać szablon funkcji min() mający trzy argumenty:
              VGORNCVGV[RGPCOG 6
              EQPUV 6 OKP
EQPUV 6 C EQPUV 6 D EQPUV 6 E

           Wersje tego szablonu będą generowane tylko dla trójargumentowych wywołań min(),
           gdzie wszystkie argumenty będą tego samego typu.


Pobieranie adresu wygenerowanej z szablonu funkcji
           Często potrzebny bywa adres funkcji — na przykład mamy funkcję pobierającą jako
           argument wskaźnik innej funkcji. Oczywiście mo na przekazać tak e funkcję wyge-
           nerowaną z szablonu, a zatem potrzebny będzie jej adres5:

4
    Formalnie rzecz biorąc, porównywanie dwóch wskaźników nieznajdujących się w jednej tablicy
    daje wynik nieokreślony, ale stosowane obecnie kompilatory nie traktują tego powa nie. Co więcej,
    zachowują się one w takiej sytuacji poprawnie.
5
    Za ten przykład jesteśmy wdzięczni Nathanowi Myersowi.
Rozdział 5. ♦ Wszystko o szablonach                                                        207


           %6GORNCVG(WPEVKQP#FFTGUUERR
           2QDKGTCPKG CFTGUW HWPMELK Y[IGPGTQYCPGL  UCDNQPW

          VGORNCVG V[RGPCOG 6 XQKF H
6
]_

          XQKF J
XQKF
RH
KPV
]_

          VGORNCVG V[RGPCOG 6
            XQKF I
XQKF
RH
6
]_

          KPV OCKP
 ]
             2G PC URGE[HKMCELC V[RW
            J
 HKPV 
             1FICF[YCPKG V[RW
            J
 H
             2G PC URGE[HKMCELC V[RW
            IKPV 
 HKPV 
             1FICF[YCPKG V[RW
            I
 HKPV 
             5RGE[HKMCELC Eú EKQYC CNG Y[UVCTECLæEC
            IKPV 
 H
          _ `

       Przykład ten porusza kilka kwestii. Po pierwsze, mimo e u ywamy szablonów, pa-
       sować muszą sygnatury. Funkcja h() pobiera wskaźnik funkcji typu void mającej ar-
       gument int*, właśnie taką funkcję wygeneruje szablon f(). Po drugie, funkcja, która
       jako argument pobiera wskaźnik funkcji, sama mo e być szablonem, jak w przypadku
       szablonu g().

       W funkcji main() widać, e działa te dedukowanie typu. W pierwszym jawnym wy-
       wołaniu h() podawany jest argument szablonu, ale wobec tego, e h() przyjmuje je-
       dynie adres funkcji mającej parametr int*, mógłby się tego domyślić kompilator.
       Jeszcze ciekawiej jest w przypadku funkcji g(), gdy tutaj mamy do czynienia z dwoma
       szablonami. Kompilator nie mo e „wywnioskować” typu, nie mając adnych danych, ale
       jeśli w przypadku f() lub g() podany zostanie typ int, resztę ju mo na będzie odgadnąć.

       Problem pojawia się, kiedy próbujemy przekazać jako parametry funkcje tolower czy
       toupper zadeklarowane w pliku nagłówkowym cctype. Mo na ich u ywać, na przy-
       kład, wraz z algorytmem transform (szczegółowo omawianym w następnym rozdziale),
       aby łańcuchy przekształcać na wielkie lub na małe litery. Jednak trzeba zachować tu
       ostro ność, gdy funkcje te mają wiele deklaracji. Najprościej byłoby zapisać coś takiego:
           OKGPPC U VQ UVFUVTKPI
          VTCPUHQTO
UDGIKP
 UGPF
 UDGIKP
 VQNQYGT

       Algorytm transform stosuje swój czwarty parametr (tutaj tolower()) do ka dego
       znaku łańcucha s, wynik umieszcza w s, przez co nadpisuje ka dy znak s odpowiada-
       jącą mu małą literą. Jednak tak zapisana instrukcja mo e zadziałać lub nie! W poni -
       szym kontekście nie zadziała:
           %(CKNGF6TCPUHQTOERR ]ZQ_
           KPENWFG CNIQTKVJO
           KPENWFG EEV[RG
           KPENWFG KQUVTGCO
208                                                         Część II ♦ Standardowa biblioteka C++


               KPENWFG UVTKPI
              WUKPI PCOGURCEG UVF

              KPV OCKP
 ]
               UVTKPI U
 .19'4 
               VTCPUHQTO
UDGIKP
 UGPF
 UDGIKP
 VQNQYGT
               EQWV  U  GPFN
              _ `

           Nawet jeśli Twój kompilator sobie z tym programem poradzi, to program jest i tak
           niepoprawny. Wynika to stąd, e plik nagłówkowy iostream udostępnia tak e dwuar-
           gumentowe wersje tolower() i toupper():
              VGORNCVG ENCUU EJCT6 EJCT6 VQWRRGT
EJCT6 E EQPUV NQECNG NQE
              VGORNCVG ENCUU EJCT6 EJCT6 VQNQYGT
EJCT6 E EQPUV NQECNG NQE

           Te szablony funkcji mają drugi argument typu locale. Kompilator nie jest w stanie
           stwierdzić, czy powinien u yć jednoargumentowej wersji tolower() z cctype czy
           powy szej. Problem ten mo na rozwiązać (prawie), za pomocą rzutowania w czasie
           wywołania transform:
              VTCPUHQTO
UDGIKP
 UGPF
 UDGIKP
 UVCVKEAECUVKPV
Thinking in C++. Edycja polska. Tom 2
Thinking in C++. Edycja polska. Tom 2
Thinking in C++. Edycja polska. Tom 2
Thinking in C++. Edycja polska. Tom 2
Thinking in C++. Edycja polska. Tom 2
Thinking in C++. Edycja polska. Tom 2
Thinking in C++. Edycja polska. Tom 2
Thinking in C++. Edycja polska. Tom 2
Thinking in C++. Edycja polska. Tom 2
Thinking in C++. Edycja polska. Tom 2
Thinking in C++. Edycja polska. Tom 2

More Related Content

What's hot

C++. Programowanie zorientowane obiektowo. Vademecum profesjonalisty
C++. Programowanie zorientowane obiektowo. Vademecum profesjonalistyC++. Programowanie zorientowane obiektowo. Vademecum profesjonalisty
C++. Programowanie zorientowane obiektowo. Vademecum profesjonalistyWydawnictwo Helion
 
Wyjątkowy język C++. 40 nowych łamigłówek, zadań programistycznych i rozwiązań
Wyjątkowy język C++. 40 nowych łamigłówek, zadań programistycznych i rozwiązańWyjątkowy język C++. 40 nowych łamigłówek, zadań programistycznych i rozwiązań
Wyjątkowy język C++. 40 nowych łamigłówek, zadań programistycznych i rozwiązańWydawnictwo Helion
 
Język C++. Gotowe rozwiązania dla programistów
Język C++. Gotowe rozwiązania dla programistówJęzyk C++. Gotowe rozwiązania dla programistów
Język C++. Gotowe rozwiązania dla programistówWydawnictwo Helion
 
CorelDRAW 11. Ćwiczenia praktyczne
CorelDRAW 11. Ćwiczenia praktyczneCorelDRAW 11. Ćwiczenia praktyczne
CorelDRAW 11. Ćwiczenia praktyczneWydawnictwo Helion
 
C++ dla programistów gier. Wydanie II
C++ dla programistów gier. Wydanie IIC++ dla programistów gier. Wydanie II
C++ dla programistów gier. Wydanie IIWydawnictwo Helion
 
Wstęp do programowania w języku C#
Wstęp do programowania w języku C#Wstęp do programowania w języku C#
Wstęp do programowania w języku C#Wydawnictwo Helion
 
CorelDRAW 11. Vademecum profesjonalisty. Tom 1
CorelDRAW 11. Vademecum profesjonalisty. Tom 1CorelDRAW 11. Vademecum profesjonalisty. Tom 1
CorelDRAW 11. Vademecum profesjonalisty. Tom 1Wydawnictwo Helion
 
C++Builder. Kompendium programisty
C++Builder. Kompendium programistyC++Builder. Kompendium programisty
C++Builder. Kompendium programistyWydawnictwo Helion
 
C++Builder Borland Developer Studio 2006. Kompendium programisty
C++Builder Borland Developer Studio 2006. Kompendium programistyC++Builder Borland Developer Studio 2006. Kompendium programisty
C++Builder Borland Developer Studio 2006. Kompendium programistyWydawnictwo Helion
 
Visual C# 2005 Express Edition. Od podstaw
Visual C# 2005 Express Edition. Od podstawVisual C# 2005 Express Edition. Od podstaw
Visual C# 2005 Express Edition. Od podstawWydawnictwo Helion
 
C++. Potęga języka. Od przykładu do przykładu
C++. Potęga języka. Od przykładu do przykładuC++. Potęga języka. Od przykładu do przykładu
C++. Potęga języka. Od przykładu do przykładuWydawnictwo Helion
 

What's hot (20)

C++. Programowanie zorientowane obiektowo. Vademecum profesjonalisty
C++. Programowanie zorientowane obiektowo. Vademecum profesjonalistyC++. Programowanie zorientowane obiektowo. Vademecum profesjonalisty
C++. Programowanie zorientowane obiektowo. Vademecum profesjonalisty
 
Wyjątkowy język C++. 40 nowych łamigłówek, zadań programistycznych i rozwiązań
Wyjątkowy język C++. 40 nowych łamigłówek, zadań programistycznych i rozwiązańWyjątkowy język C++. 40 nowych łamigłówek, zadań programistycznych i rozwiązań
Wyjątkowy język C++. 40 nowych łamigłówek, zadań programistycznych i rozwiązań
 
C++. Sztuka programowania
C++. Sztuka programowaniaC++. Sztuka programowania
C++. Sztuka programowania
 
C++Builder 6. Ćwiczenia
C++Builder 6. ĆwiczeniaC++Builder 6. Ćwiczenia
C++Builder 6. Ćwiczenia
 
Język C++. Gotowe rozwiązania dla programistów
Język C++. Gotowe rozwiązania dla programistówJęzyk C++. Gotowe rozwiązania dla programistów
Język C++. Gotowe rozwiązania dla programistów
 
C++ bez obaw
C++ bez obawC++ bez obaw
C++ bez obaw
 
CorelDRAW 11. Ćwiczenia praktyczne
CorelDRAW 11. Ćwiczenia praktyczneCorelDRAW 11. Ćwiczenia praktyczne
CorelDRAW 11. Ćwiczenia praktyczne
 
Uczta programistów
Uczta programistówUczta programistów
Uczta programistów
 
C++ dla programistów gier. Wydanie II
C++ dla programistów gier. Wydanie IIC++ dla programistów gier. Wydanie II
C++ dla programistów gier. Wydanie II
 
C++BuilderX. Ćwiczenia
C++BuilderX. ĆwiczeniaC++BuilderX. Ćwiczenia
C++BuilderX. Ćwiczenia
 
Programowanie. Od podstaw
Programowanie. Od podstawProgramowanie. Od podstaw
Programowanie. Od podstaw
 
Wstęp do programowania w języku C#
Wstęp do programowania w języku C#Wstęp do programowania w języku C#
Wstęp do programowania w języku C#
 
CorelDRAW 11. Vademecum profesjonalisty. Tom 1
CorelDRAW 11. Vademecum profesjonalisty. Tom 1CorelDRAW 11. Vademecum profesjonalisty. Tom 1
CorelDRAW 11. Vademecum profesjonalisty. Tom 1
 
Język C. Programowanie
Język C. ProgramowanieJęzyk C. Programowanie
Język C. Programowanie
 
Visual C# .NET. Encyklopedia
Visual C# .NET. EncyklopediaVisual C# .NET. Encyklopedia
Visual C# .NET. Encyklopedia
 
C++Builder. Kompendium programisty
C++Builder. Kompendium programistyC++Builder. Kompendium programisty
C++Builder. Kompendium programisty
 
C++Builder Borland Developer Studio 2006. Kompendium programisty
C++Builder Borland Developer Studio 2006. Kompendium programistyC++Builder Borland Developer Studio 2006. Kompendium programisty
C++Builder Borland Developer Studio 2006. Kompendium programisty
 
C#. Wzorce projektowe
C#. Wzorce projektoweC#. Wzorce projektowe
C#. Wzorce projektowe
 
Visual C# 2005 Express Edition. Od podstaw
Visual C# 2005 Express Edition. Od podstawVisual C# 2005 Express Edition. Od podstaw
Visual C# 2005 Express Edition. Od podstaw
 
C++. Potęga języka. Od przykładu do przykładu
C++. Potęga języka. Od przykładu do przykładuC++. Potęga języka. Od przykładu do przykładu
C++. Potęga języka. Od przykładu do przykładu
 

Viewers also liked

Windows XP PL. 100 najlepszych sztuczek i trików
Windows XP PL. 100 najlepszych sztuczek i trikówWindows XP PL. 100 najlepszych sztuczek i trików
Windows XP PL. 100 najlepszych sztuczek i trikówWydawnictwo Helion
 
Cyberprzestępczość. Jak walczyć z łamaniem prawa w Sieci
Cyberprzestępczość. Jak walczyć z łamaniem prawa w SieciCyberprzestępczość. Jak walczyć z łamaniem prawa w Sieci
Cyberprzestępczość. Jak walczyć z łamaniem prawa w SieciWydawnictwo Helion
 
Ścigany. Rozmowy z Kevinem Mitnickiem
Ścigany. Rozmowy z Kevinem MitnickiemŚcigany. Rozmowy z Kevinem Mitnickiem
Ścigany. Rozmowy z Kevinem MitnickiemWydawnictwo Helion
 
100 sposobów na Windows XP PL
100 sposobów na Windows XP PL100 sposobów na Windows XP PL
100 sposobów na Windows XP PLWydawnictwo Helion
 
Fotografia cyfrowa. 100 najlepszych sztuczek i trików
Fotografia cyfrowa. 100 najlepszych sztuczek i trikówFotografia cyfrowa. 100 najlepszych sztuczek i trików
Fotografia cyfrowa. 100 najlepszych sztuczek i trikówWydawnictwo Helion
 
Pozycjonowanie w wyszukiwarkach internetowych
Pozycjonowanie w wyszukiwarkach internetowychPozycjonowanie w wyszukiwarkach internetowych
Pozycjonowanie w wyszukiwarkach internetowychWydawnictwo Helion
 
Strażnik bezpieczeństwa danych
Strażnik bezpieczeństwa danychStrażnik bezpieczeństwa danych
Strażnik bezpieczeństwa danychWydawnictwo Helion
 
101 zabezpieczeń przed atakami w sieci komputerowej
101 zabezpieczeń przed atakami w sieci komputerowej101 zabezpieczeń przed atakami w sieci komputerowej
101 zabezpieczeń przed atakami w sieci komputerowejWydawnictwo Helion
 
J2EE. Stosowanie wzorców projektowych
J2EE. Stosowanie wzorców projektowychJ2EE. Stosowanie wzorców projektowych
J2EE. Stosowanie wzorców projektowychWydawnictwo Helion
 
Excel 2003 PL. Programowanie w VBA. Vademecum profesjonalisty
Excel 2003 PL. Programowanie w VBA. Vademecum profesjonalistyExcel 2003 PL. Programowanie w VBA. Vademecum profesjonalisty
Excel 2003 PL. Programowanie w VBA. Vademecum profesjonalistyWydawnictwo Helion
 

Viewers also liked (16)

Windows XP PL. 100 najlepszych sztuczek i trików
Windows XP PL. 100 najlepszych sztuczek i trikówWindows XP PL. 100 najlepszych sztuczek i trików
Windows XP PL. 100 najlepszych sztuczek i trików
 
Anatomia PC. Wydanie IX
Anatomia PC. Wydanie IXAnatomia PC. Wydanie IX
Anatomia PC. Wydanie IX
 
Pocket PC
Pocket PCPocket PC
Pocket PC
 
Cyberprzestępczość. Jak walczyć z łamaniem prawa w Sieci
Cyberprzestępczość. Jak walczyć z łamaniem prawa w SieciCyberprzestępczość. Jak walczyć z łamaniem prawa w Sieci
Cyberprzestępczość. Jak walczyć z łamaniem prawa w Sieci
 
ABC Photoshop CS
ABC Photoshop CSABC Photoshop CS
ABC Photoshop CS
 
Ścigany. Rozmowy z Kevinem Mitnickiem
Ścigany. Rozmowy z Kevinem MitnickiemŚcigany. Rozmowy z Kevinem Mitnickiem
Ścigany. Rozmowy z Kevinem Mitnickiem
 
100 sposobów na Windows XP PL
100 sposobów na Windows XP PL100 sposobów na Windows XP PL
100 sposobów na Windows XP PL
 
Fotografia cyfrowa. 100 najlepszych sztuczek i trików
Fotografia cyfrowa. 100 najlepszych sztuczek i trikówFotografia cyfrowa. 100 najlepszych sztuczek i trików
Fotografia cyfrowa. 100 najlepszych sztuczek i trików
 
Pozycjonowanie w wyszukiwarkach internetowych
Pozycjonowanie w wyszukiwarkach internetowychPozycjonowanie w wyszukiwarkach internetowych
Pozycjonowanie w wyszukiwarkach internetowych
 
Photoshop CS
Photoshop CSPhotoshop CS
Photoshop CS
 
Strażnik bezpieczeństwa danych
Strażnik bezpieczeństwa danychStrażnik bezpieczeństwa danych
Strażnik bezpieczeństwa danych
 
101 zabezpieczeń przed atakami w sieci komputerowej
101 zabezpieczeń przed atakami w sieci komputerowej101 zabezpieczeń przed atakami w sieci komputerowej
101 zabezpieczeń przed atakami w sieci komputerowej
 
J2EE. Stosowanie wzorców projektowych
J2EE. Stosowanie wzorców projektowychJ2EE. Stosowanie wzorców projektowych
J2EE. Stosowanie wzorców projektowych
 
Excel 2003 PL. Programowanie w VBA. Vademecum profesjonalisty
Excel 2003 PL. Programowanie w VBA. Vademecum profesjonalistyExcel 2003 PL. Programowanie w VBA. Vademecum profesjonalisty
Excel 2003 PL. Programowanie w VBA. Vademecum profesjonalisty
 
Praktyczny kurs asemblera
Praktyczny kurs asembleraPraktyczny kurs asemblera
Praktyczny kurs asemblera
 
Excel. Leksykon kieszonkowy
Excel. Leksykon kieszonkowyExcel. Leksykon kieszonkowy
Excel. Leksykon kieszonkowy
 

Similar to Thinking in C++. Edycja polska. Tom 2

Aplikacje w Visual C++ 2005. Przykłady
Aplikacje w Visual C++ 2005. PrzykładyAplikacje w Visual C++ 2005. Przykłady
Aplikacje w Visual C++ 2005. PrzykładyWydawnictwo Helion
 
Język C. Wskaźniki. Vademecum profesjonalisty
Język C. Wskaźniki. Vademecum profesjonalistyJęzyk C. Wskaźniki. Vademecum profesjonalisty
Język C. Wskaźniki. Vademecum profesjonalistyWydawnictwo Helion
 
C++Builder i Turbo C++. Podstawy
C++Builder i Turbo C++. PodstawyC++Builder i Turbo C++. Podstawy
C++Builder i Turbo C++. PodstawyWydawnictwo Helion
 
Język C++. Standardy kodowania. 101 zasad, wytycznych i zalecanych praktyk
Język C++. Standardy kodowania. 101 zasad, wytycznych i zalecanych praktykJęzyk C++. Standardy kodowania. 101 zasad, wytycznych i zalecanych praktyk
Język C++. Standardy kodowania. 101 zasad, wytycznych i zalecanych praktykWydawnictwo Helion
 
RS 232C - praktyczne programowanie. Od Pascala i C++ do Delphi i Buildera. Wy...
RS 232C - praktyczne programowanie. Od Pascala i C++ do Delphi i Buildera. Wy...RS 232C - praktyczne programowanie. Od Pascala i C++ do Delphi i Buildera. Wy...
RS 232C - praktyczne programowanie. Od Pascala i C++ do Delphi i Buildera. Wy...Wydawnictwo Helion
 
C++ Builder. Symulacje komputerowe
C++ Builder. Symulacje komputeroweC++ Builder. Symulacje komputerowe
C++ Builder. Symulacje komputeroweWydawnictwo Helion
 
Wzorce projektowe. Analiza kodu sposobem na ich poznanie
Wzorce projektowe. Analiza kodu sposobem na ich poznanieWzorce projektowe. Analiza kodu sposobem na ich poznanie
Wzorce projektowe. Analiza kodu sposobem na ich poznanieWydawnictwo Helion
 
Programowanie w języku C. FAQ
Programowanie w języku C. FAQProgramowanie w języku C. FAQ
Programowanie w języku C. FAQWydawnictwo Helion
 
Programuje W Delphi I C Builder
Programuje W Delphi I C BuilderProgramuje W Delphi I C Builder
Programuje W Delphi I C Builderfreeebook
 

Similar to Thinking in C++. Edycja polska. Tom 2 (16)

Aplikacje w Visual C++ 2005. Przykłady
Aplikacje w Visual C++ 2005. PrzykładyAplikacje w Visual C++ 2005. Przykłady
Aplikacje w Visual C++ 2005. Przykłady
 
C++. Leksykon kieszonkowy
C++. Leksykon kieszonkowyC++. Leksykon kieszonkowy
C++. Leksykon kieszonkowy
 
C++Builder 6 i bazy danych
C++Builder 6 i bazy danychC++Builder 6 i bazy danych
C++Builder 6 i bazy danych
 
Język C. Wskaźniki. Vademecum profesjonalisty
Język C. Wskaźniki. Vademecum profesjonalistyJęzyk C. Wskaźniki. Vademecum profesjonalisty
Język C. Wskaźniki. Vademecum profesjonalisty
 
AutoCAD 2004
AutoCAD 2004AutoCAD 2004
AutoCAD 2004
 
ArchiCAD 10
ArchiCAD 10ArchiCAD 10
ArchiCAD 10
 
C++Builder i Turbo C++. Podstawy
C++Builder i Turbo C++. PodstawyC++Builder i Turbo C++. Podstawy
C++Builder i Turbo C++. Podstawy
 
Język C++. Standardy kodowania. 101 zasad, wytycznych i zalecanych praktyk
Język C++. Standardy kodowania. 101 zasad, wytycznych i zalecanych praktykJęzyk C++. Standardy kodowania. 101 zasad, wytycznych i zalecanych praktyk
Język C++. Standardy kodowania. 101 zasad, wytycznych i zalecanych praktyk
 
RS 232C - praktyczne programowanie. Od Pascala i C++ do Delphi i Buildera. Wy...
RS 232C - praktyczne programowanie. Od Pascala i C++ do Delphi i Buildera. Wy...RS 232C - praktyczne programowanie. Od Pascala i C++ do Delphi i Buildera. Wy...
RS 232C - praktyczne programowanie. Od Pascala i C++ do Delphi i Buildera. Wy...
 
C# i ASP.NET. Szybki start
C# i ASP.NET. Szybki startC# i ASP.NET. Szybki start
C# i ASP.NET. Szybki start
 
C++ Builder. Symulacje komputerowe
C++ Builder. Symulacje komputeroweC++ Builder. Symulacje komputerowe
C++ Builder. Symulacje komputerowe
 
AutoCAD 2004 PL
AutoCAD 2004 PLAutoCAD 2004 PL
AutoCAD 2004 PL
 
CorelDraw X3 PL. Kurs
CorelDraw X3 PL. KursCorelDraw X3 PL. Kurs
CorelDraw X3 PL. Kurs
 
Wzorce projektowe. Analiza kodu sposobem na ich poznanie
Wzorce projektowe. Analiza kodu sposobem na ich poznanieWzorce projektowe. Analiza kodu sposobem na ich poznanie
Wzorce projektowe. Analiza kodu sposobem na ich poznanie
 
Programowanie w języku C. FAQ
Programowanie w języku C. FAQProgramowanie w języku C. FAQ
Programowanie w języku C. FAQ
 
Programuje W Delphi I C Builder
Programuje W Delphi I C BuilderProgramuje W Delphi I C Builder
Programuje W Delphi I C Builder
 

More from Wydawnictwo Helion

Tworzenie filmów w Windows XP. Projekty
Tworzenie filmów w Windows XP. ProjektyTworzenie filmów w Windows XP. Projekty
Tworzenie filmów w Windows XP. ProjektyWydawnictwo Helion
 
Blog, więcej niż internetowy pamiętnik
Blog, więcej niż internetowy pamiętnikBlog, więcej niż internetowy pamiętnik
Blog, więcej niż internetowy pamiętnikWydawnictwo Helion
 
Pozycjonowanie i optymalizacja stron WWW. Ćwiczenia praktyczne
Pozycjonowanie i optymalizacja stron WWW. Ćwiczenia praktycznePozycjonowanie i optymalizacja stron WWW. Ćwiczenia praktyczne
Pozycjonowanie i optymalizacja stron WWW. Ćwiczenia praktyczneWydawnictwo Helion
 
E-wizerunek. Internet jako narzędzie kreowania image&#39;u w biznesie
E-wizerunek. Internet jako narzędzie kreowania image&#39;u w biznesieE-wizerunek. Internet jako narzędzie kreowania image&#39;u w biznesie
E-wizerunek. Internet jako narzędzie kreowania image&#39;u w biznesieWydawnictwo Helion
 
Microsoft Visual C++ 2008. Tworzenie aplikacji dla Windows
Microsoft Visual C++ 2008. Tworzenie aplikacji dla WindowsMicrosoft Visual C++ 2008. Tworzenie aplikacji dla Windows
Microsoft Visual C++ 2008. Tworzenie aplikacji dla WindowsWydawnictwo Helion
 
Co potrafi Twój iPhone? Podręcznik użytkownika. Wydanie II
Co potrafi Twój iPhone? Podręcznik użytkownika. Wydanie IICo potrafi Twój iPhone? Podręcznik użytkownika. Wydanie II
Co potrafi Twój iPhone? Podręcznik użytkownika. Wydanie IIWydawnictwo Helion
 
Makrofotografia. Magia szczegółu
Makrofotografia. Magia szczegółuMakrofotografia. Magia szczegółu
Makrofotografia. Magia szczegółuWydawnictwo Helion
 
Java. Efektywne programowanie. Wydanie II
Java. Efektywne programowanie. Wydanie IIJava. Efektywne programowanie. Wydanie II
Java. Efektywne programowanie. Wydanie IIWydawnictwo Helion
 
Ajax, JavaScript i PHP. Intensywny trening
Ajax, JavaScript i PHP. Intensywny treningAjax, JavaScript i PHP. Intensywny trening
Ajax, JavaScript i PHP. Intensywny treningWydawnictwo Helion
 
PowerPoint 2007 PL. Seria praktyk
PowerPoint 2007 PL. Seria praktykPowerPoint 2007 PL. Seria praktyk
PowerPoint 2007 PL. Seria praktykWydawnictwo Helion
 
Serwisy społecznościowe. Budowa, administracja i moderacja
Serwisy społecznościowe. Budowa, administracja i moderacjaSerwisy społecznościowe. Budowa, administracja i moderacja
Serwisy społecznościowe. Budowa, administracja i moderacjaWydawnictwo Helion
 

More from Wydawnictwo Helion (20)

Tworzenie filmów w Windows XP. Projekty
Tworzenie filmów w Windows XP. ProjektyTworzenie filmów w Windows XP. Projekty
Tworzenie filmów w Windows XP. Projekty
 
Blog, więcej niż internetowy pamiętnik
Blog, więcej niż internetowy pamiętnikBlog, więcej niż internetowy pamiętnik
Blog, więcej niż internetowy pamiętnik
 
Access w biurze i nie tylko
Access w biurze i nie tylkoAccess w biurze i nie tylko
Access w biurze i nie tylko
 
Pozycjonowanie i optymalizacja stron WWW. Ćwiczenia praktyczne
Pozycjonowanie i optymalizacja stron WWW. Ćwiczenia praktycznePozycjonowanie i optymalizacja stron WWW. Ćwiczenia praktyczne
Pozycjonowanie i optymalizacja stron WWW. Ćwiczenia praktyczne
 
E-wizerunek. Internet jako narzędzie kreowania image&#39;u w biznesie
E-wizerunek. Internet jako narzędzie kreowania image&#39;u w biznesieE-wizerunek. Internet jako narzędzie kreowania image&#39;u w biznesie
E-wizerunek. Internet jako narzędzie kreowania image&#39;u w biznesie
 
Microsoft Visual C++ 2008. Tworzenie aplikacji dla Windows
Microsoft Visual C++ 2008. Tworzenie aplikacji dla WindowsMicrosoft Visual C++ 2008. Tworzenie aplikacji dla Windows
Microsoft Visual C++ 2008. Tworzenie aplikacji dla Windows
 
Co potrafi Twój iPhone? Podręcznik użytkownika. Wydanie II
Co potrafi Twój iPhone? Podręcznik użytkownika. Wydanie IICo potrafi Twój iPhone? Podręcznik użytkownika. Wydanie II
Co potrafi Twój iPhone? Podręcznik użytkownika. Wydanie II
 
Makrofotografia. Magia szczegółu
Makrofotografia. Magia szczegółuMakrofotografia. Magia szczegółu
Makrofotografia. Magia szczegółu
 
Windows PowerShell. Podstawy
Windows PowerShell. PodstawyWindows PowerShell. Podstawy
Windows PowerShell. Podstawy
 
Java. Efektywne programowanie. Wydanie II
Java. Efektywne programowanie. Wydanie IIJava. Efektywne programowanie. Wydanie II
Java. Efektywne programowanie. Wydanie II
 
JavaScript. Pierwsze starcie
JavaScript. Pierwsze starcieJavaScript. Pierwsze starcie
JavaScript. Pierwsze starcie
 
Ajax, JavaScript i PHP. Intensywny trening
Ajax, JavaScript i PHP. Intensywny treningAjax, JavaScript i PHP. Intensywny trening
Ajax, JavaScript i PHP. Intensywny trening
 
PowerPoint 2007 PL. Seria praktyk
PowerPoint 2007 PL. Seria praktykPowerPoint 2007 PL. Seria praktyk
PowerPoint 2007 PL. Seria praktyk
 
Excel 2007 PL. Seria praktyk
Excel 2007 PL. Seria praktykExcel 2007 PL. Seria praktyk
Excel 2007 PL. Seria praktyk
 
Access 2007 PL. Seria praktyk
Access 2007 PL. Seria praktykAccess 2007 PL. Seria praktyk
Access 2007 PL. Seria praktyk
 
Word 2007 PL. Seria praktyk
Word 2007 PL. Seria praktykWord 2007 PL. Seria praktyk
Word 2007 PL. Seria praktyk
 
Serwisy społecznościowe. Budowa, administracja i moderacja
Serwisy społecznościowe. Budowa, administracja i moderacjaSerwisy społecznościowe. Budowa, administracja i moderacja
Serwisy społecznościowe. Budowa, administracja i moderacja
 
AutoCAD 2008 i 2008 PL
AutoCAD 2008 i 2008 PLAutoCAD 2008 i 2008 PL
AutoCAD 2008 i 2008 PL
 
Bazy danych. Pierwsze starcie
Bazy danych. Pierwsze starcieBazy danych. Pierwsze starcie
Bazy danych. Pierwsze starcie
 
Inventor. Pierwsze kroki
Inventor. Pierwsze krokiInventor. Pierwsze kroki
Inventor. Pierwsze kroki
 

Thinking in C++. Edycja polska. Tom 2

  • 1. IDZ DO PRZYK£ADOWY ROZDZIA£ SPIS TRE CI Thinking in C++. Edycja polska. Tom II KATALOG KSI¥¯EK Autor: Bruce Eckel, Chuck Allison KATALOG ONLINE T³umaczenie: Przemys³aw Szeremiota, Tomasz ¯mijewski ISBN: 83-7361-409-5 Tytu³ orygina³u: Thinking in C++, Vol. 2: ZAMÓW DRUKOWANY KATALOG Practical Programming, Second Edition Format: B5, stron: 688 TWÓJ KOSZYK Nauka jêzyka C++ i szczegó³owe poznanie jego mo¿liwo ci to powa¿ne wyzwanie DODAJ DO KOSZYKA nie tylko dla pocz¹tkuj¹cego, ale równie¿ dla zaawansowanego programisty. W ksi¹¿ce Thinking in C++. Edycja polska. Bruce Eckel w doskona³y sposób przedstawi³ podstawowe zagadnienia zwi¹zane z tym jêzykiem. Je li opanowa³e CENNIK I INFORMACJE materia³ z tej ksi¹¿ki, mo¿esz rozpocz¹æ lekturê drugiego tomu. Ksi¹¿ka, któr¹ trzymasz w rêce — Thinking in C++. Edycja polska. Tom II to kolejny ZAMÓW INFORMACJE bestseller Bruce’a Eckela po wiêcony jêzykowi C++. Tym razem Bruce w typowy dla O NOWO CIACH siebie, prosty i zrozumia³y sposób opisuje zaawansowane aspekty programowania w C++. Dowiesz siê, jak korzystaæ z referencji, przeci¹¿ania operatorów, dziedziczenia ZAMÓW CENNIK i obiektów dynamicznych, a tak¿e poznasz zagadnienia zaawansowane — prawid³owe u¿ycie szablonów, wyj¹tków i wielokrotnego dziedziczenia. Wszystkie tematy opatrzone s¹ æwiczeniami. CZYTELNIA • obs³uga wyj¹tków • programowanie defensywne FRAGMENTY KSI¥¯EK ONLINE • standardowa biblioteka C++ • strumienie wej cia-wyj cia • wzorce projektowe • zaawansowane metody programowania obiektowego • wspó³bie¿no æ Kody ród³owe znajduj¹ce siê w ksi¹¿ce s¹ zgodne z wieloma kompilatorami C++. Bruce Eckel jest prezesem MindView, Inc., firmy prowadz¹cej kursy i szkolenia zarówno otwarte, jak i zamkniête, a tak¿e zajmuj¹cej siê doradztwem i nadzorem nad projektami zwi¹zanymi z technologiami obiektowymi i wzorcami projektowymi. Jest autorem ksi¹¿ek Thinking in Java oraz pierwszego tomu Thinking in C++, a tak¿e wspó³autorem ksi¹¿ki Thinking in C#. Napisa³ tak¿e kilka innych ksi¹¿ek i ponad 150 artyku³ów. Wydawnictwo Helion Od ponad 20 lat prowadzi wyk³ady i seminaria na ca³ym wiecie. By³ cz³onkiem ul. Chopina 6 Komitetu Standardów C++. Zdoby³ tytu³ naukowy w dziedzinie fizyki stosowanej 44-100 Gliwice i in¿ynierii oprogramowania. tel. (32)230-98-63 Chuck Allison jest matematykiem, pe³ni¹cym obecnie funkcjê wyk³adowcy na wydziale e-mail: helion@helion.pl informatyki uniwersytetu stanowego Utah Valley. Do niedawna pe³ni³ funkcjê redaktora w magazynie C/C++ Users Journal. Jest tak¿e autorem ksi¹¿ki C&C++ Code Capsules: A Guide for Practitioners i kilkudziesiêciu artyku³ów po wiêconych programowaniu w C i C++. Bra³ udzia³ w tworzeniu standardu C++. Jego artyku³y i omówienia napisanych przez niego ksi¹¿ek mo¿na znale æ w witrynie WWW www.freshsources.com.
  • 2. Spis treści Wstęp ............................................................................................. 11 Cele....................................................................................................................................11 Rozdziały...........................................................................................................................12 Ćwiczenia ..........................................................................................................................14 Rozwiązania do ćwiczeń.............................................................................................14 Kod źródłowy....................................................................................................................15 Obsługiwane wersje języka...............................................................................................16 Standardy językowe ..........................................................................................................17 O okładce...........................................................................................................................17 Część I Tworzenie niezawodnych systemów.................................19 Rozdział 1. Obsługa wyjątków............................................................................ 21 Tradycyjna obsługa błędów ..............................................................................................22 Wyrzucanie wyjątku..........................................................................................................24 Przechwytywanie wyjątku.................................................................................................25 Blok try .......................................................................................................................25 Obsługa wyjątków ......................................................................................................25 Zakończenie i kontynuacja .........................................................................................26 Dopasowywanie wyjątków ...............................................................................................27 Przechwytywanie dowolnych wyjątków.....................................................................29 Ponowne wyrzucanie wyjątku ....................................................................................29 Wyjątki nieprzechwycone...........................................................................................30 Czyszczenie.......................................................................................................................32 Zarządzanie zasobami.................................................................................................33 Wszystko jest obiektem ..............................................................................................34 auto_ptr .......................................................................................................................36 Bloki try na poziomie funkcji .....................................................................................38 Wyjątki standardowe.........................................................................................................39 Specyfikacje wyjątków .....................................................................................................41 Jakieś lepsze specyfikacje wyjątków? ........................................................................45 Specyfikacja wyjątków i dziedziczenie ......................................................................45 Kiedy nie u ywać specyfikacji wyjątków?.................................................................46 Bezpieczeństwo wyjątków ................................................................................................47 Programowanie z u yciem wyjątków ...............................................................................50 Kiedy unikać wyjątków?.............................................................................................51 Typowe zastosowania wyjątków ................................................................................52 Narzuty ..............................................................................................................................55 Podsumowanie ..................................................................................................................57 Ćwiczenia ..........................................................................................................................57
  • 3. 6 Thinking in C++. Edycja polska. Tom 2 Rozdział 2. Programowanie defensywne ............................................................. 59 Asercje...............................................................................................................................61 Najprostszy system testów jednostkowych, który ma szansę zadziałać ...........................65 Automatyczne testowanie ...........................................................................................66 Szkielet TestSuite........................................................................................................70 Zestawy testowe..........................................................................................................73 Kod szkieletu testowego .............................................................................................74 Techniki usuwania błędów................................................................................................79 Makra śledzące............................................................................................................79 Plik śladu.....................................................................................................................80 Znajdowanie wycieków pamięci.................................................................................81 Podsumowanie ..................................................................................................................86 Ćwiczenia ..........................................................................................................................86 Część II Standardowa biblioteka C++...........................................91 Rozdział 3. Wszystko o łańcuchach.................................................................... 93 Czym jest łańcuch?............................................................................................................94 Tworzenie i inicjalizacja łańcuchów C++...........................................................................95 Operacje na łańcuchach.....................................................................................................98 Dodawanie, wstawianie i łączenie łańcuchów............................................................98 Podmiana znaków łańcucha......................................................................................100 Sklejanie za pomocą przecią onych operatorów spoza klasy...................................103 Szukanie w łańcuchach ...................................................................................................104 Znajdowanie od końca ..............................................................................................107 Znajdowanie pierwszego i ostatniego ze zbioru znaków..........................................109 Usuwanie znaków z łańcuchów ................................................................................111 Porównywanie łańcuchów ........................................................................................112 Łańcuchy a znaki ......................................................................................................116 Przykład zastosowania łańcuchów ..................................................................................121 Podsumowanie ................................................................................................................125 Ćwiczenia ........................................................................................................................126 Rozdział 4. Strumienie wejścia-wyjścia............................................................. 129 Po co nowa biblioteka? ...................................................................................................129 Iostream przybywa z odsieczą.........................................................................................133 Wstawianie i pobieranie............................................................................................134 Typowe zastosowania ...............................................................................................137 Dane wejściowe pobierane wierszami ......................................................................139 Obsługa błędów strumieni...............................................................................................140 Strumienie związane z plikami .......................................................................................143 Przykład przetwarzania pliku....................................................................................143 Tryby otwarcia ..........................................................................................................145 Buforowanie strumieni....................................................................................................146 Przeszukiwanie strumieni wejścia-wyjścia .....................................................................148 Strumienie powiązane z łańcuchami ...............................................................................151 Łańcuchowe strumienie wejściowe ..........................................................................152 Łańcuchowe strumienie wyjściowe ..........................................................................153 Formatowanie strumieni wyjściowych............................................................................156 Flagi formatujące ......................................................................................................156 Pola formatujące .......................................................................................................158 Szerokość, wypełnienie, dokładność ........................................................................159 Kompletny przykład..................................................................................................160
  • 4. Spis treści 7 Manipulatory ...................................................................................................................162 Manipulatory z argumentami....................................................................................163 Tworzenie manipulatorów ........................................................................................166 Efektory.....................................................................................................................167 Przykłady wykorzystujące iostream................................................................................169 Zarządzanie kodem źródłowym biblioteki klas ........................................................169 Wykrywanie błędów kompilatora.............................................................................173 Prosty rejestrator danych...........................................................................................175 Obsługa wielu języków ...................................................................................................179 Strumienie znaków szerokich ...................................................................................179 Ustawienia lokalne....................................................................................................181 Podsumowanie ................................................................................................................183 Ćwiczenia ........................................................................................................................183 Rozdział 5. Wszystko o szablonach .................................................................. 187 Parametry szablonów ......................................................................................................187 Parametry szablonów niebędące typami...................................................................188 Domyślne argumenty szablonów..............................................................................190 Szablony jako parametry szablonów ........................................................................191 Słowo kluczowe typename .......................................................................................196 U ycie słowa kluczowego template jako wskazówki...............................................198 Szablony składowe....................................................................................................199 Szablony funkcji..............................................................................................................201 Dedukowanie typu argumentów szablonu funkcji....................................................202 Przecią anie szablonów funkcji................................................................................205 Pobieranie adresu wygenerowanej z szablonu funkcji .............................................206 Stosowanie funkcji do sekwencji STL......................................................................209 Częściowe uporządkowanie szablonów funkcji .......................................................212 Specjalizacja szablonów..................................................................................................213 Specjalizacja jawna...................................................................................................214 Specjalizacja częściowa ............................................................................................215 Przykład praktyczny..................................................................................................217 Unikanie nadmiarowego kodu ..................................................................................220 Odszukiwanie nazw.........................................................................................................224 Nazwy w szablonach.................................................................................................224 Szablony i funkcje zaprzyjaźnione ...........................................................................228 Idiomy programowania za pomocą szablonów...............................................................233 Cechy charakterystyczne ..........................................................................................233 Reguły .......................................................................................................................238 Tajemniczo powtarzający się wzorzec szablonów ...................................................240 Szablony i metaprogramowanie ......................................................................................242 Programowanie na poziomie kompilacji ..................................................................243 Szablony wyra eń .....................................................................................................251 Modele kompilacji szablonów ........................................................................................256 Model włączania .......................................................................................................256 Ukonkretnianie jawne ...............................................................................................257 Model separacji.........................................................................................................259 Podsumowanie ................................................................................................................260 Ćwiczenia ........................................................................................................................261 Rozdział 6. Algorytmy uogólnione..................................................................... 265 Algorytmy uogólnione — wprowadzenie ..........................................................................265 Predykaty ..................................................................................................................268 Iteratory strumieni.....................................................................................................270 Zło oność algorytmu ................................................................................................272
  • 5. 8 Thinking in C++. Edycja polska. Tom 2 Obiekty funkcyjne ...........................................................................................................274 Klasyfikacja obiektów funkcyjnych .........................................................................275 Automatyczne tworzenie obiektów funkcyjnych......................................................276 Adaptowalność obiektów funkcyjnych.....................................................................279 Więcej przykładów wykorzystania obiektów funkcyjnych ......................................281 Adaptery wskaźników do funkcji .............................................................................287 Pisanie własnych adapterów obiektów funkcyjnych ................................................293 Katalog algorytmów STL................................................................................................297 Narzędzia przydatne w tworzeniu przykładów.........................................................299 Wypełnianie i generowanie sekwencji......................................................................303 Zliczanie....................................................................................................................304 Manipulowanie sekwencjami....................................................................................305 Wyszukiwanie i zastępowanie elementów................................................................310 Porównywanie sekwencji..........................................................................................316 Usuwanie elementów sekwencji ...............................................................................319 Sortowanie i operacje na sekwencjach posortowanych ............................................322 Operacje na stertach..................................................................................................331 Wykonywanie operacji na wszystkich elementach sekwencji..................................332 Algorytmy numeryczne ............................................................................................339 Narzędzia ..................................................................................................................342 Tworzenie własnych algorytmów uogólnionych ............................................................343 Podsumowanie ................................................................................................................345 Ćwiczenia ........................................................................................................................345 Rozdział 7. Kontenery...................................................................................... 351 Kontenery i iteratory .......................................................................................................351 Dokumentacja biblioteki STL...................................................................................353 Wprowadzenie.................................................................................................................353 Kontenery przechowujące ciągi znakowe.................................................................358 Dziedziczenie po kontenerach STL ..........................................................................360 Kraina iteratorów.............................................................................................................362 Iterator w kontenerach dwukierunkowych................................................................364 Kategorie iteratorów .................................................................................................365 Iteratory predefiniowane...........................................................................................367 Kontenery sekwencyjne: vector, list i deque...................................................................373 Podstawowe operacje na kontenerach sekwencyjnych .................................................373 Kontener typu vector.................................................................................................376 Kontener typu deque .................................................................................................383 Konwersja sekwencji ................................................................................................385 Kontrolowany dostęp swobodny...............................................................................387 Kontener typu list......................................................................................................388 Wymienianie całych sekwencji.................................................................................393 Kontener typu set ............................................................................................................394 Klasa iteratora słów...................................................................................................397 Szablon stack...................................................................................................................402 Szablon queue .................................................................................................................405 Kolejki priorytetowe .......................................................................................................410 Przechowywanie bitów ...................................................................................................418 Typ bitset<n> ............................................................................................................419 Typ vector<bool> .....................................................................................................422 Kontenery asocjacyjne ....................................................................................................424 Generowanie elementów i wypełnianie kontenerów asocjacyjnych ........................428 Magia kontenerów typu map ....................................................................................431 Kontener typu multimap ...........................................................................................433 Kontener typu multiset..............................................................................................436
  • 6. Spis treści 9 Korzystanie z wielu kontenerów STL.............................................................................439 Czyszczenie kontenera wskaźników ...............................................................................442 Tworzenie własnych kontenerów....................................................................................444 Rozszerzenia biblioteki STL ...........................................................................................446 Kontenery spoza STL......................................................................................................448 Podsumowanie ................................................................................................................452 Ćwiczenia ........................................................................................................................453 Część III Zagadnienia zaawansowane .........................................457 Rozdział 8. Rozpoznawanie typu w czasie wykonania programu......................... 459 Rzutowanie w czasie wykonania.....................................................................................459 Operator typeid................................................................................................................464 Rzutowanie na pośrednie poziomy hierarchii klas ...................................................466 Wskaźniki na typ void ..............................................................................................467 RTTI a szablony........................................................................................................468 Wielodziedziczenie .........................................................................................................469 Zastosowania mechanizmu RTTI....................................................................................470 Sortownia odpadków ................................................................................................471 Implementacja i narzuty mechanizmu RTTI...................................................................475 Podsumowanie ................................................................................................................475 Ćwiczenia ........................................................................................................................476 Rozdział 9. Wielodziedziczenie ......................................................................... 479 Wprowadzenie do wielodziedziczenia ............................................................................479 Dziedziczenie interfejsu ..................................................................................................481 Dziedziczenie implementacji ..........................................................................................484 Duplikaty podobiektów ...................................................................................................489 Wirtualne klasy bazowe ..................................................................................................493 Wyszukiwanie nazw........................................................................................................502 Unikanie wielodziedziczenia...........................................................................................504 Rozszerzanie interfejsu ...................................................................................................506 Podsumowanie ................................................................................................................509 Ćwiczenia ........................................................................................................................510 Rozdział 10. Wzorce projektowe ........................................................................ 513 Pojęcie wzorca.................................................................................................................513 Wy szość kompozycji nad dziedziczeniem..............................................................515 Klasyfikacja wzorców .....................................................................................................515 Właściwości, pojęcia, wzorce ...................................................................................516 Upraszczanie pojęć..........................................................................................................516 Posłaniec ...................................................................................................................517 Parametr zbiorczy .....................................................................................................518 Singleton..........................................................................................................................519 Odmiany Singletona..................................................................................................520 Polecenie — wybór operacji ...........................................................................................524 Polecenia izolujące obsługę zdarzeń.........................................................................526 Izolowanie obiektów .......................................................................................................529 Pośrednik — dostęp do innego obiektu ....................................................................529 Stan — modyfikowanie czynności obiektu ..............................................................531 Adapter ............................................................................................................................532 Metoda szablonowa.........................................................................................................535 Strategia — dynamiczny wybór algorytmu ....................................................................536 Łańcuch odpowiedzialności — wypróbowywanie sekwencji strategii ................................537
  • 7. 10 Thinking in C++. Edycja polska. Tom 2 Fabryki — hermetyzacja procesu tworzenia obiektu......................................................540 Fabryki polimorficzne...............................................................................................542 Fabryka abstrakcyjna ................................................................................................545 Konstruktory wirtualne .............................................................................................547 Builder — tworzenie zło onych obiektów .........................................................................552 Obserwator ......................................................................................................................558 Pojęcie klasy wewnętrznej........................................................................................561 Przykład zastosowania Obserwatora.........................................................................564 Dyspozycja wielokrotna..................................................................................................567 Wielokrotna dyspozycja z wzorcem Wizytator ........................................................571 Podsumowanie ................................................................................................................575 Ćwiczenia ........................................................................................................................575 Rozdział 11. Współbieżność............................................................................... 579 Motywacja.......................................................................................................................580 Współbie ność w języku C++.........................................................................................582 Instalacja biblioteki ZThread ....................................................................................582 Definiowanie zadań.........................................................................................................584 Klasa Thread ...................................................................................................................585 Tworzenie interfejsu u ytkownika o krótkim czasie odpowiedzi.............................587 Uproszczenie kodu z wykorzystaniem Wykonawców .............................................589 Tymczasowe zawieszanie działania wątków ............................................................592 Usypianie wątków.....................................................................................................594 Priorytety wątków.....................................................................................................595 Współdzielenie ograniczonych zasobów............................................................................597 Gwarantowanie istnienia obiektów...........................................................................597 Niewłaściwe odwołania do zasobów ........................................................................601 Kontrola dostępu.......................................................................................................603 Uproszczenie kodu z wykorzystaniem Stra ników ..................................................605 Pamięć lokalna wątku ...............................................................................................608 Zatrzymywanie zadań .....................................................................................................610 Zapobieganie kolizji odwołań do strumieni wejścia-wyjścia ...................................610 Ogród botaniczny......................................................................................................611 Zatrzymywanie zadań zablokowanych .....................................................................616 Przerwanie.................................................................................................................617 Współpraca wątków ........................................................................................................623 Oczekiwanie i nadawanie sygnałów .........................................................................623 Zale ności typu producent-konsument .....................................................................627 Rozwiązywanie problemów wielowątkowości przez kolejkowanie.........................630 Sygnalizacja rozgłoszeniowa ....................................................................................635 Zakleszczenie ..................................................................................................................641 Podsumowanie ................................................................................................................647 Ćwiczenia ........................................................................................................................649 Dodatki .......................................................................................653 Dodatek A Zalecana lektura ........................................................................... 655 Język C++........................................................................................................................655 Ksią ki Bruce’a Eckela.............................................................................................656 Ksią ki Chucka Allisona...........................................................................................657 Zaawansowane omówienia języka C++..........................................................................658 Ksią ki o wzorcach projektowych ..................................................................................660 Dodatek B Uzupełnienie .................................................................................. 661 Skorowidz...................................................................................... 667
  • 8. Rozdział 5. Wszystko o szablonach Szablony C++ to zdecydowanie więcej ni „kontenery zmiennych typu T”. Wpraw- dzie początkowo chodziło o stworzenie bezpiecznych ze względu na typy, ogólnych kontenerów, ale we współczesnym C++ szablony słu ą te do generowania specjali- zowanego kodu i optymalizowania wykonania programu ju na etapie kompilacji po- przez u ycie specyficznych konstrukcji programistycznych. W niniejszym rozdziale Czytelnik będzie mógł się praktycznie zapoznać z mo liwo- ściami (i pułapkami) programowania za pomocą szablonów C++. Obszerniejszą analizę odpowiednich zagadnień języka oraz pułapek znaleźć mo na w doskonałej ksią ce Davida Vandevoorde’a i Nico Josuttisa1. Parametry szablonów Jak ju powiedzieliśmy w pierwszym tomie, szablony mają dwie odmiany i występują jako: szablony funkcji i szablony klas. Jedne i drugie są w całości opisane swoimi pa- rametrami. Ka dy parametr szablonu sam mo e być: 1. Typem (wbudowanym lub zdefiniowanym przez u ytkownika). 2. Stałą w chwili kompilacji (na przykład liczby całkowite, wskaźniki i referencje danych statycznych; często określa się takie stałe jako parametry niebędące typami). 3. Innym szablonem. Wszystkie przykłady z pierwszego tomu nale ą do pierwszej kategorii i takie parametry występują najczęściej. Klasycznym przykładem prostego szablonu będącego kontenerem jest klasa Stack (Stos). Jako kontener obiekt Stack nie dba o to, jakiego typu obiekty zawiera; sposób przechowywania tych obiektów nie zmienia się zale nie od ich typu. Z tego powodu mo na u yć parametru będącego typem do opisania typu obiektów prze- chowywanych na stosie: 1 Vandevoorde i Josuttis, C++. Szablony. Vademecum profesjonalisty, Helion, 2003.
  • 9. 188 Część II ♦ Standardowa biblioteka C++ VGORNCVGENCUU 6 ENCUU 5VCEM ] 6
  • 10. FCVC UKGAV EQWPV RWDNKE XQKF RWUJ EQPUV 6 V KVF _ Konkretny typ, który w danym stosie ma być u yty, podaje się jako argument odpo- wiadający parametrowi T: 5VCEMKPV O[5VCEM UVQU NKED EC MQYKV[EJ KPV Kompilator u ywa obiektu Stack dostosowanego do typu int przez podstawienie int pod T i wygenerowanie odpowiedniego kodu. Nazwa instancji klasy wygenerowanej na podstawie tego szablonu to Stackint. Parametry szablonów niebędące typami Mo na te u ywać parametrów szablonów niebędących typami, o ile tylko odpowiadają one liczbom całkowitym znanym na etapie kompilacji. Mo na, na przykład, stworzyć stos o ustalonej wielkości, przekazując parametr niebędący typem, odpowiadający wielkości tablicy u ytej do implementacji tego stosu: VGORNCVGENCUU 6 UKGAV 0 ENCUU 5VCEM ] 6 FCVC=0? 0 VQ WUVCNQPC RQLGOPQ è UKGAV EQWPV RWDNKE XQKF RWUJ EQPUV 6 V KVF _ Podczas tworzenia instancji takiego szablonu musisz podać wartość stałą znaną pod- czas kompilacji, która będzie u yta jako wartość parametru N: 5VCEMKPV O[(KZGF5VCEM Wartość N jest znana ju na etapie kompilacji, więc tablica data mo e zostać umiesz- czona na stosie, a nie w pamięci wymagającej alokowania, co mo e przyspieszyć działanie programu dzięki uniknięciu opóźnień związanych z dynamiczną alokacją pamięci. Zgodnie z przedstawioną wcześniej zasadą, nazwą uzyskanej w ten sposób klasy będzie Stackint, 100. Oznacza to, e ka da kolejna wartość N powoduje utworzenie innego typu klasy. Na przykład klasa Stackint, 99 to klasa inna ni Stackint, 100. Szablon klasy bitset, szczegółowo omawiany w rozdziale 7., to jedyna klasa standar- dowej biblioteki C++, w której u ywany jest parametr szablonu niebędący typem; pa- rametr ten określa liczbę bitów, jakie mo e przechowywać obiekt bitset. Poni szy przykładowy generator liczb losowych u ywa obiektu bitset do śledzenia liczb tak, aby wszystkie liczby w danym zakresie były zwracane w losowej kolejności bez po- wtórzeń tak długo, a u yte zostaną wszystkie liczby. Poni szy przykład pokazuje tak e przecią enie funkcji operator() w celu uzyskania składni podobnej do wywoła- nia funkcji:
  • 11. Rozdział 5. ♦ Wszystko o szablonach 189 %7TCPFJ ]DQT_ .QUQYG IGPGTQYCPKG NKED DG RQYVÎTG KHPFGH 74#0A* FGHKPG 74#0A* KPENWFG DKVUGV KPENWFG EUVFFGH KPENWFG EUVFNKD KPENWFG EVKOG WUKPI UVFUKGAV WUKPI UVFDKVUGV VGORNCVGUKGAV 7RRGT$QWPF ENCUU 7TCPF ] DKVUGV7RRGT$QWPF WUGF RWDNKE 7TCPF ] UTCPF VKOG .QUQYQ _ UKGAV QRGTCVQT (WPMELC IGPGTCVQT _ VGORNCVGUKGAV 7RRGT$QWPF KPNKPG UKGAV 7TCPF7RRGT$QWPF QRGTCVQT ] KH WUGFEQWPV 7RRGT$QWPF WUGFTGUGV K QF PQYC Y[E[ è DKVUGV UKGAV PGYXCN YJKNG WUGF=PGYXCN TCPF 7RRGT$QWPF? C FQ PCNGKGPKC PKGRQYVCTCNPGL YCTVQ EK WUGF=PGYXCN? VTWG TGVWTP PGYXCN _ GPFKH 74#0A* ` Niepowtarzalność w klasie Urand uzyskujemy dzięki śledzeniu w zbiorze bitset wszystkich liczb, jakie występują w zakresie (górne ograniczenie tego zakresu poda- wane jest jako argument szablonu) i rejestrując u ycie ka dej liczby przez ustawienie odpowiedniego bitu w strukturze used. Kiedy wszystkie liczby zostaną u yte, zbiór bitset jest czyszczony i losowanie odbywa się od nowa. Oto prosty przykład u ycia obiektu Urand: %7TCPF6GUVERR ]DQT_ KPENWFG KQUVTGCO KPENWFG 7TCPFJ WUKPI PCOGURCEG UVF KPV OCKP ] 7TCPF W HQT KPV K K K EQWV W _ ` Jak jeszcze powiemy dalej, argumenty szablonów niebędące typami są wa ne w przypadku optymalizowania obliczeń numerycznych.
  • 12. 190 Część II ♦ Standardowa biblioteka C++ Domyślne argumenty szablonów Parametrom szablonu klasy mo na przypisać argumenty domyślne (niedopuszczalne jest ich stosowanie w przypadku szablonów funkcji). Tak jak w przypadku argumen- tów domyślnych funkcji powinno się je definiować tylko raz, w pierwszej deklaracji lub definicji widzianej przez kompilator. Kiedy jakiś argument domyślny zostanie ju zdefiniowany, wszystkie dalsze szablony te muszą mieć wartości domyślne. Aby pokazana powy ej klasa stosu o ustalonej wielkości była łatwiejsza w u yciu, mo na dodać do niej argument domyślny: VGORNCVGENCUU 6 UKGAV 0 ENCUU 5VCEM ] 6 FCVC=0? 0 VQ WUVCNQPC RQLGOPQ è UKGAV EQWPV RWDNKE XQKF RWUJ EQPUV 6 V KVF _ Teraz, jeśli podczas deklarowania obiektu Stack pominięty zostanie drugi argument szablonu, wartość N domyślnie będzie równa 100. Mo na te podać wartości domyślne dla wszystkich argumentów, ale wtedy i tak podczas deklarowania instancji szablonu trzeba będzie u yć pustej pary nawiasów, aby kompilator „wiedział”, e chodzi o szablon klasy: VGORNCVGENCUU 6 KPV UKGAV 0 QDC CTIWOGPV[ FQO[ NPG ENCUU 5VCEM ] 6 FCVC=0? 0 VQ WUVCNQPC RQLGOPQ è UKGAV EQWPV RWDNKE XQKF RWUJ EQPUV 6 V KVF _ 5VCEM O[5VCEM TÎYPQYC PG 5VCEMKPV Argumenty domyślne są intensywnie wykorzystywane w standardowej bibliotece C++. Przykładowo szablon klasy vector zadeklarowany został następująco: VGORNCVG ENCUU 6 ENCUU #NNQECVQT CNNQECVQT6 ENCUU XGEVQT Zwróć uwagę na spację między dwoma zamykającymi nawiasami kątowymi. Dzięki niej kompilator nie zinterpretuje tych dwóch znaków () jako operatora przesunięcia w prawo. Z powy szej deklaracji wynika, e szablon vector tak naprawdę ma dwa argumenty: typ przechowywanych obiektów oraz typ odpowiadający alokatorowi u ywanemu w wektorze (więcej o alokatorach powiemy w rozdziale 7.) Jeśli drugi argument zostanie pominięty, u yty zostanie standardowy szablon allocator sparametryzowany pierwszym parametrem szablonu. Z deklaracji wynika te , e w kolejnych parametrach szablonów mo na u ywać parametrów poprzednich — tutaj tak u yto parametru T.
  • 13. Rozdział 5. ♦ Wszystko o szablonach 191 Wprawdzie w szablonach funkcji nie mo na u ywać domyślnych argumentów sza- blonu, ale parametrów szablonów mo na u ywać jako argumentów domyślnych zwy- kłych funkcji. Poni szy szablon funkcji sumuje elementy sekwencji: %(WPEGHERR KPENWFG KQUVTGCO WUKPI PCOGURCEG UVF VGORNCVGENCUU 6 6 UWO 6
  • 14. D 6
  • 15. G 6 KPKV 6 ] YJKNG D G KPKV
  • 16. D TGVWTP KPKV _ KPV OCKP ] KPV C=? ]_ EQWV UWO C C UKGQH C UKGQH C=? GPFN _ ` Trzeci argument sum() jest wartością początkową dla sumy elementów. Argument ten jest pominięty, więc domyślnie wynosi T(); w przypadku typu int i innych typów wbudowa- nych pseudokonstruktor realizuje inicjalizację zerem. Szablony jako parametry szablonów Trzeci rodzaj parametrów, jakich mo na u yć w szablonie, to inny szablon klasy. Mo e to wydawać się dziwne, gdy szablony są typami, a parametry będące typami są dozwolo- ne; jeśli jednak w kodzie szablonu jako parametr ma być u yty inny szablon, kompi- lator musi najpierw „wiedzieć”, e parametrem jest właśnie szablon. Poni szy przy- kład pokazuje u ycie szablonu jako parametru innego szablonu: %6GOR6GORERR 2QMCWLG W [EKG UCDNQPW LCMQ RCTCOGVTW UCDNQPW KPENWFG EUVFFGH KPENWFG KQUVTGCO WUKPI PCOGURCEG UVF VGORNCVGENCUU 6 ENCUU #TTC[ ] Y[M [ EKæI FCLæE[ UKú RTGF W Cè GPWO ]+0+6 _ 6
  • 17. FCVC UKGAV ECRCEKV[ UKGAV EQWPV RWDNKE #TTC[ ] EQWPV FCVC PGY 6=ECRCEKV[ +0+6? _ `#TTC[ ] FGNGVG =? FCVC _ XQKF RWUJADCEM EQPUV 6 V ] KH EQWPV ECRCEKV[ ] 2QYKúMUGPKG VCDNKE[ DCQYGL UKGAV PGY%CR
  • 19. 192 Część II ♦ Standardowa biblioteka C++ 6
  • 20. PGYCVC PGY 6=PGY%CR? HQT UKGAV K K EQWPV K PGYCVC=K? FCVC=K? FGNGVG FCVC FCVC PGYCVC ECRCEKV[ PGY%CR _ FCVC=EQWPV ? V _ XQKF RQRADCEM ] KH EQWPV EQWPV _ 6
  • 21. DGIKP ] TGVWTP FCVC _ 6
  • 22. GPF ] TGVWTP FCVC EQWPV _ _ VGORNCVGENCUU 6 VGORNCVGENCUU ENCUU 5GS ENCUU %QPVCKPGT ] 5GS6 UGS RWDNKE XQKF CRRGPF EQPUV 6 V ] UGSRWUJADCEM V _ 6
  • 23. DGIKP ] TGVWTP UGSDGIKP _ 6
  • 24. GPF ] TGVWTP UGSGPF _ _ KPV OCKP ] %QPVCKPGTKPV #TTC[ EQPVCKPGT EQPVCKPGTCRRGPF EQPVCKPGTCRRGPF KPV
  • 25. R EQPVCKPGTDGIKP YJKNG R EQPVCKPGTGPF EQWV
  • 26. R GPFN _ ` Szablon klasy Array to najzwyklejszy kontener zawierający sekwencję elementów. Szablon Container ma dwa parametry: typ przechowywanych obiektów oraz struktu- rę danych słu ącą do przechowywania danych. Poni szy wiersz implementacji klasy Container wymusza poinformowanie kompilatora, e parametr Seq jest szablonem: 5GS6 UGS Gdybyśmy nie zadeklarowali Seq jako parametru będącego szablonem, kompilator zgłosi błąd, twerdząc, e Seq nie jest szablonem, a jako takiego go u ywamy. W funkcji main() tworzona jest instancja szablonu Container w ten sposób, w klasie Array przecho- wywane były liczby całkowite — zatem w tym przykładzie Seq oznacza Array.
  • 27. Rozdział 5. ♦ Wszystko o szablonach 193 Zauwa , e w tym wypadku nie jest konieczne nazywanie parametru Seq w deklaracji Container. Odpowiedni wiersz to: VGORNCVGENCUU 6 VGORNCVGENCUU ENCUU 5GS Wprawdzie moglibyśmy zapisać: VGORNCVGENCUU 6 VGORNCVGENCUU 7 ENCUU 5GS lecz parametr U nie jest w ogóle potrzebny. Wszystko, co istotne, to to, e Seq jest szablonem klasy mającym pojedynczy parametr będący typem. Jest to analogia do pomijania nazw parametrów funkcji, kiedy nie są potrzebne, na przykład przy prze- cią aniu operatora postinkrementacji: 6 QRGTCVQT KPV Słowo kluczowe int jest potrzebne jedynie ze względów formalnych, więc odpowia- dający mu argument nie musi mieć nazwy. Poni szy program korzysta z tablicy o ustalonej wielkości mającej dodatkowy para- metr szablonu odpowiadający wielkości tej tablicy: %6GOR6GORERR 9KGNQOKGPP[ UCDNQP LCMQ RCTCOGVT UCDNQPW KPENWFG EUVFFGH KPENWFG KQUVTGCO WUKPI PCOGURCEG UVF VGORNCVGENCUU 6 UKGAV 0 ENCUU #TTC[ ] 6 FCVC=0? UKGAV EQWPV RWDNKE #TTC[ ] EQWPV _ XQKF RWUJADCEM EQPUV 6 V ] KH EQWPV 0 FCVC=EQWPV ? V _ XQKF RQRADCEM ] KH EQWPV EQWPV _ 6
  • 28. DGIKP ] TGVWTP FCVC _ 6
  • 29. GPF ] TGVWTP FCVC EQWPV _ _ VGORNCVGENCUU 6UKGAV 0VGORNCVGENCUUUKGAV ENCUU 5GS ENCUU %QPVCKPGT ] 5GS60 UGS RWDNKE XQKF CRRGPF EQPUV 6 V ] UGSRWUJADCEM V _ 6
  • 30. DGIKP ] TGVWTP UGSDGIKP _ 6
  • 31. GPF ] TGVWTP UGSGPF _ _ KPV OCKP ] EQPUV UKGAV 0 %QPVCKPGTKPV 0 #TTC[ EQPVCKPGT
  • 32. 194 Część II ♦ Standardowa biblioteka C++ EQPVCKPGTCRRGPF EQPVCKPGTCRRGPF KPV
  • 33. R EQPVCKPGTDGIKP YJKNG R EQPVCKPGTGPF EQWV
  • 34. R GPFN _ ` Znowu nazwy parametrów w deklaracji Seq wewnątrz deklaracji Containter są zbędne, ale potrzebne są dwa dodatkowe parametry do zadeklarowania pola seq, stąd na najwy - szym poziomie pojawia się parametr N niebędący typem. Łączenie argumentów domyślnych z parametrami szablonów będących szablonami jest nieco bardziej problematyczne. Kiedy kompilator sprawdza parametr wewnętrzny parametru szablonu, nie są uwzględniane argumenty domyślne, wobec czego w celu uzyskania dokładnego dopasowania konieczne jest powtórzenie wartości domyślnych. Poni szy przykład wykorzystuje argument domyślny do szablonu Array o stałej wielko- ści, pokazuje te , jak sobie z tym dziwactwem języka radzić: %6GOR6GORERR ]DQT_ ]OUE_ æEGPKG RCTCOGVTÎY UCDNQPÎY DúFæE[EJ UCDNQPCOK CTIWOGPVCOK FQO[ NP[OK KPENWFG EUVFFGH KPENWFG KQUVTGCO WUKPI PCOGURCEG UVF VGORNCVGENCUU 6 UKGAV 0 #TIWOGPV FQO[ NP[ ENCUU #TTC[ ] 6 FCVC=0? UKGAV EQWPV RWDNKE #TTC[ ] EQWPV _ XQKF RWUJADCEM EQPUV 6 V ] KH EQWPV 0 FCVC=EQWPV ? V _ XQKF RQRADCEM ] KH EQWPV EQWPV _ 6
  • 35. DGIKP ] TGVWTP FCVC _ 6
  • 36. GPF ] TGVWTP FCVC EQWPV _ _ VGORNCVGENCUU 6 VGORNCVGENCUU UKGAV ENCUU 5GS ENCUU %QPVCKPGT ] 5GS6 UGS 7 [VQ CTIWOGPVW FQO[ NPGIQ RWDNKE XQKF CRRGPF EQPUV 6 V ] UGSRWUJADCEM V _ 6
  • 37. DGIKP ] TGVWTP UGSDGIKP _ 6
  • 38. GPF ] TGVWTP UGSGPF _ _ KPV OCKP ] %QPVCKPGTKPV #TTC[ EQPVCKPGT EQPVCKPGTCRRGPF
  • 39. Rozdział 5. ♦ Wszystko o szablonach 195 EQPVCKPGTCRRGPF KPV
  • 40. R EQPVCKPGTDGIKP YJKNG R EQPVCKPGTGPF EQWV
  • 41. R GPFN _ ` W poni szym wierszu trzeba włączyć domyślną wielkość równą 10: VGORNCVGENCUU 6 VGORNCVGENCUU UKGAV ENCUU 5GS Obie definicje, seq w Container i container, w main() wykorzystują wartości do- myślne. Jedynym sposobem u ycia czegokolwiek innego ni wartość domyślna jest sko- rzystanie z metody z poprzedniego programu, TempTemp2.cpp. Jest to jedyny wyją- tek od podanej wcześniej zasady mówiącej, e argumenty domyślne powinny pojawiać się w danej jednostce kompilacji tylko raz. Wobec faktu, e wszystkie standardowe kontenery przechowujące elementy w formie sekwencji (vector, list oraz deque omówiono dokładnie w rozdziale 7.) mają domyślny argument allocator, powy sza technika jest przydatna, jeśli trzeba jedną z tych trzech metod uporządkowania przekazać jako parametr szablonu. W poni szym programie vector i list są przekazywane do dwóch instancji szablonu Container. %6GOR6GORERR ]DQT_ ]OUE_ 2TGMCCPKG UVCPFCTFQY[EJ UGMYGPELK LCMQ CTIWOGPVÎY UCDNQPW KPENWFG KQUVTGCO KPENWFG NKUV KPENWFG OGOQT[ GMNCTCELC CNNQECVQT6 KPENWFG XGEVQT WUKPI PCOGURCEG UVF VGORNCVGENCUU 6 VGORNCVGENCUU 7 ENCUU CNNQECVQT7 ENCUU 5GS ENCUU %QPVCKPGT ] 5GS6 UGS 0KGLCYPKG UVQUQYCPG LGUV FQO[ NPG CNNQECVQT6 RWDNKE XQKF RWUJADCEM EQPUV 6 V ] UGSRWUJADCEM V _ V[RGPCOG 5GS6 KVGTCVQT DGIKP ] TGVWTP UGSDGIKP _ V[RGPCOG 5GS6 KVGTCVQT GPF ] TGVWTP UGSGPF _ _ KPV OCKP ] 7 [L YGMVQTC %QPVCKPGTKPV XGEVQT X%QPVCKPGT X%QPVCKPGTRWUJADCEM X%QPVCKPGTRWUJADCEM HQT XGEVQTKPV KVGTCVQT R X%QPVCKPGTDGIKP R X%QPVCKPGTGPF R ] EQWV
  • 42. R GPFN _ 7 [L NKUV[ %QPVCKPGTKPV NKUV N%QPVCKPGT N%QPVCKPGTRWUJADCEM N%QPVCKPGTRWUJADCEM
  • 43. 196 Część II ♦ Standardowa biblioteka C++ HQT NKUVKPV KVGTCVQT R N%QPVCKPGTDGIKP R N%QPVCKPGTGPF R ] EQWV
  • 44. R GPFN _ _ ` W tym wypadku nazwaliśmy pierwszy parametr szablonu wewnętrznego Seq (ta na- zwa to U), gdy alokatory w standardowych sekwencjach muszą być sparametryzo- wane tym samym typem, co obiekt ich u ywający. Poza tym, skoro domyślna wartość parametru allocator jest znana, mo emy ją pominąć w dalszych odwołaniach do SeqT, jak w poprzednim programie. Jednak dokładne omówienie tego przykładu wymaga objaśnienia znaczenia słowa kluczowego typename. Słowo kluczowe typename Niech będzie dany program: %6[RGPCOGF+ERR ]DQT_ 5 QYQ V[RGPCOG W [YCPG LGUV LCMQ RTGHKMU V[RÎY CIPKG F QP[EJ VGORNCVGENCUU 6 ENCUU : ] )F[D[ PKG D[ Q V[RGPCOG RQYUVC D[ VW D æF V[RGPCOG 6KF K RWDNKE XQKF H ] KI _ _ ENCUU ; ] RWDNKE ENCUU KF ] RWDNKE XQKF I ]_ _ _ KPV OCKP ] :; Z[ Z[H _ ` W definicji szablonu zakłada się, e klasa T musi mieć pewnego rodzaju zagnie d ony identyfikator id. Jednak id mo e być te statycznym polem T (a wtedy mo na byłoby na id wykonywać operacje bezpośrednio), natomiast nie mo na „tworzyć obiektu typu id”. Jednak właśnie to się tu dzieje — identyfikator id jest traktowany tak, jakby był typem zagnie d onym w T. W przypadku klasy Y id jest faktycznie typem zagnie d onym, ale bez słowa kluczowego typename kompilator nie wiedziałby o tym w chwili kompi- lowania X. Jeśli kompilator umo liwia traktowanie identyfikatora występującego w szablonie jako typu lub jako czegoś innego ni typ, przyjmie, e identyfikator jest czymś innym ni typ, czyli zało y, e identyfikator odnosi się do obiektu (przy czym dane typów pro- stych te są traktowane jako obiekty), wyliczenia lub czegoś podobnego. Jednak kompilator nie zało y, i nie mo e zało yć, e jest to typ.
  • 45. Rozdział 5. ♦ Wszystko o szablonach 197 Wobec tego, e domyślne działanie kompilatora powoduje, e we wskazanych wy ej dwóch miejscach nie chodzi o typ, trzeba u yć słowa kluczowego typename dla nazw zagnie d onych (wyjątkiem są listy inicjalizujące konstruktora, gdzie nie jest to ani potrzebne, ani dozwolone). W powy szym przykładzie kompilator widząc typename T::id, „wie” (dzięki słowu kluczowemu typename), e id odnosi się do typu zagnie d o- nego, więc mo e stworzyć obiekt tego typu. Cała ta zasada w formie skróconej brzmi: jeśli typ odnoszący się do kodu wewnątrz szablonu jest kwalifikowany parametrem szablonu będącym typem, powinien być po- przedzony słowem kluczowym typename, chyba e występuje w specyfikacji klasy bazowej lub na liście inicjalizacyjnej w tym samym zakresie (w obu tych przypadkach słowa tego nie mo na u yć). Powy sza dyskusja całkowicie objaśnia u ycie słowa kluczowego typename w pro- gramie TempTemp4.cpp. Bez tego słowa kluczowego kompilator zało yłby, e wy- ra enie SeqT::iterator nie jest typem, podczas gdy dalej u ywane jest ono do zde- finiowania wartości zwracanej przez funkcje begin() i end(). W następnym przykładzie, zawierającym szablon funkcji pozwalający wydrukować dowolną standardową sekwencję C++, pokazano podobny sposób u ycia typename: %2TKPV5GSERR ]OUE_ (WPMELC FTWMWLæEC V[RQYG UGMYGPELG % KPENWFG KQUVTGCO KPENWFG NKUV KPENWFG OGOQT[ KPENWFG XGEVQT WUKPI PCOGURCEG UVF VGORNCVGENCUU 6 VGORNCVGENCUU 7 ENCUU CNNQECVQT7 ENCUU 5GS XQKF RTKPV5GS 5GS6 UGS ] HQT V[RGPCOG 5GS6 KVGTCVQT D UGSDGIKP D UGSGPF EQWV
  • 46. D GPFN _ KPV OCKP ] 2TGVYCTCPKG YGMVQTC XGEVQTKPV X XRWUJADCEM XRWUJADCEM RTKPV5GS X 2TGVYCTCPKG NKUV[ NKUVKPV NUV NUVRWUJADCEM NUVRWUJADCEM RTKPV5GS NUV _ ` Znowu, gdyby nie słowo kluczowe typename, kompilator zinterpretowałby iterator jako statyczne pole nale ące do SeqT, czyli byłby to błąd składniowy — przecie typ jest wymagany.
  • 47. 198 Część II ♦ Standardowa biblioteka C++ Typedef i typename Nie wolno zakładać, e słowo kluczowe typename utworzy nową nazwę typu. Celem stosowania tego słowa jest wskazanie kompilatorowi, e tak zakwalifikowany identy- fikator ma być zinterpretowany jako typ. Wiersz: V[RGPCOG 5GS6 KVGTCVQT +V mówi, e zmienna It jest zmienną typu SeqT::iterator. Jeśli nale ałoby stworzyć nazwę nowego typu, jak zwykle trzeba u yć typedef: V[RGFGH V[RGPCOG 5GS+V KVGTCVQT +V Użycie typename zamiast class Innym zastosowaniem słowa kluczowego typename jest mo liwość u ycia typename zamiast class na liście argumentów szablonu. Czasami powstający kod jest dzięki temu czytelniejszy: %7UKPI6[RGPCOGERR 7 [EKG V[RGPCOG PC NK EKG CTIWOGPVÎY UCDNQPW VGORNCVGV[RGPCOG 6 ENCUU : ] _ KPV OCKP ] :KPV Z _ ` Prawdopodobnie nieczęsto spotkasz się z takim u yciem słowa kluczowego typename, gdy słowo to zostało dodane do języka dość długo po zdefiniowaniu szablonów. Użycie słowa kluczowego template jako wskazówki Tak jak słowo kluczowe typename pomaga kompilatorowi w sytuacjach, kiedy nie spodziewa się on identyfikatora typu, istnieje te potencjalna trudność związana z lekse- mami niebędącymi identyfikatorami, jak znaki i ; czasami oznaczają one symbole mniejszości i większości, a czasami ograniczają listy parametrów szablonu. W ramach przykładu skorzystajmy jeszcze raz z klasy bitset: %QV6GORNCVGERR 2QMCWLG W [EKG MQPUVTWMELK VGORNCVG KPENWFG DKVUGV KPENWFG EUVFFGH KPENWFG KQUVTGCO KPENWFG UVTKPI WUKPI PCOGURCEG UVF VGORNCVGENCUU EJCT6 UKGAV 0 DCUKEAUVTKPIEJCT6 DKVUGV6Q5VTKPI EQPUV DKVUGV0 DU ] TGVWTP DU VGORNCVG VQAUVTKPIEJCT6 EJCTAVTCKVUEJCT6 CNNQECVQTEJCT6 _
  • 48. Rozdział 5. ♦ Wszystko o szablonach 199 KPV OCKP ] DKVUGV DU DUUGV DUUGV EQWV DU GPFN UVTKPI U DKVUGV6Q5VTKPIEJCT DU EQWV U GPFN _ ` Klasa bitset realizuje konwersję na obiekt-łańcuch za pomocą funkcji składowej to_st- ring. Aby obsłu yć ró ne klasy łańcuchów, to_string sama jest szablonem, zgodnie z definicją szablonu basic_string omawianą w rozdziale 3. Deklaracja to_string w ramach bitset wygląda następująco: VGORNCVG ENCUU EJCT6 ENCUU VTCKVU ENCUU #NNQECVQT DCUKEAUVTKPIEJCT6 VTCKVU #NNQECVQT VQAUVTKPI EQPUV Nasz pokazany powy szej szablon funkcji bitsetToString() pozwala zwracać obiekty bitset jako ró nego rodzaju łańcuchy znaków. Aby uzyskać, na przykład, łańcuch z szero- kimi znakami, nale y wywołanie zapisać następująco: YUVTKPI U DKVUGV6Q5VTKPIYEJCTAV DU Zauwa , e basic_string korzysta z domyślnych argumentów szablonu, więc nie mu- simy powtarzać argumentów char_traits i allocator w wartości zwracanej. Niestety, bitset::to_string nie u ywa argumentów domyślnych. U ycie bitsetToStringchar(bs) jest wygodniejsze ni pisanie za ka dym razem całego bs.template to_stringchar, char_traits, allocatorchar (). Instrukcja return w funkcji bitsetToString() zawiera słowo kluczowe template w dość dziwnym miejscu — zaraz po operatorze „kropka” zastosowanym do obiektu bs typu bitset. Wynika to stąd, e kiedy analizowany jest szablon, znak znajdujący się za napisem to_string zostałby interpretowany jako operator mniejszości, a nie początek lub lista argumentów szablonu. W punkcie „Odszukiwanie nazw” w dalszej części roz- działu słowo kluczowe template u yte w tym kontekście informuje kompilator, e dalej następuje nazwa szablonu; dzięki temu znak zostanie zinterpretowany prawidłowo. Takie samo rozumowanie dotyczy operatorów - i :: stosowanych do szablonów. Tak jak w przypadku słowa kluczowego template opisana technika unikania wieloznaczności mo e być u ywana jedynie w szablonach2. Szablony składowe Szablon funkcji bitset::to_string() jest przykładem szablonu składowego czyli szablonu zadeklarowanego w innej klasie lub szablonie klasy. Dzięki temu mo na tworzyć rozmaite kombinacje niezale nych argumentów szablonów. Praktyczny przykład znaleźć mo na w szablonie klas complex w standardowej bibliotece C++. Szablon complex ma pa- rametr będący typem, który pozwala zadeklarować typ zmiennoprzecinkowy słu ący 2 Komitet standaryzacyjny C++ rozwa a rezygnację z klauzuli „jedynie w szablonach”, jeśli chodzi o unikanie wieloznaczności. Niektóre kompilatory ju teraz pozwalają na stosowanie takich podpowiedzi poza szablonami.
  • 49. 200 Część II ♦ Standardowa biblioteka C++ do przechowywania części rzeczywistej i urojonej liczby zespolonej. Poni szy frag- ment kodu z biblioteki standardowej pokazuje konstruktor szablonu składowego sza- blonu klasy complex: VGORNCVGV[RGPCOG 6 ENCUU EQORNGZ ] RWDNKE VGORNCVGENCUU : EQORNGZ EQPUV EQORNGZ: Standardowy szablon complex ma ju gotowe specjalizacje z parametrem T o warto- ściach float, double oraz long double. Pokazany powy ej konstruktor szablonu skła- dowego pozwala stworzyć nową liczbę zespoloną wykorzystującą inny typ zmienno- przecinkowy jako typ bazowy, jak poni ej: EQORNGZHNQCV EQORNGZFQWDNG Y W deklaracji w parametr T szablonu complex ma wartość double, zaś X to float. Szablony składowe bardzo ułatwiają tego typu konwersje. Wobec tego, e definiowanie szablonu w szablonie jest operacją zagnie d enia, przedrostki oznaczające szablony muszą to zagnie d anie odzwierciedlać, jeśli tylko szablon składowy zostanie zdefiniowany poza definicją klasy zewnętrznej. Jeśli, na przykład, mamy zaimplementować szablon klasy complex i nale y zdefiniować kon- struktor szablonu składowego poza definicją klasy opartej na szablonie complex, trzeba byłoby zrobić to tak: VGORNCVGV[RGPCOG 6 VGORNCVGV[RGPCOG : EQORNGZ6 EQORNGZ EQPUV EQORNGZ: E ]
  • 51. _ Inne zastosowanie szablonów funkcji składowych w bibliotece standardowej to ini- cjalizacja kontenerów takich jak vector. Załó my, e mamy vector zawierający dane typu int i chcemy tym wektorem zainicjalizować nowy wektor z liczbami double: KPV FCVC=? ] _ XGEVQTKPV X FCVC FCVC XGEVQTFQWDNG X XDGIKP XGPF O ile tylko elementy v1 są zgodne co do przypisania z elementami v2 (a double i int w tym sensie są zgodne), wszystko działa prawidłowo. Szablon klasy vector ma na- stępujący konstruktor szablonu składowego: VGORNCVGENCUU +PRWV+VGTCVQT XGEVQT +PRWV+VGTCVQT HKTUV +PRWV+VGTCVQT NCUV EQPUV #NNQECVQT #NNQECVQT Taka konstrukcja tak naprawdę w deklaracjach wektora jest u yta dwukrotnie. Kiedy v1 jest inicjalizowane na podstawie tablicy liczb int, InputIterator jest typu int*. Kiedy v2 jest inicjalizowane na podstawie v1, InputIterator w instancji konstruktora szablonu składowego jest typu vectorint::iterator. Szablony składowe mogą być tak e klasami (nie muszą być funkcjami, choć zwykle to właśnie jest potrzebne). W następnym przykładzie pokazano szablon klasy składowej znajdujący się wewnątrz szablonu klasy zewnętrznej:
  • 52. Rozdział 5. ♦ Wszystko o szablonach 201 %/GODGT%NCUUERR 5CDNQP MNCU[ UM CFQYGL KPENWFG KQUVTGCO KPENWFG V[RGKPHQ WUKPI PCOGURCEG UVF VGORNCVGENCUU 6 ENCUU 1WVGT ] RWDNKE VGORNCVGENCUU 4 ENCUU +PPGT ] RWDNKE XQKF H _ _ VGORNCVGENCUU 6 VGORNCVG ENCUU 4 XQKF 1WVGT6 +PPGT4 H ] EQWV 1WVGT V[RGKF 6PCOG GPFN EQWV +PPGT V[RGKF 4PCOG GPFN EQWV 2G PC +PPGT V[RGKF
  • 53. VJKUPCOG GPFN _ KPV OCKP ] 1WVGTKPV +PPGTDQQN KPPGT KPPGTH _ ` Omawiany w rozdziale 8. operator typeid zwraca obiekt, którego funkcja składowa name() podaje zapisany jako łańcuch jego typ lub typ zmiennej. Wprawdzie dokładna postać tego łańcucha jest ró na w ró nych kompilatorach, ale wynik działania powy - szego programu będzie podobny do: 1WVGT KPV +PPGT DQQN 2G PC +PPGT 1WVGTKPV +PPGTDQQN Deklaracja zmiennej inner w programie głównym powoduje ukonkretnienie Innerbool i Outerint. Szablony funkcji składowych nie mogą być deklarowane jako wirtualne. Stosowane obecnie kompilatory „spodziewają się”, e będą w stanie określić wielkość tablicy funkcji wirtualnych klasy w chwili analizowania tej klasy. Umo liwienie stosowania wirtualnych szablonów funkcji składowych wymagałoby znajomości wszystkich wywołań takich funkcji składowych w programie, co jest niemo liwe, szczególnie w przypadku projektów zawierających wiele plików. Szablony funkcji Tak jak szablon klasy opisuje rodzinę klas, tak szablon funkcji opisuje rodzinę funkcji. Składnia tworzenia szablonów jednych i drugich jest w zasadzie identyczna, a ró nice dotyczą głównie sposobu u ycia. Podczas tworzenia instancji szablonu klas zawsze
  • 54. 202 Część II ♦ Standardowa biblioteka C++ trzeba stosować nawiasy kątowe i podawać wszystkie niedomyślne argumenty sza- blonu. Z kolei w przypadku szablonów funkcji często mo na pomijać argumenty sza- blonu, zaś domyślne argumenty szablonu są niedopuszczalne. Przyjrzyjmy się typo- wej implementacji szablonu funkcji min() zadeklarowanego w pliku nagłówkowym algorithm: VGORNCVGV[RGPCOG 6 EQPUV 6 OKP EQPUV 6 C EQPUV 6 D ] TGVWTP C D ! C D _ Szablon taki mo na wywołać, podając typ argumentów w nawiasach kątowych, tak jak w przypadku szablonów klas: KPV OKPKPV K L U ycie takiej składni informuje kompilator, e potrzebny jest szablon funkcji min z typem int u ytym zamiast parametru T, więc kompilator wygeneruje odpowiedni kod. Zgodnie z konwencją nazewniczą dotyczącą klas generowanych przez szablony klas mo na się spodziewać, e nazwą tak wywołanej funkcji będzie minint. Dedukowanie typu argumentów szablonu funkcji Zawsze mo na u yć jawnej specyfikacji szablonu funkcji jak powy ej, ale często wy- godnie byłoby pominąć argumenty szablonu i pozwolić kompilatorowi wywniosko- wać ich wartości na podstawie argumentów funkcji, na przykład tak: KPV OKP K L Jeśli i i j są liczbami int, kompilator „wie”, e potrzebna jest funkcja minint(), i do- konuje automatycznie odpowiedniego zastąpienia. Typy muszą być identyczne, gdy szablon pierwotnie zdefiniowany jest z jednym tylko argumentem określającym typ, u ywanym dla obu parametrów funkcji. W przypadku argumentów funkcji, których typ wynika z parametru szablonu, nie są wykonywane adne standardowe konwersje. Jeśli, na przykład, trzeba byłoby znaleźć mniejszą z liczb int i double, poni sza próba wywołania nie powiodłaby się: KPV OKP Z L Z LGUV V[RW FQWDNG Zmienne x i j mają ró ne typy, więc aden pojedynczy parametr T w szablonie min nie mo e zostać u yty, a wobec tego wywołanie jest niezgodne z deklaracją szablonu. Mo na tego problemu uniknąć, rzutując jeden argument na typ argumentu drugiego albo stosując wywołanie z pełną specyfikacją, na przykład: KPV OKPFQWDNG Z L W ten sposób kompilator „wie”, e ma wygenerować funkcję min() korzystającą z typu double, a wtedy ju zmienna j mo e w sposób standardowy przekształcona na typ double (gdy funkcja mindouble(const double, const double) mo e zostać wygenerowana).
  • 55. Rozdział 5. ♦ Wszystko o szablonach 203 Kuszące byłoby za ądanie u ycia w przypadku szablonu min u ycia dwóch parametrów, dzięki czemu typy argumentów mogłyby być dowolne: VGORNCVGV[RGPCOG 6 V[RGPCOG 7 EQPUV 6 OKP EQPUV 6 C EQPUV 7 D ] TGVWTP C D ! C D _ Często jest to dobre rozwiązanie, choć w tym wypadku jego zastosowanie jest dyskusyjne: min() musi zwrócić wartość, a nie ma jednoznacznie dobrej metody określenia typu tej wartości — czy powinien to być typ T albo U. Jeśli typ wartości zwracanej przez funkcję jest niezale nym parametrem szablonu, zawsze w chwili wywołania funkcji trzeba podać ten typ jawnie, gdy nie ma adnych podstaw do wywnioskowania tego typu. Taka sytuacja występuje w przypadku szablonu fromS- tring pokazanego poni ej: %5VTKPI%QPXJ KHPFGH 564+0)%108A* FGHKPG 564+0)%108A* 5CDNQP[ HWPMELK RTGMUVC ECLæE[EJ PC C EWEJ[ K C EWEJÎY KPENWFG UVTKPI KPENWFG UUVTGCO VGORNCVGV[RGPCOG 6 6 HTQO5VTKPI EQPUV UVFUVTKPI U ] UVFKUVTKPIUVTGCO KU U 6 V KU V TGVWTP V _ VGORNCVGV[RGPCOG 6 UVFUVTKPI VQ5VTKPI EQPUV 6 V ] UVFQUVTKPIUVTGCO U U V TGVWTP UUVT _ GPFKH 564+0)%108A* ` Podane szablony funkcji obsługują konwersje na typ std::string oraz z tego typu dla dowolnych typów mających odpowiednio operatory wstawiania i pobierania da- nych ze strumienia. Oto program testowy pokazujący u ycie typu complex z biblioteki standardowej: %5VTKPI%QPX6GUVERR KPENWFG 5VTKPI%QPXJ KPENWFG KQUVTGCO KPENWFG EQORNGZ WUKPI PCOGURCEG UVF KPV OCKP ] KPV K EQWV K VQ5VTKPI K P HNQCV Z EQWV Z VQ5VTKPI Z P
  • 56. 204 Część II ♦ Standardowa biblioteka C++ EQORNGZHNQCV E EQWV E VQ5VTKPI E P EQWV GPFN K HTQO5VTKPIKPV UVTKPI EQWV K K GPFN Z HTQO5VTKPIHNQCV UVTKPI EQWV Z Z GPFN E HTQO5VTKPI EQORNGZHNQCV UVTKPI EQWV E E GPFN _ ` Wynik działania tego programu będzie następujący: K Z E K Z E Zauwa , e w ka dej instancji fromString parametr szablonu jest podawany w wy- wołaniu. Jeśli masz szablon funkcji z parametrami szablonu zarówno dla parametrów funkcji jak i wartości zwracanej, konieczne jest zadeklarowanie najpierw parametru odpowiadającego wartości zwracanej; w przeciwnym przypadku niemo liwe będzie pomijanie parametrów szablonu odpowiadających parametrom funkcji. W ramach przy- kładu przyjrzyjmy się takiemu oto dobrze znanemu szablonowi funkcji3: %+ORNKEKV%CUVERR VGORNCVGV[RGPCOG 4 V[RGPCOG 2 4 KORNKEKVAECUV EQPUV 2 R ] TGVWTP R _ KPV OCKP ] KPV K HNQCV Z KORNKEKVAECUVHNQCV K KPV L KORNKEKVAECUVKPV Z EJCT
  • 58. K _ ` Jeśli zamienisz znajdujące się na początku pliku parametry R i P miejscami, niemo - liwe będzie skompilowanie takiego programu, gdy typ wartości zwracanej nie będzie podany (po takiej zmianie pierwszy parametr odpowiadałby typowi parametru funk- cji). Ostatni wiersz (zakomentowany) jest niedopuszczalny, gdy nie istnieje standar- dowa konwersja typu int na char*; implicit_cast słu y do realizacji tych konwersji, które są dopuszczalne. Zachowując pewną ostro ność, mo na nawet wydedukować wielkość tablicy. Poni szy przykład zawiera wykonujący to szablon funkcji inicjalizującej tablicę, init2: 3 Zobacz: Stroustrup, The C++ Programming Language, 3rd Edition, Addison Wesley, strony 335 – 336.
  • 59. Rozdział 5. ♦ Wszystko o szablonach 205 %#TTC[5KGERR KPENWFG EUVFFGH WUKPI UVFUKGAV VGORNCVGUKGAV 4 UKGAV % V[RGPCOG 6 XQKF KPKV 6 C=4?=%? ] HQT UKGAV K K 4 K HQT UKGAV L L % L C=K?=L? 6 _ VGORNCVGUKGAV 4 UKGAV % ENCUU 6 XQKF KPKV 6 C=4?=%? ] RCTCOGVT DúFæE[ TGHGTGPELæ HQT UKGAV K K 4 K HQT UKGAV L L % L C=K?=L? 6 _ KPV OCKP ] KPV C=?=? KPKV C RQFCPKG MQPKGEPG KPKV C TQOKCT QUVCPKG QMTG NQP[ RTG MQORKNCVQT _ ` Wymiary tablicy nie są przekazywane jako część typu parametru funkcji, chyba e parametr ten jest przekazywany przez wskaźnik lub referencję. Szablon funkcji init2 zawiera deklarację a jako referencji tablicy dwuwymiarowej, więc wymiary R i C zo- staną wyznaczone przez mechanizm szablonów, przez co init2 staje się wygodnym narzędziem do inicjalizowania dwuwymiarowych tablic dowolnej wielkości. Szablon init1 nie przekazuje tablicy przez referencję, wobec czego tutaj wielkość tablicy musi być jawnie podawana, choć typ parametru mo e być nadal wywnioskowany. Przeciążanie szablonów funkcji Tak jak w przypadku zwykłych funkcji, mo na przecią ać szablony funkcji mające takie same nazwy. Kiedy kompilator przetwarza w programie wywołanie funkcji, musi zdecydować, który szablon lub zwykła funkcje będzie „najlepiej pasować” do danego wywołania. Jeśli istnieje opisany wcześniej szablon funkcji min(), dodajmy jeszcze zwykłe funkcje: %/KP6GUVERR KPENWFG EUVTKPI KPENWFG KQUVTGCO WUKPI UVFUVTEOR WUKPI UVFEQWV WUKPI UVFGPFN VGORNCVGV[RGPCOG 6 EQPUV 6 OKP EQPUV 6 C EQPUV 6 D ] TGVWTP C D ! C D _ EQPUV EJCT
  • 62. D ] TGVWTP UVTEOR C D ! C D _
  • 63. 206 Część II ♦ Standardowa biblioteka C++ FQWDNG OKP FQWDNG Z FQWDNG [ ] TGVWTP Z [ ! Z [ _ KPV OCKP ] EQPUV EJCT
  • 64. U OÎYKæ 0K
  • 65. U T[EGTG MVÎT[ EQWV OKP GPFN UCDNQP EQWV OKP GPFN FQWDNG EQWV OKP GPFN FQWDNG EQWV OKP U U GPFN T[EGTG MVÎT[ EQPUV EJCT
  • 66. EQWV OKP U U GPFN OÎYKæ 0K UCDNQP _ ` Teraz oprócz szablonu funkcji mamy zdefiniowane dwie zwykłe funkcje: wersję min() u ywającą łańcuchów języka C oraz wersję z double. Gdyby nie istniał szablon, wy- wołanie w wierszu 1. wywoływałoby wersję double funkcji min(), a to z uwagi na konwersję standardową typu int na double. Jednak istniejący szablon pozwala wygenero- wać wersję int, która jest uwa ana za lepiej dopasowaną, więc ten szablon zostanie u yty. Wywołanie w wierszu 2. odpowiada wersji z double, zaś wywołanie z wiersza 3. wywołuje tę samą funkcję, niejawnie konwertując 1 na 1.0. W wierszu 4. bezpośrednio wywoływana wersja const char* funkcji min(). W wierszu 5. wymuszamy na kompila- torze u ycie szablonu, gdy do nazwy funkcji dodajemy pustą parę nawiasów kąto- wych; wobec tego z szablonu generowana jest wersja const char* i jest ona u ywana (widać to po nieprawidłowej odpowiedzi — nastąpiło najzwyklejsze porównanie ad- resów!)4. Jeśli zastanawiasz się, czemu zamiast dyrektywy using namespace std; u yliśmy deklaracji using, wiedz, e niektóre kompilatory niejawnie dołączają pliki nagłówkowe deklarujące std::min(), które mogłyby spowodować konflikt z naszymi deklaracjami nazw min(). Jak powiedziano wy ej, mo na przecią ać szablony mające tę samą nazwę, o ile tylko kompilator będzie w stanie je od siebie odró nić. Mo na byłoby, na przykład, zadeklaro- wać szablon funkcji min() mający trzy argumenty: VGORNCVGV[RGPCOG 6 EQPUV 6 OKP EQPUV 6 C EQPUV 6 D EQPUV 6 E Wersje tego szablonu będą generowane tylko dla trójargumentowych wywołań min(), gdzie wszystkie argumenty będą tego samego typu. Pobieranie adresu wygenerowanej z szablonu funkcji Często potrzebny bywa adres funkcji — na przykład mamy funkcję pobierającą jako argument wskaźnik innej funkcji. Oczywiście mo na przekazać tak e funkcję wyge- nerowaną z szablonu, a zatem potrzebny będzie jej adres5: 4 Formalnie rzecz biorąc, porównywanie dwóch wskaźników nieznajdujących się w jednej tablicy daje wynik nieokreślony, ale stosowane obecnie kompilatory nie traktują tego powa nie. Co więcej, zachowują się one w takiej sytuacji poprawnie. 5 Za ten przykład jesteśmy wdzięczni Nathanowi Myersowi.
  • 67. Rozdział 5. ♦ Wszystko o szablonach 207 %6GORNCVG(WPEVKQP#FFTGUUERR 2QDKGTCPKG CFTGUW HWPMELK Y[IGPGTQYCPGL UCDNQPW VGORNCVG V[RGPCOG 6 XQKF H 6
  • 68. ]_ XQKF J XQKF
  • 70. ]_ VGORNCVG V[RGPCOG 6 XQKF I XQKF
  • 71. RH 6
  • 72. ]_ KPV OCKP ] 2G PC URGE[HKMCELC V[RW J HKPV 1FICF[YCPKG V[RW J H 2G PC URGE[HKMCELC V[RW IKPV HKPV 1FICF[YCPKG V[RW I HKPV 5RGE[HKMCELC Eú EKQYC CNG Y[UVCTECLæEC IKPV H _ ` Przykład ten porusza kilka kwestii. Po pierwsze, mimo e u ywamy szablonów, pa- sować muszą sygnatury. Funkcja h() pobiera wskaźnik funkcji typu void mającej ar- gument int*, właśnie taką funkcję wygeneruje szablon f(). Po drugie, funkcja, która jako argument pobiera wskaźnik funkcji, sama mo e być szablonem, jak w przypadku szablonu g(). W funkcji main() widać, e działa te dedukowanie typu. W pierwszym jawnym wy- wołaniu h() podawany jest argument szablonu, ale wobec tego, e h() przyjmuje je- dynie adres funkcji mającej parametr int*, mógłby się tego domyślić kompilator. Jeszcze ciekawiej jest w przypadku funkcji g(), gdy tutaj mamy do czynienia z dwoma szablonami. Kompilator nie mo e „wywnioskować” typu, nie mając adnych danych, ale jeśli w przypadku f() lub g() podany zostanie typ int, resztę ju mo na będzie odgadnąć. Problem pojawia się, kiedy próbujemy przekazać jako parametry funkcje tolower czy toupper zadeklarowane w pliku nagłówkowym cctype. Mo na ich u ywać, na przy- kład, wraz z algorytmem transform (szczegółowo omawianym w następnym rozdziale), aby łańcuchy przekształcać na wielkie lub na małe litery. Jednak trzeba zachować tu ostro ność, gdy funkcje te mają wiele deklaracji. Najprościej byłoby zapisać coś takiego: OKGPPC U VQ UVFUVTKPI VTCPUHQTO UDGIKP UGPF UDGIKP VQNQYGT Algorytm transform stosuje swój czwarty parametr (tutaj tolower()) do ka dego znaku łańcucha s, wynik umieszcza w s, przez co nadpisuje ka dy znak s odpowiada- jącą mu małą literą. Jednak tak zapisana instrukcja mo e zadziałać lub nie! W poni - szym kontekście nie zadziała: %(CKNGF6TCPUHQTOERR ]ZQ_ KPENWFG CNIQTKVJO KPENWFG EEV[RG KPENWFG KQUVTGCO
  • 73. 208 Część II ♦ Standardowa biblioteka C++ KPENWFG UVTKPI WUKPI PCOGURCEG UVF KPV OCKP ] UVTKPI U .19'4 VTCPUHQTO UDGIKP UGPF UDGIKP VQNQYGT EQWV U GPFN _ ` Nawet jeśli Twój kompilator sobie z tym programem poradzi, to program jest i tak niepoprawny. Wynika to stąd, e plik nagłówkowy iostream udostępnia tak e dwuar- gumentowe wersje tolower() i toupper(): VGORNCVG ENCUU EJCT6 EJCT6 VQWRRGT EJCT6 E EQPUV NQECNG NQE VGORNCVG ENCUU EJCT6 EJCT6 VQNQYGT EJCT6 E EQPUV NQECNG NQE Te szablony funkcji mają drugi argument typu locale. Kompilator nie jest w stanie stwierdzić, czy powinien u yć jednoargumentowej wersji tolower() z cctype czy powy szej. Problem ten mo na rozwiązać (prawie), za pomocą rzutowania w czasie wywołania transform: VTCPUHQTO UDGIKP UGPF UDGIKP UVCVKEAECUVKPV