37
Wstęp do programowania obiektowego Szablony w C++ 1

Wstęp do programowania obiektowegoii.uwb.edu.pl/~m.rybnik/wp-content/uploads/WdPO-W9... · 2017. 4. 20. · Wstęp do programowania obiektowego Szablony w C++ . 1 . ... • Aby zagwarantować

  • Upload
    others

  • View
    0

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Wstęp do programowania obiektowegoii.uwb.edu.pl/~m.rybnik/wp-content/uploads/WdPO-W9... · 2017. 4. 20. · Wstęp do programowania obiektowego Szablony w C++ . 1 . ... • Aby zagwarantować

Wstęp do programowania obiektowego

Szablony w C++

1

Page 2: Wstęp do programowania obiektowegoii.uwb.edu.pl/~m.rybnik/wp-content/uploads/WdPO-W9... · 2017. 4. 20. · Wstęp do programowania obiektowego Szablony w C++ . 1 . ... • Aby zagwarantować

Szablony

• Szablon - 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 parametryzację działania programu, optymalizację kodu i parametryzację informacji.

• Współcześnie szablony są szeroko wykorzystywane. 2

Page 3: Wstęp do programowania obiektowegoii.uwb.edu.pl/~m.rybnik/wp-content/uploads/WdPO-W9... · 2017. 4. 20. · Wstęp do programowania obiektowego Szablony w C++ . 1 . ... • Aby zagwarantować

SZABLONY FUNKCJI 3

Page 4: Wstęp do programowania obiektowegoii.uwb.edu.pl/~m.rybnik/wp-content/uploads/WdPO-W9... · 2017. 4. 20. · Wstęp do programowania obiektowego Szablony w C++ . 1 . ... • Aby zagwarantować

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.

4

Page 5: Wstęp do programowania obiektowegoii.uwb.edu.pl/~m.rybnik/wp-content/uploads/WdPO-W9... · 2017. 4. 20. · Wstęp do programowania obiektowego Szablony w C++ . 1 . ... • Aby zagwarantować

Przykład szablonu funkcji template <typename T> inline T const& max (T const& a, T const& b) { // jeżeli a < b zwróć b; w przeciwnym przypadku zwróć a return a < b ? b : a; } int main() { ::max(7, 68); ::max(7.0, 42.0); // wywołanie szablonu max<double> (dedukcja typu

argumentów) ::max<>(7, 42); // wywołanie szablonu max<int> (dedukcja typu

argumentów) ::max<double>(7, 42); // wywołanie szablonu max<double> (bez dedukcji typu) }

5

Page 6: Wstęp do programowania obiektowegoii.uwb.edu.pl/~m.rybnik/wp-content/uploads/WdPO-W9... · 2017. 4. 20. · Wstęp do programowania obiektowego Szablony w C++ . 1 . ... • Aby zagwarantować

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

Page 7: Wstęp do programowania obiektowegoii.uwb.edu.pl/~m.rybnik/wp-content/uploads/WdPO-W9... · 2017. 4. 20. · Wstęp do programowania obiektowego Szablony w C++ . 1 . ... • Aby zagwarantować

SZABLONY KLAS 7

Page 8: Wstęp do programowania obiektowegoii.uwb.edu.pl/~m.rybnik/wp-content/uploads/WdPO-W9... · 2017. 4. 20. · Wstęp do programowania obiektowego Szablony w C++ . 1 . ... • Aby zagwarantować

Szablony klas • Szablon klasy to klasa implementowana równocześnie dla wielu

nieokreślonych z góry typów. template <typename T> class Stack { private: std::vector<T> elems; // elementy public: void push(T const&); // wstawia element na szczyt stosu void pop(); // zdejmuje element ze szczytu stosu T top() const; // zwraca szczytowy element stosu bool empty() const { // czy stos jest pusty? return elems.empty(); } };

• Aby skorzystać z szablonu klasy, należy w liście argumentów szablonu określić typ konkretyzacji. Szablon klasy jest dla tego typu konkretyzowany i kompilowany.

Stack<int> intStack; // stos elementów typu int Stack<std::string> stringStack;// stos elementów typu std::string

• Konkretyzacji podlegają w szablonach klas wyłącznie te metody, które zostały wywołane.

8

Page 9: Wstęp do programowania obiektowegoii.uwb.edu.pl/~m.rybnik/wp-content/uploads/WdPO-W9... · 2017. 4. 20. · Wstęp do programowania obiektowego Szablony w C++ . 1 . ... • Aby zagwarantować

• Szablony klas można specjalizować dla wybranych typów. template<> class Stack<std::string> { private: std::deque<std::string> elems; // elementy public: void push(std::string const&); // wstaw element std::string top() const;

...

}; • Szablony klas można częściowo specjalizować dla wybranych typów. // specjalizacja częściowa (oba parametry szablonu mają ten sam typ) template<typename T> class MyClass<T, T> { ... } // specjalizacja częściowa (drugi parametr szablonu to int) template <typename T> class MyClass<T, int> { ... } // specjalizacja częściowa (oba parametry są typu wskaźnikowego) template <typename T1, typename T2> class MyClass<T1*, T2*> { ... } 9

Page 10: Wstęp do programowania obiektowegoii.uwb.edu.pl/~m.rybnik/wp-content/uploads/WdPO-W9... · 2017. 4. 20. · Wstęp do programowania obiektowego Szablony w C++ . 1 . ... • Aby zagwarantować

• Możliwe jest definiowanie wartości domyślnych parametrów szablonów klas. Mogą się one odwoływać do poprzednich parametrów szablonu.

template <typename T, typename CONT = std::vector<T> > class Stack { private:

CONT elems; // elementy

public:

void push(T const&); // wstaw element na szczyt stosu

void pop(); // usuń element ze szczytu stosu

T top() const; // zwróć szczytowy element stosu

bool empty() const { // czy stos jest pusty?

return elems.empty();

}

};

template <typename T, typename CONT> void Stack<T,CONT>::push (T const& elem) {

elems.push_back(elem); // dołącz kopię przekazanego elementu

}

// stos elementów typu int:

Stack<int> intStack; // stos elementów typu double przechowywany w kontenerze std::deque

Stack<double,std::deque<double> > dblStack; 10

Page 11: Wstęp do programowania obiektowegoii.uwb.edu.pl/~m.rybnik/wp-content/uploads/WdPO-W9... · 2017. 4. 20. · Wstęp do programowania obiektowego Szablony w C++ . 1 . ... • Aby zagwarantować

Inne aspekty szablonów

• Aby odwołać się do nazwy typu uzależnionego od parametru szablonu, należy kwalifikować tę nazwę słowem kluczowym typename.

template <typename T> class MyClass { typename T::SubType * ptr; ...

}

• Klasy zagnieżdżone i metody składowe również mogą być definiowane jako szablony. Przydaje się to między innymi do implementacji operacji ogólnych, wykorzystujących wewnętrzną konwersję typów. Nie eliminuje to naturalnie procesu kontroli typów.

template <typename T> template <typename T2> Stack<T>& Stack<T>::operator= (Stack<T2> const& op2) { Stack<T2> tmp(op2); // utwórz kopię przypisywanego stosu elems.clear(); // usuń istniejące elementy stosu while (!tmp.empty()) { // kopiuj elementy do nowego stosu elems.push_front(tmp.top()); tmp.pop(); } return *this; }

11

Page 12: Wstęp do programowania obiektowegoii.uwb.edu.pl/~m.rybnik/wp-content/uploads/WdPO-W9... · 2017. 4. 20. · Wstęp do programowania obiektowego Szablony w C++ . 1 . ... • Aby zagwarantować

• Parametrami szablonów mogą być również szablony klas, jako tak zwane szablony parametrów szablonów.

template <typename T, template <typename ELEM, typename ALLOC = std::allocator<ELEM> > class CONT = std::deque > class Stack { private: CONT<T> elems; ... } Stack<int, std::vector> > vStack; • Argumenty szablonów parametrów szablonów podlegają ścisłemu

dopasowaniu. Dopasowanie to ignoruje argumenty domyślne szablonów parametrów szablonów.

• Aby zagwarantować inicjalizację składowych i metod szablonów wartościami domyślnymi również dla szablonów konkretyzowanych typami wbudowanymi, należy wykorzystać konstruktor domyślny.

template <typename T> void foo () { T x = T(); }

12

Page 13: Wstęp do programowania obiektowegoii.uwb.edu.pl/~m.rybnik/wp-content/uploads/WdPO-W9... · 2017. 4. 20. · Wstęp do programowania obiektowego Szablony w C++ . 1 . ... • Aby zagwarantować

• 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 <typename T> inline T const& max (T const& a, T const& b) { return a < b ? b : a; } int main() { std::string s; ::max("jabłko","wiśnia"); // DOBRZE: typy zgodne ::max("jabłko","pomidor"); // BŁĄD: różne typy ::max("jabłko",s); // BŁĄD: różne typy }

13

Page 14: Wstęp do programowania obiektowegoii.uwb.edu.pl/~m.rybnik/wp-content/uploads/WdPO-W9... · 2017. 4. 20. · Wstęp do programowania obiektowego Szablony w C++ . 1 . ... • Aby zagwarantować

ZASTOSOWANIE SZABLONÓW 14

Page 15: Wstęp do programowania obiektowegoii.uwb.edu.pl/~m.rybnik/wp-content/uploads/WdPO-W9... · 2017. 4. 20. · Wstęp do programowania obiektowego Szablony w C++ . 1 . ... • Aby zagwarantować

Zastosowanie szablonów

• Korzystanie 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<int>;

// jawna konkretyzacja niektórych metod szablonu klasy Stack<> dla typu std::string template Stack<std::string>::Stack(); template void Stack<std::string>::push(std::string const&);

• Zazwyczaj zalecane jest stosowanie modelu włączania (czyli umieszczenia całości kodu szablonu w plikach nagłówkowych).

• Rozdzielając definicję i deklarację szablonu pomiędzy różnymi plikami nagłówkowymi, można dowolnie wybierać pomiędzy modelem włączania i modelem konkretyzacji jawnej.

• Standard języka C++ definiuje dla szablonów model oddzielnej kompilacji (wykorzystujący słowo kluczowe export). Model ten nie doczekał się jeszcze powszechnej implementacji.

15

Page 16: Wstęp do programowania obiektowegoii.uwb.edu.pl/~m.rybnik/wp-content/uploads/WdPO-W9... · 2017. 4. 20. · Wstęp do programowania obiektowego Szablony w C++ . 1 . ... • Aby zagwarantować

Siła polimorfizmu szablonów

Polimorfizm 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

16

Page 17: Wstęp do programowania obiektowegoii.uwb.edu.pl/~m.rybnik/wp-content/uploads/WdPO-W9... · 2017. 4. 20. · Wstęp do programowania obiektowego Szablony w C++ . 1 . ... • Aby zagwarantować

Nowe formy wzorców projektowych Interfejs

Implementation *body; operationA() { body->operationA() } operationB() { body->operationB() body->operationC() }

Implementacja

virtual operationA() = 0; virtual operationB() = 0; virtual operationC() = 0;

Implementacja B

virtual operationA(); virtual operationB(); virtual operationC();

Implementacja A

virtual operationA(); virtual operationB(); virtual operationC();

Implementacja B

operationA(); operationB(); operationC();

Implementacja A

operationA(); operationB(); operationC();

Interfejs

Impl body; operationA() { body.operationA() } operationB() { body.operationB() body.operationC() }

Impl

body

17

Page 18: Wstęp do programowania obiektowegoii.uwb.edu.pl/~m.rybnik/wp-content/uploads/WdPO-W9... · 2017. 4. 20. · Wstęp do programowania obiektowego Szablony w C++ . 1 . ... • Aby zagwarantować

Object

Iterator Iterator (Collection&) void reset() Object* operator++() Object* operator() ()

Collection virtual void doRest(Iterator &) virtual Object* doNext(Iterator &) virtual void doFinish(Iterator &) ...

SeqCInt Bag Set

Stack LinkedList OrderedCInt

SortedCInt

IdentSet Dictionary

IdentDict Hierarchia klas biblioteki NIHCL

• 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).

18

Page 19: Wstęp do programowania obiektowegoii.uwb.edu.pl/~m.rybnik/wp-content/uploads/WdPO-W9... · 2017. 4. 20. · Wstęp do programowania obiektowego Szablony w C++ . 1 . ... • Aby zagwarantować

KLASY CECH I WYTYCZNYCH 19

Page 20: Wstęp do programowania obiektowegoii.uwb.edu.pl/~m.rybnik/wp-content/uploads/WdPO-W9... · 2017. 4. 20. · Wstęp do programowania obiektowego Szablony w C++ . 1 . ... • Aby zagwarantować

Klasy cech i wytycznych

• Cechy 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 <typename T> inline T accum (T const* beg, T const* end) {

T total = T(); // zakładamy, że T() utworzy wartość zerową while (beg != end) {

total += *beg;

++beg;

}

return total;

}

• Problemy: • utworzenie wartości zerowej, • określenie typu zmiennej kumulującej.

20

Page 21: Wstęp do programowania obiektowegoii.uwb.edu.pl/~m.rybnik/wp-content/uploads/WdPO-W9... · 2017. 4. 20. · Wstęp do programowania obiektowego Szablony w C++ . 1 . ... • Aby zagwarantować

• Parametryzacja cech template <typename T, typename AT = AccumulationTraits<T> > class Accum { public: static typename AT::AccT accum (T const* beg, T const* end) { typename AT::AccT total = AT::zero(); while (beg != end) { total += *beg; ++beg; } return total; } };

• Szablon AccumulationTraits zwany jest szablonem cechy, gdyż przechowuje cechę parametru typu

template <typename T> class AccumulationTraits; template<> class AccumulationTraits<char> { public: typedef int AccT; static AccT zero() { return 0; } };

template<> class AccumulationTraits<int> { public: typedef long AccT; static AccT zero() { return 0; } };

21

Page 22: Wstęp do programowania obiektowegoii.uwb.edu.pl/~m.rybnik/wp-content/uploads/WdPO-W9... · 2017. 4. 20. · Wstęp do programowania obiektowego Szablony w C++ . 1 . ... • Aby zagwarantować

• Klasa wytycznych (klasa ukierunkowana) – klasa udostępniająca interfejs jednego lub więcej wytycznych algorytmu.

template <typename T, typename Policy = SumPolicy, typename Traits = AccumulationTraits<T> > class Accum { public: typedef typename Traits::AccT AccT; static AccT accum (T const* beg, T const* end) { AccT total = Traits::zero(); while (beg != end) { Policy::accumulate(total, *beg); ++beg; } return total; } }; class SumPolicy { public: template <typename T1, typename T2> static void accumulate (T1& total, T2 const & value) { total += value; } }; 22

Page 23: Wstęp do programowania obiektowegoii.uwb.edu.pl/~m.rybnik/wp-content/uploads/WdPO-W9... · 2017. 4. 20. · Wstęp do programowania obiektowego Szablony w C++ . 1 . ... • Aby zagwarantować

Biblioteka standardowa udostępnia tak zwane cechy iteratorów.

// stl_iterator_base_types.h template<typename _Category, typename _Tp, typename _Distance = ptrdiff_t, typename _Pointer = _Tp*, typename _Reference = _Tp&> struct iterator { /// One of the @link iterator_tags tag types@endlink. typedef _Category iterator_category; /// The type "pointed to" by the iterator. typedef _Tp value_type; /// Distance between iterators is represented as this type. typedef _Distance difference_type; /// This type represents a pointer-to-value_type. typedef _Pointer pointer; /// This type represents a reference-to-value_type. typedef _Reference reference; };

23

Page 24: Wstęp do programowania obiektowegoii.uwb.edu.pl/~m.rybnik/wp-content/uploads/WdPO-W9... · 2017. 4. 20. · Wstęp do programowania obiektowego Szablony w C++ . 1 . ... • Aby zagwarantować

METAPROGRAMY 24

Page 25: Wstęp do programowania obiektowegoii.uwb.edu.pl/~m.rybnik/wp-content/uploads/WdPO-W9... · 2017. 4. 20. · Wstęp do programowania obiektowego Szablony w C++ . 1 . ... • Aby zagwarantować

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 funkcji obliczania N-tej potęgi liczby 3 template<int N> class Pow3 { public: enum { result = 3 * Pow3<N-1>::result }; }; // specjalizacja pełna, kończąca rekurencję template<> class Pow3<0> { public: enum { result = 1 }; }; Pow3<7>::result

25

Page 26: Wstęp do programowania obiektowegoii.uwb.edu.pl/~m.rybnik/wp-content/uploads/WdPO-W9... · 2017. 4. 20. · Wstęp do programowania obiektowego Szablony w C++ . 1 . ... • Aby zagwarantować

• 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 <typename T> inline T dot_product (int dim, T* a, T* b) { T result = T(); for (int i=0; i<dim; ++i) { result += a[i]*b[i]; } return result; }

Kompilator optymalizuje pętle dla wielu iteracji, co w tym przypadku daje efekt raczej odwrotny od pożądanego. Pożądanym efektem byłoby rozwinięcie pętli do postaci: a[0]*b[0] + a[1]*b[1] + a[2]*b[2] 26

Page 27: Wstęp do programowania obiektowegoii.uwb.edu.pl/~m.rybnik/wp-content/uploads/WdPO-W9... · 2017. 4. 20. · Wstęp do programowania obiektowego Szablony w C++ . 1 . ... • Aby zagwarantować

// szablon podstawowy template <int DIM, typename T> class DotProduct { public: static T result (T* a, T* b) { return *a * *b + DotProduct<DIM-1,T>::result(a+1,b+1); } }; // specjalizacja częściowa jako kryterium wyjścia z pętli template <typename T> class DotProduct<1,T> { public: static T result (T* a, T* b) { return *a * *b; } }; // wygodna funkcja template <int DIM, typename T> inline T dot_product (T* a, T* b) { return DotProduct<DIM,T>::result(a,b); }

Biblioteki takie jak Blitz++, MTL czy POOMA wykorzystują metaprogramy do zwiększenia efektywności procedur numerycznych algebry liniowej.

Obliczanie iloczynu skalarnego z wykorzystaniem szablonów.

27

Page 28: Wstęp do programowania obiektowegoii.uwb.edu.pl/~m.rybnik/wp-content/uploads/WdPO-W9... · 2017. 4. 20. · Wstęp do programowania obiektowego Szablony w C++ . 1 . ... • Aby zagwarantować

SZABLONY WYRAŻEŃ 28

Page 29: Wstęp do programowania obiektowegoii.uwb.edu.pl/~m.rybnik/wp-content/uploads/WdPO-W9... · 2017. 4. 20. · Wstęp do programowania obiektowego Szablony w C++ . 1 . ... • Aby zagwarantować

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<typename T> SArray<T> operator* (SArray<T> const& a, SArray<T> const& b) {

SArray<T> result(a.size()); for (size_t k = 0; k<a.size(); ++k) { result[k] = a[k]*b[k]; } return result; } int main() { SArray<double> x(1000), y(1000); x = 1.2*x + x*y; }

29

Page 30: Wstęp do programowania obiektowegoii.uwb.edu.pl/~m.rybnik/wp-content/uploads/WdPO-W9... · 2017. 4. 20. · Wstęp do programowania obiektowego Szablony w C++ . 1 . ... • Aby zagwarantować

Obiekty tymczasowe i rozdzielanie pętli

Efektywność takiej implementacji okazuje się być wysoce niezadowalająca, a to z dwóch powodów:

1. Każde zastosowanie operatora powoduje utworzenie przynajmniej jednej tablicy tymczasowej.

2. 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;

30

Page 31: Wstęp do programowania obiektowegoii.uwb.edu.pl/~m.rybnik/wp-content/uploads/WdPO-W9... · 2017. 4. 20. · Wstęp do programowania obiektowego Szablony w C++ . 1 . ... • Aby zagwarantować

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<double>, Array<double> >,

A_Mult<Array<double>, Array<double> > >

+

* *

1.2 x x y

Drzewo składniowe odpowiadające wyrażeniu 1.2*x+x*y 31

Page 32: Wstęp do programowania obiektowegoii.uwb.edu.pl/~m.rybnik/wp-content/uploads/WdPO-W9... · 2017. 4. 20. · Wstęp do programowania obiektowego Szablony w C++ . 1 . ... • Aby zagwarantować

// klasa obiektów reprezentujących dodawanie dwóch operandów template <typename T, typename OP1, typename OP2> class A_Add { private: typename A_Traits<OP1>::ExprRef op1; // pierwszy operand typename A_Traits<OP2>::ExprRef op2; // drugi operand public: // konstruktor inicjalizujący odwołania do operandów A_Add (OP1 const& a, OP2 const& b) : op1(a), op2(b) { } // oblicz sumę T operator[] (size_t idx) const { return op1[idx] + op2[idx]; } // size jest rozmiarem maksymalnym size_t size() const { assert (op1.size()==0 || op2.size()==0 || op1.size()==op2.size()); return op1.size()!=0 ? op1.size() : op2.size(); } }; 32

Page 33: Wstęp do programowania obiektowegoii.uwb.edu.pl/~m.rybnik/wp-content/uploads/WdPO-W9... · 2017. 4. 20. · Wstęp do programowania obiektowego Szablony w C++ . 1 . ... • Aby zagwarantować

Typ Array i operatory

template <typename T, typename Rep = SArray<T> > class Array {

// dodawanie dwóch tablic Array

template <typename T, typename R1, typename R2> Array<T,A_Add<T,R1,R2> > operator+ (Array<T,R1> const& a, Array<T,R2> const& b) { return Array<T,A_Add<T,R1,R2> > (A_Add<T,R1,R2>(a.rep(),b.rep())); }

33

Page 34: Wstęp do programowania obiektowegoii.uwb.edu.pl/~m.rybnik/wp-content/uploads/WdPO-W9... · 2017. 4. 20. · Wstęp do programowania obiektowego Szablony w C++ . 1 . ... • Aby zagwarantować

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<long*> &ones) {

std::sort (ones.begin(), ones.end(), *_1 > *_2);

}

• Biblioteka standardowa języka C++ zawiera szablon klasy o nazwie valarray, który miał być wykorzystywany do tablicowych obliczeń numerycznych.

34

Page 35: Wstęp do programowania obiektowegoii.uwb.edu.pl/~m.rybnik/wp-content/uploads/WdPO-W9... · 2017. 4. 20. · Wstęp do programowania obiektowego Szablony w C++ . 1 . ... • Aby zagwarantować

Inteligentne wskaźniki

• Dwa 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; } delete ptr; }

void do_something() { Holder<AnyT> ptr(new AnyT); ptr->perform(); }

35

Page 36: Wstęp do programowania obiektowegoii.uwb.edu.pl/~m.rybnik/wp-content/uploads/WdPO-W9... · 2017. 4. 20. · Wstęp do programowania obiektowego Szablony w C++ . 1 . ... • Aby zagwarantować

36

Page 37: Wstęp do programowania obiektowegoii.uwb.edu.pl/~m.rybnik/wp-content/uploads/WdPO-W9... · 2017. 4. 20. · Wstęp do programowania obiektowego Szablony w C++ . 1 . ... • Aby zagwarantować

Prosty przykład użycia klasy Vector z konkretną z góry znaną ilością elementów wektora: vector<int> wektorek(2); wektorek[0]=34; wektorek[1]=12; cout << wektorek[0] << endl; cout << wektorek[1] << endl; Prosty przykład użycia klasy Vector z nieznaną ilością elementów wektora: vector<int> vec; for (int i=0; i<30; i++) vec.push_back(i); for(int i=0; i<vec.size(); i++) cout << vec[i]<< endl; 37