Thinking in C++. Edycja polska. Tom 2

1,395 views

Published on

Szkoła programowania Bruce’a Eckela!

Podczas nauki tworzenia aplikacji w języku C++ towarzyszyć Ci będzie jeden z najlepszych dydaktyków programowania na świecie!

Nauka języka C++ i szczegółowe poznanie jego możliwości to poważne wyzwanie 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ś materiał z tej książki, możesz rozpocząć lekturę drugiego tomu.

Następnym krokiem jest -- "Thinking in C++. Edycja polska. Tom II" -- kolejny bestseller Bruce’a Eckela poświęcony językowi C++. Tym razem Bruce w typowy dla siebie, prosty i zrozumiały sposób opisuje zaawansowane aspekty programowania w C++. Dowiesz się, jak korzystać z referencji, przeciążania operatorów, dziedziczenia 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.

* obsługa wyjątków
* programowanie defensywne
* 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++.

O autorach:
Bruce Eckel jest prezesem MindView, Inc., firmy prowadzącej zarówno otwarte jak i zamknięte kursy treningowe; zajmującej się też doradztwem, nadzorem i kontrolą nad projektami związanymi z technologiami obiektowymi i wzorcami projektowymi. [więcej...]

Chuck Allison jest matematykiem, pełniącym obecnie funkcję wykładowcy na wydziale informatyki uniwersytetu stanowego Utah Valley. Do niedawna pełnił funkcję redaktora w magazynie C/C++ Users Journal. [więcej...]

0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
1,395
On SlideShare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
11
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Thinking in C++. Edycja polska. Tom 2

  1. 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. 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. 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. 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. 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. 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. 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. 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. 9. 188 Część II ♦ Standardowa biblioteka C++ VGORNCVGENCUU 6 ENCUU 5VCEM ] 6
  10. 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. 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. 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. 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. 14. D 6
  15. 15. G 6 KPKV 6 ] YJKNG D G KPKV
  16. 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. 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
  18. 18. ECRCEKV[
  19. 19. 192 Część II ♦ Standardowa biblioteka C++ 6
  20. 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. 21. DGIKP ] TGVWTP FCVC _ 6
  22. 22. GPF ] TGVWTP FCVC EQWPV _ _ VGORNCVGENCUU 6 VGORNCVGENCUU ENCUU 5GS ENCUU %QPVCKPGT ] 5GS6 UGS RWDNKE XQKF CRRGPF EQPUV 6 V ] UGSRWUJADCEM V _ 6
  23. 23. DGIKP ] TGVWTP UGSDGIKP _ 6
  24. 24. GPF ] TGVWTP UGSGPF _ _ KPV OCKP ] %QPVCKPGTKPV #TTC[ EQPVCKPGT EQPVCKPGTCRRGPF EQPVCKPGTCRRGPF KPV
  25. 25. R EQPVCKPGTDGIKP YJKNG R EQPVCKPGTGPF EQWV
  26. 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. 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. 28. DGIKP ] TGVWTP FCVC _ 6
  29. 29. GPF ] TGVWTP FCVC EQWPV _ _ VGORNCVGENCUU 6UKGAV 0VGORNCVGENCUUUKGAV ENCUU 5GS ENCUU %QPVCKPGT ] 5GS60 UGS RWDNKE XQKF CRRGPF EQPUV 6 V ] UGSRWUJADCEM V _ 6
  30. 30. DGIKP ] TGVWTP UGSDGIKP _ 6
  31. 31. GPF ] TGVWTP UGSGPF _ _ KPV OCKP ] EQPUV UKGAV 0 %QPVCKPGTKPV 0 #TTC[ EQPVCKPGT
  32. 32. 194 Część II ♦ Standardowa biblioteka C++ EQPVCKPGTCRRGPF EQPVCKPGTCRRGPF KPV
  33. 33. R EQPVCKPGTDGIKP YJKNG R EQPVCKPGTGPF EQWV
  34. 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. 35. DGIKP ] TGVWTP FCVC _ 6
  36. 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. 37. DGIKP ] TGVWTP UGSDGIKP _ 6
  38. 38. GPF ] TGVWTP UGSGPF _ _ KPV OCKP ] %QPVCKPGTKPV #TTC[ EQPVCKPGT EQPVCKPGTCRRGPF
  39. 39. Rozdział 5. ♦ Wszystko o szablonach 195 EQPVCKPGTCRRGPF KPV
  40. 40. R EQPVCKPGTDGIKP YJKNG R EQPVCKPGTGPF EQWV
  41. 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. 42. R GPFN _ 7 [L NKUV[ %QPVCKPGTKPV NKUV N%QPVCKPGT N%QPVCKPGTRWUJADCEM N%QPVCKPGTRWUJADCEM
  43. 43. 196 Część II ♦ Standardowa biblioteka C++ HQT NKUVKPV KVGTCVQT R N%QPVCKPGTDGIKP R N%QPVCKPGTGPF R ] EQWV
  44. 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. 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. 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. 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. 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. 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 ]
  50. 50. VWVCL VTG è
  51. 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. 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. 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. 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. 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. 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
  57. 57. R KORNKEKVAECUVEJCT
  58. 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. 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
  60. 60. OKP EQPUV EJCT
  61. 61. C EQPUV EJCT
  62. 62. D ] TGVWTP UVTEOR C D ! C D _
  63. 63. 206 Część II ♦ Standardowa biblioteka C++ FQWDNG OKP FQWDNG Z FQWDNG [ ] TGVWTP Z [ ! Z [ _ KPV OCKP ] EQPUV EJCT
  64. 64. U OÎYKæ 0K
  65. 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. 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. 67. Rozdział 5. ♦ Wszystko o szablonach 207 %6GORNCVG(WPEVKQP#FFTGUUERR 2QDKGTCPKG CFTGUW HWPMELK Y[IGPGTQYCPGL UCDNQPW VGORNCVG V[RGPCOG 6 XQKF H 6
  68. 68. ]_ XQKF J XQKF
  69. 69. RH KPV
  70. 70. ]_ VGORNCVG V[RGPCOG 6 XQKF I XQKF
  71. 71. RH 6
  72. 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. 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

×