1 Szablony C++ Leszek Mierzejewski
2 Szablony Szablon to funkcja bądź klasa zaimplementowana dla nieokreślonego z góry typu. Typ ten jest określany (w sposób jawny bądź niejawny) w miejscu zastosowania szablonu. Ponieważ szablony są elementami języka, są objęte pełną kontrolą typów i zasięgu widoczności. Szablony pozwalają na parametryzacje działania programu, optymalizację kodu i parametryzacje informacji. We współczesnych programach szablony są wykorzystywane bardzo szeroko.
3 Szablon funkcji Szablony funkcji definiują rodzinę funkcji dla różnych parametrów szablonu. Konstrukcja składniowa template < lista-parametrów-oddzielonych-przecinkami > Słowo kluczowe typename wprowadza do listy parametrów tzw. parametr typu. Z przyczyn historycznych w określeniu parametru typu dopuszcza się stosowanie w miejsc typename słowa kluczowego class. Definiowanie i korzystanie z szablonu funkcji template
4 Przekazując w wywołaniu argumenty szablonu, konkretyzujemy szablon funkcji dla wskazanych typów argumentów. Proces zastępowania parametrów szablonu konkretnymi typami nazywamy konkretyzacją (ang. instantiation) szablonu. Efekt konkretyzacji – nowa jednostka (klasa, funkcja lub metoda klasy) – zwany jest ogólnie specjalizacją. Szablony są kompilowane dwukrotnie: Pierwszy raz kod szablonu jest analizowany pod kątem poprawności składniowej. Drugi raz podczas konkretyzacji: kod szablonu jest weryfikowany pod kątem poprawności wszystkich wywołań. Możliwe jest przeciążanie szablonów funkcji. Możliwe jest jawne kwalifikowanie parametrów szablonu. Przeciążając szablony funkcji, należy ograniczać zmiany do jawnego określania parametrów szablonu. Zawsze warto sprawdzić, czy w miejscu wywołania znane są wszystkie wersje przeciążonego szablonu funkcji.
5 Szablony klas Szablon klasy to klasa implementowana równocześnie dla wielu nieokreślonych z góry typów. template
6 Szablony klas można specjalizować dla wybranych typów.template<> class Stack
7 Możliwe jest definiowanie wartości domyślnych parametrów szablonów klas. Mogą się one odwoływać do poprzednich parametrów szablonu. template
8 Inne aspekty szablonówAby odwołać się do nazwy typu uzależnionego od parametru szablonu, należy kwalifikować tę nazwę słowem kluczowym typename. template
9 Parametrami szablonów mogą być również szablony klas, jako tak zwane szablony parametrów szablonów.template
10 Literały łańcuchowe (napisy) są podczas dedukcji argumentów poddawane konwersji z typu tablicowego do typu wskaźnikowego tylko wtedy, gdy są przekazywane przez wartość. // uwaga: parametry przekazywane przez referencję template
11 Zastosowanie szablonówKorzystanie z szablonów oznacza konieczność rewizji tradycyjnego modelu kompilator-konsolidator. Opracowano więc rozmaite metody organizowania kodu szablonów: model włączania, konkretyzację jawną i model separacji. Konkretyzacja jawna // jawna konkretyzacja szablonu klasy Stack<> dla typu int template Stack
12 Siła polimorfizmu szablonówPolimorfizm implementowany przez dziedziczenie Polimorfizm implementowany za pośrednictwem szablonów ograniczony, bo interfejsy typów uczestniczących w polimorfizmie są określone przez projekt klasy bazowej (inwazyjność) nieograniczony, bo interfejsy typów uczestniczących w polimorfizmie nie są z góry określone dynamiczny, bo wiązanie interfejsu z implementacją odbywa się w czasie wykonania statyczny, bo wiązanie interfejsu z implementacją odbywa się w czasie kompilacji Dynamiczny polimorfizm Statyczny polimorfizm łatwa obsługa zbiorów obiektów niejednorodnych potencjalnie mniejszy rozmiar kodu wykonywalnego możliwość pełnej kompilacji kodu łatwa implementacja kolekcji typów wbudowanych potencjalnie większa szybkość działania wygenerowanego kodu możliwość korzystania z typów udostępniających interfejsy częściowe
13 Nowe formy wzorców projektowychInterfejs Implementation *body; operationA() { body->operationA() } operationB() { body->operationB() body->operationC() Implementacja virtual operationA() = 0; virtual operationB() = 0; virtual operationC() = 0; body Implementacja A virtual operationA(); virtual operationB(); virtual operationC(); Implementacja B virtual operationA(); virtual operationB(); virtual operationC(); Impl Interfejs Impl body; operationA() { body.operationA() } operationB() { body.operationB() body.operationC() Implementacja A operationA(); operationB(); operationC(); Implementacja B operationA(); operationB(); operationC();
14 niska szybkość wykonywania (obsługa wywołań wirtualnych), Object Iterator Iterator (Collection&) void reset() Object *operator++() Object *operator() () Collection vrtual void doRest(Iterator &) vrtual Object *doNext(Iterator &) vrtual void doFinish(Iterator &) ... SeqCInt Bag Set Stack LinkedList OrderedCInt IdentSet Dictionary Hierarchia klas biblioteki NIHCL SortedCInt IdentDict Typy kontenerowe były główną motywacją wprowadzenia do języka C++ mechanizmu szablonów. National Institutes of Health Class Library (NIHCL) – biblioteka implementująca kontenery za pośrednictwem hierarchii polimorficznych. Wady NIHCL: niska szybkość wykonywania (obsługa wywołań wirtualnych), duża zajętość pamięci (kopertowanie typów wbudowanych).
15 Klasy cech i wytycznychCechy reprezentacją dodatkowe właściwości parametru szablonu. Wytyczne reprezentują konfigurowalne zachowania ogólnych funkcji i typów. Przykład – kumulowanie ciągu elementów template
16 Parametryzacja cech template
17 Klasa wytycznych (klasa ukierunkowana) – klasa udostępniająca interfejs jednego lub więcej wytycznych algorytmu. template
18 Biblioteka standardowa udostępnia tak zwane cechy iteratorów.// stl_iterator_base_types.h template
19 Metaprogramy Metaprogramowanie polega na „programowaniu programu”, a więc na tworzeniu takiego kodu, na podstawie którego system kompilacji wygeneruje inny kod, implementujący docelowy zestaw funkcji programu. Cel: maksymalizacja wydajności, uproszczenie interfejsu. // szablon podstawowy obliczania N-tej potęgi liczby 3 template
20 Zupełność obliczeniowa zmienne stanu (parametry szablonów), pętle (szablony rekurencyjne), wybór ścieżki obliczeniowej (wyrażenia warunkowe i specjalizacje), arytmetyka liczb całkowitych. Metaprogramowanie w rozwijaniu pętli // Obliczanie iloczynu skalarnego. template
21 Obliczanie iloczynu skalarnego z wykorzystaniem szablonów.// szablon podstawowy template
22 Szablony wyrażeń Szablony wyrażeń opierają się na głęboko zagnieżdżonych konkretyzacjach szablonów. Początkowo służyły wyłącznie do obsługi klas tablic numerycznych. // mnożenie dwóch tablic SArrays template
23 Obiekty tymczasowe i rozdzielanie pętliEfektywność takiej implementacji okazuje się być wysoce niezadowalająca, a to z dwóch powodów: Każde zastosowanie operatora powoduje utworzenie przynajmniej jednej tablicy tymczasowej. Każde zastosowanie operatora wymaga dodatkowego przeglądu tablic argumentów i tablicy wynikowej. tmp1 = 1.2 * x tmp2 = x * y tmp3 = tmp1 + tmp2 x = tmp3
24 Kodowanie wyrażeń obliczeniowych za pomocą argumentów szablonów.Wyrażenie 1.2*x + x*y jest tłumaczone do obiektu następującego typu: A_Add< A_Mult< A_Scalar
25 // klasa obiektów reprezentujących dodawanie dwóch operandówtemplate
26 Typ Array i operatory template
27 Wydajność szablonów wyrażeń i ich ograniczenia.Wiele niewielkich funkcji rozwijanych w miejscu wywołania wywołuje się wzajemnie, co powoduje alokowanie na stosie wielu prostych obiektów szablonów wyrażeń. Szablony wyrażeń nie mogą rozwiązywać wszystkich trudności związanych z tablicowymi obliczeniami numerycznymi. Przykładowo nie da się ich zastosować do mnożenia macierzowego w postaci: x = A*x; Ciekawe zastosowanie szablonów wyrażeń zawiera biblioteka Lambda Library autorstwa Jaakko Jarvi’ego i Gary’ego Powella. Biblioteka ta wykorzystuje w roli szablonów wyrażeń standardowe obiekty funkcyjne. void lambda_demo (std::vector
28 Inteligentne wskaźnikiDwa modele posiadania zasobu – z wyłącznym prawem własności i ze wspólnym prawem własności. Bibliotek standardowa C++ zawiera szablon inteligentnych wskaźników, opatrzony nazwą auto_ptr. void do_something() { AnyT *ptr = 0; try { ptr = new AnyT; ptr->perform(); ... } catch (...) { delete ptr; throw; } void do_something() { Holder
29 Bibliografia "C++ Szablony. Vademecum profesjonalisty" (tytuł oryg. "C++ Template - The Complete Guide") autorstwa Davida Vandevoorde'a i Nicolaia M. Josuttisa, Wydawnictwo Helion, 2003 Dobre omówienia tematu inteligentnych wskaźników można znaleźć w książce „Język C++ bardziej efektywny”, Scott Meyers, Wydawnictwa Naukowo-Techniczne, 1998