Programowanie Obiektowo Zorientowane w języku...

Post on 25-Sep-2020

4 views 0 download

Transcript of Programowanie Obiektowo Zorientowane w języku...

Programowanie Obiektowo Zorientowanew języku C++11

Zmiany w bibliotece standardowejhttps://en.cppreference.com, https://wikipedia.org

Mirosław Głowacki 1,2

1Akademia Górniczo-Hutnicza im. Stanisława Staszica w KtrakowieWydział Inżynierii Metali i Informatyki StosowanejKatedra Informatyki Stosowanej i Modelowania

Sierpień 2018

Mirosław Głowacki (AGH, UJK) Programowanie w języku c++ 2018 1 / 48

Spis treści1 Zmiany w bibliotece standardowej C++2 Aktualizacja komponentów standardowej biblioteki3 Ułatwienie używania wątków4 Typy krotkowe5 Tablice mieszające6 Wyrażenia regularne7 Sprytne wskaźniki ogólnego przeznaczenia8 Rozszerzalne mechanizmy generowania liczb losowych9 Referencja adapterowa10 Polimorficzne adaptery dla obiektów funkcyjnych11 Cechy typów dla metaprogramowania12 Jednolite metody ustalenia typów zwracanych wartości wobiektach funkcyjnych

Mirosław Głowacki (AGH, UJK) Programowanie w języku c++ 2018 2 / 48

Spis treści1 Zmiany w bibliotece standardowej C++2 Aktualizacja komponentów standardowej biblioteki3 Ułatwienie używania wątków4 Typy krotkowe5 Tablice mieszające6 Wyrażenia regularne7 Sprytne wskaźniki ogólnego przeznaczenia8 Rozszerzalne mechanizmy generowania liczb losowych9 Referencja adapterowa10 Polimorficzne adaptery dla obiektów funkcyjnych11 Cechy typów dla metaprogramowania12 Jednolite metody ustalenia typów zwracanych wartości wobiektach funkcyjnych

Mirosław Głowacki (AGH, UJK) Programowanie w języku c++ 2018 3 / 48

Zmiany w bibliotece standardowej C++

Do standardowej biblioteki C++11 wprowadzone kilka zmian,które mogłyby być zaimplementowane również w starszychwersjach C++ , ale część bazuje na nowych możliwościachrdzenia języka C++11

Duża część nowych bibliotek jest zdefiniowana w dokumenciezwanym TR1 (Technical Report 1), który był opublikowany w2005 roku.

Różne pełne i częściowe implementacje TR1 są dostępne wprzestrzeni nazw std::tr1 .

W C++11 są one dostępne w przestrzeni std , jednak zostałyone uaktualnione w związku z nowymi możliwościami językaC++11

Mirosław Głowacki (AGH, UJK) Programowanie w języku c++ 2018 4 / 48

Zmiany w bibliotece standardowej C++

Główne zmiany w bibliotece standardowej C++ to:Aktualizacja komponentów standardowej bibliotekiUłatwienie używania wątkówTypy krotkoweTablice mieszająceWyrażenia regularneSprytne wskaźniki ogólnego przeznaczeniaRozszerzalne mechanizmy generowania liczb losowych

Silniki dla liczb pseudolosowychSilniki dla niedeterministycznego generatora liczb losowychRozkład liczb losowych

Referencja adapterowaPolimorficzne adaptery dla obiektów funkcyjnychCechy typów dla metaprogramowaniaJednolite metody ustalenia typów zwracanych wartości wobiektach funkcyjnych

Mirosław Głowacki (AGH, UJK) Programowanie w języku c++ 2018 5 / 48

Spis treści1 Zmiany w bibliotece standardowej C++2 Aktualizacja komponentów standardowej biblioteki3 Ułatwienie używania wątków4 Typy krotkowe5 Tablice mieszające6 Wyrażenia regularne7 Sprytne wskaźniki ogólnego przeznaczenia8 Rozszerzalne mechanizmy generowania liczb losowych9 Referencja adapterowa10 Polimorficzne adaptery dla obiektów funkcyjnych11 Cechy typów dla metaprogramowania12 Jednolite metody ustalenia typów zwracanych wartości wobiektach funkcyjnych

Mirosław Głowacki (AGH, UJK) Programowanie w języku c++ 2018 6 / 48

Aktualizacja komponentów biblioteki

C++11 oferuje liczne nowe możliwości językowe, z których mogąskorzystać komponenty istniejącej biblioteki standardowej.Przykładowo, większość komponentów biblioteki może skorzystaćna obsłudze konstruktora przenoszącego opartego na r-referencji.Korzyść może wynikać z szybkiego przenoszenia ciężkichkontenerów, jak i ich zawartości pod nowy adres pamięci.Nowe możliwości języka, z których komponenty skorzystają, to:

r-referencje i związana z tym obsługa przenoszenia,obsługa kodowania UTF-16 i UTF-32,zmienne szablony (razem z r-referencję dla pełnegoprzekazywania argumentów),wyrażenia stałe w fazie kompilacji,decltype ,

jawne operatory konwersji,metody ze specyfikatorami default i delete i inne.

Mirosław Głowacki (AGH, UJK) Programowanie w języku c++ 2018 7 / 48

Spis treści1 Zmiany w bibliotece standardowej C++2 Aktualizacja komponentów standardowej biblioteki3 Ułatwienie używania wątków4 Typy krotkowe5 Tablice mieszające6 Wyrażenia regularne7 Sprytne wskaźniki ogólnego przeznaczenia8 Rozszerzalne mechanizmy generowania liczb losowych9 Referencja adapterowa10 Polimorficzne adaptery dla obiektów funkcyjnych11 Cechy typów dla metaprogramowania12 Jednolite metody ustalenia typów zwracanych wartości wobiektach funkcyjnych

Mirosław Głowacki (AGH, UJK) Programowanie w języku c++ 2018 8 / 48

Ułatwienie używania wątków

C++11 dostarcza nowy model pamięci obsługujący wątki.

W głównej mierze możliwość wielowątkowych programów jestzasługą biblioteki standardowej C++11 .

Została dodana klasa wątku, która pobiera jako argument obiektfunkcyjny do uruchomienia w nowym wątku.

Możliwe jest zamrażanie wątku, dopóki inny wątek nie zakończyswego działania, czyli dołączanie wątku (ang. thread joining).

Dostęp do operacji specyficznych dla danej platformy jestmożliwy wszędzie tam, gdzie jest to osiągalne.

Dla synchronizacji pomiędzy wątkami do biblioteki zostałydodane też muteksy i monitory.

Są one dostępne, dla łatwiejszego użycia, poprzez blokady RAIIi algorytmy zatrzaskowe.

Mirosław Głowacki (AGH, UJK) Programowanie w języku c++ 2018 9 / 48

Spis treści1 Zmiany w bibliotece standardowej C++2 Aktualizacja komponentów standardowej biblioteki3 Ułatwienie używania wątków4 Typy krotkowe5 Tablice mieszające6 Wyrażenia regularne7 Sprytne wskaźniki ogólnego przeznaczenia8 Rozszerzalne mechanizmy generowania liczb losowych9 Referencja adapterowa10 Polimorficzne adaptery dla obiektów funkcyjnych11 Cechy typów dla metaprogramowania12 Jednolite metody ustalenia typów zwracanych wartości wobiektach funkcyjnych

Mirosław Głowacki (AGH, UJK) Programowanie w języku c++ 2018 10 / 48

Typy krotkowe

Krotki mogą być uważane za uogólnienie składowych struktur.Wersja C++11 krotki TR1 korzysta z nowych możliwości języka- ze zmiennych szablonów.Wersja ta nie wymaga jawnie zdefiniowanej maksymalnej liczbytypów, tak jak wersja z TR1 .Kompilatory mają wewnętrzne ograniczenie głębokości rekursji,ale wersja krotek z C++11 nie pokazuje tej wartości.Definicja klasy krotkowej wygląda następująco:

template <class ...Typy> class tuple;

Użycie klasy krotkowej prezentuje przykład:

# include <tuple>tuple<int, double, const char *> tpl(18, 1., "Ala");int lg = get<0>(tpl); // Przypisanie 'lg' wartości 18get<2>(tpl) = "Ola"; // Modyfikacja 3 element krotki

Mirosław Głowacki (AGH, UJK) Programowanie w języku c++ 2018 11 / 48

Typy krotkowe

Możliwe jest utworzenie krotki bez jej zawartości tylko wtedy,gdy typy elementów krotek posiadają konstruktory domyślne.Jest także możliwe przypisanie jednej krotki drugiej.Jeśli typy tych krotek są takie same, to jest wtedy konieczne abykażdy typ elementów miał konstruktor kopiujący.Jeśli nie są takie same, to każdy typ elementu po prawej stronieprzypisania musi być konwertowalny do odpowiadającego mutypu po lewej stronie lub musi istnieć konstruktor tworzącyelement na podstawie odpowiednika.

tuple< int , double, string > t1 ;tuple< char, short , const char*> t2('X', 2, "Ala");t1 = t2 ; // Ok, pierwsze dwa elementy mogą być

// skonwertowane, trzeci może być// skonstruowany z 'const char*'.

Mirosław Głowacki (AGH, UJK) Programowanie w języku c++ 2018 12 / 48

Spis treści1 Zmiany w bibliotece standardowej C++2 Aktualizacja komponentów standardowej biblioteki3 Ułatwienie używania wątków4 Typy krotkowe5 Tablice mieszające6 Wyrażenia regularne7 Sprytne wskaźniki ogólnego przeznaczenia8 Rozszerzalne mechanizmy generowania liczb losowych9 Referencja adapterowa10 Polimorficzne adaptery dla obiektów funkcyjnych11 Cechy typów dla metaprogramowania12 Jednolite metody ustalenia typów zwracanych wartości wobiektach funkcyjnych

Mirosław Głowacki (AGH, UJK) Programowanie w języku c++ 2018 13 / 48

Tablice mieszające

Zmiana dotyczy wprowadzenia do biblioteki standardowejC++11 tablic z haszowaniem lub inaczej tablic mieszających w

postaci nieuporządkowanych kontenerów asocjacyjnych.Kolizje są kontrolowane tylko za pomocą metody łańcuchowej -nie stosuje się adresowania otwartego.W celu uniknięcia kolizji nazw z niestandardowymi bibliotekamiużywany jest przedrostek unordered zamiast hash .Wprowadzono cztery typy tablic mieszających:unordered set , unordered multiset , unordered map iunordered multimap .

Nowe klasy spełniają wszystkie wymagania klasy kontenerów zSTL i mają wszystkie metody dostępowe do elementów:insert , erase , begin i end .

Wprowadzono rozszerzenie pliku nagłówkowego <functional>i dodano pliki <unordered set> i <unordered map> .

Mirosław Głowacki (AGH, UJK) Programowanie w języku c++ 2018 14 / 48

Tablice mieszające

Przykładowe zastosowanie unoredered set iunordered map :

# include <iostream># include <unordered_set># include <unordered_map>using namespace std;int main (){unordered_set<string> mySet;mySet = {"Australia", "Polska", "Austria"};for (auto it = mySet.begin(); it != mySet.end(); ++it)cout << "Kraj: " << *it << endl;

unordered_map<string, string> myMap;myMap = {{"Austria","Wieden"}, {"Polska","Warszawa"},

{"Australia","Canberra"}};for (auto it = myMap.begin(); it != myMap.end(); ++it)cout << "Kraj: " << it->first

<< ", stolica: " << it->second << endl;}

Mirosław Głowacki (AGH, UJK) Programowanie w języku c++ 2018 15 / 48

Spis treści1 Zmiany w bibliotece standardowej C++2 Aktualizacja komponentów standardowej biblioteki3 Ułatwienie używania wątków4 Typy krotkowe5 Tablice mieszające6 Wyrażenia regularne7 Sprytne wskaźniki ogólnego przeznaczenia8 Rozszerzalne mechanizmy generowania liczb losowych9 Referencja adapterowa10 Polimorficzne adaptery dla obiektów funkcyjnych11 Cechy typów dla metaprogramowania12 Jednolite metody ustalenia typów zwracanych wartości wobiektach funkcyjnych

Mirosław Głowacki (AGH, UJK) Programowanie w języku c++ 2018 16 / 48

Wyrażenia regularne

Biblioteka standardowa C++11 wprowadza obsługę popularnychwyrażeń regularnych (ang. regural expressions)Biblioteka wykorzystuje przy tym wszystkie zalety obiektowegojęzyka programowania.Nowa biblioteka, definiowana w nowym pliku nagłówkowym<regex> , składa się z klas:

instancji klasy szablonowej basic regex reprezentującejwyrażenia regularne,instancji klasy szablonowej match results reprezentującejwystąpienia.

Funkcja regex search jest używana do przeszukiwania, afunkcja regex replace do zamiany .Algorytmy regex search i regex replace przyjmująwyrażenie regularne i napis, a znalezione wystąpienia zapisują wstrukturze match results .

Mirosław Głowacki (AGH, UJK) Programowanie w języku c++ 2018 17 / 48

Wyrażenia regularnePrzykład użycia regex search :

# include <iostream># include <string># include <regex>using namespace std;int main(){string str[] = {"Kolor1: #ff0000", "Kolor2: #0000ff"};regex rgx("#([a-f0-9]{2})""([a-f0-9]{2})""([a-f0-9]{2})");smatch wyn; // "smatch" jest szablonem "match_result"

// skonkretyzowanym typem "string"for (const auto& s : str) {if(regex_search(s, wyn, rgx))cout << "Wynik '" << s << "'\n";cout << "Prefix: '" << wyn.prefix() << "'\n";for (size_t i = 0; i < wyn.size(); ++i)cout << i << ": " << wyn[i] << '\n';

cout << "Suffix: '" << wyn.suffix() << "\'\n\n";}

return 0;}

Mirosław Głowacki (AGH, UJK) Programowanie w języku c++ 2018 18 / 48

Wyrażenia regularne

Wyrażenie regularne ( regex ):"#([a-f0-9]{2})""([a-f0-9]{2})""([a-f0-9]{2})" onazwie rgx oznacza, że poszukiwany będzie wzorzec:1 posiadający na początku znak: #2 następnie: ([a-f0-9]{2}) , co oznacza dwukrotne wystąpienie

(... {2}) jednego z symboli [...] z zakresów: a do f lub 0 do 93 punkt nr 2 ma zostać powtórzony trzykrotnie.

Instrukcja regex_search(s, wyn, rgx) powodujeprzeszukanie łańcucha s celem znalezienia wyrażenia rgx , auzyskane wyniki zapisuje w obiekcie wyn typu smatch

Łańcuch znakowy wyn[0] zawiera całą odnalezioną sekwencję,

a wyn[i] , gdzie i = 1, 2, ... jej poszczególne części składowe.

wyn.prefix() i wyn.suffix oznaczają łańcuchy:poprzedzający i następujący po odnalezionej sekwencji.

Mirosław Głowacki (AGH, UJK) Programowanie w języku c++ 2018 19 / 48

Wyrażenia regularneWynikiem działania programu będzie:

Wynik ’Kolor1: #ff0000’Prefix: ’Kolor1: ’0: #ff00001: ff2: 003: 00Suffix: ’’

Wynik ’Kolor2: #0000ff’Prefix: ’Kolor2: ’0: #0000ff1: 002: 003: ffSuffix: ’’Mirosław Głowacki (AGH, UJK) Programowanie w języku c++ 2018 20 / 48

Spis treści1 Zmiany w bibliotece standardowej C++2 Aktualizacja komponentów standardowej biblioteki3 Ułatwienie używania wątków4 Typy krotkowe5 Tablice mieszające6 Wyrażenia regularne7 Sprytne wskaźniki ogólnego przeznaczenia8 Rozszerzalne mechanizmy generowania liczb losowych9 Referencja adapterowa10 Polimorficzne adaptery dla obiektów funkcyjnych11 Cechy typów dla metaprogramowania12 Jednolite metody ustalenia typów zwracanych wartości wobiektach funkcyjnych

Mirosław Głowacki (AGH, UJK) Programowanie w języku c++ 2018 21 / 48

Sprytne wskaźniki ogólnego przeznaczenia

Standard języka C++11 udostępnia udogodnienia, dzięki którymmożna wyeliminować na zawsze niektóre problemy, które byłypoważnym utrapieniem dla programistów.

Jednym z takich problemów są wycieki pamięci przy jejdynamicznym alokowaniu.

Często zapomina się o zwalnianiu (przy użyciu operatorówdelete i delete[] ) pamięci zarezerwowanej przy pomocynew oraz new[] .

Nowe udogodnienia w postaci wskaźników unikalnychunique::ptr i współdzielonych shared::ptr powodują, że z

operatora delete będziemy korzystać coraz rzadziej.

Nie są to nowe konstrukcje języka, a jedynie szablony klas zbiblioteki szablonów STL .

Mirosław Głowacki (AGH, UJK) Programowanie w języku c++ 2018 22 / 48

Sprytne wskaźniki ogólnego przeznaczenia

Szablony te wymagają co najmniej jednego parametru - typudanych na jakie wskaźnik ma pokazywać.Drugim parametrem szablonu może być specjalna klasa obiektówfunkcyjnych, która zwalnia pamięć po obiekcie.Standardowo jest używany default delete z bibliotekistandardowej - obiekt, który wykorzystuje wbudowany w językoperator delete .Aby wykorzystywać omawiane wskaźniki należy dołączyć doprojektu plik nagłówkowy #include <memory> .

Dzięki przeciążeniu operatorów: operator-> , operator* ,operator= i operator bool można korzystać z nowych

wskaźników tak samo jak ze zwykłych.Dostęp do wskazywanego adresu możliwy jest dzięki metodzieget() , więc wskaźnik można też wykorzystywać gdy wymagany

jest tradycyjnych wskaźnik.Mirosław Głowacki (AGH, UJK) Programowanie w języku c++ 2018 23 / 48

Wskaźnik unikalny

Może istnieć tylko jeden wskaźnik unikalny unique ptrpokazujący na dany obiekt.W momencie kiedy przestaje istnieć wskaźnik, usuwany jesttakże wskazywany obiekt i zwalniana pamięć.Obiekt, na który wskazuje wskaźnik jest także usuwany kiedy dowskaźnika przypisujemy inny obiekt.Wskaźnik unique ptr posiada zasoby wskazywanego obiektuna własność i jako jedyny ma prawo do ich modyfikacji - niemoże być on zarządzany przez inny sprytny wskaźnik.

int main(){int i1 = 12, i2 = 22;unique_ptr<int> uni(new int);*uni = i1;unique ptr<int> kopia = uni;shared ptr<int> kopia = uni;return 0 }

Mirosław Głowacki (AGH, UJK) Programowanie w języku c++ 2018 24 / 48

Wskaźnik współdzielony

Współdzielony wskaźnik shared ptr jest wskaźnikiem zezliczaniem referencji.Może istnieć wiele wskaźników tego typu do tego samegoobiektu (ang. aliasing).Likwidowany współdzielony wskaźnik automatycznie niszczywskazywany obiekt tylko wtedy, gdy nie ma już innychwskaźników odnoszących się do tego obiektu.

int main( ){shared_ptr<double> nowy(new double);{shared_ptr<double> kopia = nowy;*kopia = 89.3;} // Niszczenie wyłacznie wskaźnika 'kopia'return 0;

} // Niszczenie wskaźnika 'nowy' wraz z jego obiektem

Mirosław Głowacki (AGH, UJK) Programowanie w języku c++ 2018 25 / 48

Sprytne wskaźniki ogólnego przeznaczenia

Wskaźnik unique ptr jest zamiennikiem wskaźnikaauto ptr , który został oznaczony jako deprecated.

Wskaźnik unique ptr ma wszystkie możliwości auto ptr zwyjątkiem niebezpiecznego niejawnego przenoszenia z l-wartości.W przeciwieństwie do auto ptr , unique ptr może byćstosowany z kontenerami C++11 uwzględniającymi przenoszenie.Wprowadzono również pojęcie słabego wskaźnika - tzw.weak ptr , który jest referencją do shared ptr .

Istnienie wskaźnika weak ptr nie zapobiega niszczeniu obiektu.

Wskaźnik weak ptr udziela informacji, czy wskazywany obiektnadal istnieje - jeśli tak, może być podstawą dostępu do pamięci.

Aby uzyskać dostęp do wskazywanego obiektu weak ptr musizostać najpierw przekonwertowany do shared ptr .

Mirosław Głowacki (AGH, UJK) Programowanie w języku c++ 2018 26 / 48

Sprytne wskaźniki ogólnego przeznaczenia

Przykład użycia unique ptr , shared ptr i weak ptr :

# include <iostream># include <memory>using namespace std;struct myClass{void f(int i){cout << "f(" << i << ") ";} };

int main(){unique_ptr<myClass> uptr1(new myClass);unique ptr<myClass> uptr2(uptr1);shared_ptr<myClass> sptr1(new myClass);shared_ptr<myClass> sptr2(sptr1);uptr1->f(1); sptr1->f(2); (*sptr2).f(3);myClass *zw = sptr1.get();weak_ptr<myClass> wptr1 = sptr1;sptr2 = wptr1.lock(); // lock() zwraca shared_ptrwptr1->f(4); sptr1->f(5); (*sptr2).f(6);return 0; }

Mirosław Głowacki (AGH, UJK) Programowanie w języku c++ 2018 27 / 48

Spis treści1 Zmiany w bibliotece standardowej C++2 Aktualizacja komponentów standardowej biblioteki3 Ułatwienie używania wątków4 Typy krotkowe5 Tablice mieszające6 Wyrażenia regularne7 Sprytne wskaźniki ogólnego przeznaczenia8 Rozszerzalne mechanizmy generowania liczb losowych9 Referencja adapterowa10 Polimorficzne adaptery dla obiektów funkcyjnych11 Cechy typów dla metaprogramowania12 Jednolite metody ustalenia typów zwracanych wartości wobiektach funkcyjnych

Mirosław Głowacki (AGH, UJK) Programowanie w języku c++ 2018 28 / 48

Nowe mechanizmy generowania liczb losowych

Biblioteka standardowa C umożliwia generowanie liczbpseudolosowych za pomocą funkcji rand .Jednak algorytm tej funkcji odpowiada wymogom biblioteki C .C++ odziedziczyło tę funkcjonalność bez żadnych zmian.

Dopiero C++11 zapewnia nowe metody generowania liczbpseudolosowych, a funkcję generowania liczb losowychpodzielono na dwie części:

silnik generatora liczb losowych,część odpowiedzialną za rozkład losowy, który określa zakres imatematyczny rozkład wyniku.

W przeciwieństwie do standardowego rand , mechanizm C++11jest wyposażony w trzy różne algorytmy silnika:

linear congruential engine ,

subtract with carry engine ,

mersenne twister engine .

Mirosław Głowacki (AGH, UJK) Programowanie w języku c++ 2018 29 / 48

Nowe mechanizmy generowania liczb losowych

C++11 udostępnia również około 20 standardowych rozkładów:normalny, studenta, bernouliego, poissona, weibulla, χ2, itd.

Generator i rozkład są traktowane łącznie, np.:

# include <random># include <iostream># include <functional>int main(){std::default_random_engine e;std::uniform_int_distribution<unsigned int> d(0, 10);auto rnd = std::bind(d, e);for(int i = 0; i < 10; ++i)std::cout << rnd() << endl;

}

Mirosław Głowacki (AGH, UJK) Programowanie w języku c++ 2018 30 / 48

Nowe mechanizmy generowania liczb losowych

W zaprezentowanym przykładzie uniform int distributionjest szablonem funkcji rozkładu normalnego.

Klasa default random engine to instancja szablonu klas onazwie linear congruential engine - jednego z trzechwymienionych pseudo-losowych generatorów liczb losowych.

Funkcja szablonowa bind zwraca adapter obiektu funkcyjnego -tzw. call wrapper.

Mirosław Głowacki (AGH, UJK) Programowanie w języku c++ 2018 31 / 48

Spis treści1 Zmiany w bibliotece standardowej C++2 Aktualizacja komponentów standardowej biblioteki3 Ułatwienie używania wątków4 Typy krotkowe5 Tablice mieszające6 Wyrażenia regularne7 Sprytne wskaźniki ogólnego przeznaczenia8 Rozszerzalne mechanizmy generowania liczb losowych9 Referencja adapterowa10 Polimorficzne adaptery dla obiektów funkcyjnych11 Cechy typów dla metaprogramowania12 Jednolite metody ustalenia typów zwracanych wartości wobiektach funkcyjnych

Mirosław Głowacki (AGH, UJK) Programowanie w języku c++ 2018 32 / 48

Referencja adapterowa

Referencja adapterowa - reference wrapper - to szablonklasy, który opakowuje referencję w obiekt, który może byćkopiowany lub przypisywany.

Jest to mechanizm do przechowywania referencji wewnątrz tablicczy standardowych kontenerów (np. std::vector ), którezwykle nie mogą zawierać referencji.

Funkcje pomocnicze często używane do generowania obiektówstd::reference wrapper to std::ref dla dowolnej

referencji i dla stałej referencji std::cref .

# include <functional> // std::reference_wrapperint a(10),b(20),c(30);

// Tablica referencji:std::reference_wrapper<int> refs[] = {a, b, c};

Mirosław Głowacki (AGH, UJK) Programowanie w języku c++ 2018 33 / 48

Referencja adapterowa

Przykładowy program:

int main (){int a(10),b(20),c(30);std::reference_wrapper<int> refs[] = {a, b, c};int re[] = {a, b, c};a = -99;for (int& r : refs) std::cout << ' ' << r;std::cout << std::endl;for (int& r : re) std::cout << ' ' << r;std::cout << std::endl;return 0;}

i wynik jego działania (tablica re przechowuje jedynie kopie):

-99 20 3010 20 30Mirosław Głowacki (AGH, UJK) Programowanie w języku c++ 2018 34 / 48

Spis treści1 Zmiany w bibliotece standardowej C++2 Aktualizacja komponentów standardowej biblioteki3 Ułatwienie używania wątków4 Typy krotkowe5 Tablice mieszające6 Wyrażenia regularne7 Sprytne wskaźniki ogólnego przeznaczenia8 Rozszerzalne mechanizmy generowania liczb losowych9 Referencja adapterowa10 Polimorficzne adaptery dla obiektów funkcyjnych11 Cechy typów dla metaprogramowania12 Jednolite metody ustalenia typów zwracanych wartości wobiektach funkcyjnych

Mirosław Głowacki (AGH, UJK) Programowanie w języku c++ 2018 35 / 48

Polimorficzne adaptery dla obiektów funkcyjnych

Polimorficzne adaptery dla obiektów funkcyjnych są podobnesemantycznie i składniowo do wskaźników do funkcji.Są one jednak mniej ściśle wiązane i mogą ogólnie odnosić się dowszelakich odwołań do: funkcji, metod lub funktorów, którychargumenty są kompatybilne z tymi w adapterze - przykładowo:

# include <iostream># include <functional>double iloczyn(double a, double b){return a * b;}function<double (double, double)> mojAdapter;int main(){mojAdapter = iloczyn;std::cout << mojAdapter(3., 4.) << std::endl;plus<double> funSuma;mojAdapter = funSuma;std::cout << mojAdapter(1.25, 2.5) << std::endl;return 0;

}Mirosław Głowacki (AGH, UJK) Programowanie w języku c++ 2018 36 / 48

Polimorficzne adaptery dla obiektów funkcyjnych

Adapter polimorficzny mojAdapter jest obiektem klasyszablonowej function z biblioteki <functional> .Struktura szablonowa plus jest funktorem zawartym wstandardowej bibliotece C++ .Instancje tego szablonu są funktorami zawierającymi operatorT operator()(const T&, const T&) const .

Instukcja double funSuma(double, double) będzie zatemwywołaniem tego operatora na rzecz obiektu funSuma .Przypisanie mojAdapter = funSuma jest poprawne, ponieważ

zarówno adapter jak i operator() struktury plus majązgodne: parametry i typ zwracany.Instrukcja mojAdapter(1.25, 2.5) jest wywołaniem metody

operator() klasy plus za pomocą adaptera polimorficznego.

Mirosław Głowacki (AGH, UJK) Programowanie w języku c++ 2018 37 / 48

Polimorficzne adaptery dla obiektów funkcyjnych

# include <iostream># include <functional>using namespace std;struct Test{bool operator()(short x, short y){return x < y;}

};function<bool (short, short)> mojAdapter;function<int (int, int)> mojAdapter2;bool mniejszy(long x, long y){return x < y;}int main(){if (!mojAdapter){mojAdapter = &mniejszy;Test mojTest;mojAdapter = ref(mojTest);

}mojAdapter2 = mojAdapter;cout << mojAdapter2(3, 2) << endl;return 0;

}

Mirosław Głowacki (AGH, UJK) Programowanie w języku c++ 2018 38 / 48

Polimorficzne adaptery dla obiektów funkcyjnych

W przytoczonym przykładzie wyrażenie !mojAdapter jestprawdziwe ponieważ mojAdapter nie ma jeszcze przypisanejfunkcji - czyli ma przypisany NULL .

Jeśli jednak adapter nie odnosi się do żadnej funkcji to próbaodwołania do funkcji za jego pomocą, np.: mojAdapter(1, 2)powoduje wyjątek bad function call .

Przypisanie mojAdapter = ref(mojTest) jest poprawneponieważ std::ref jest funkcją szablonową zwracającąadapter metody operator() struktury mojTest .

Przypisania mojAdapter = &mniejszy imojAdapter2 = mojAdapter są poprawne, ponieważ w obu

przypadkach parametry i typ zwracany podlegają poprawnejkonwersji.

Mirosław Głowacki (AGH, UJK) Programowanie w języku c++ 2018 39 / 48

Spis treści1 Zmiany w bibliotece standardowej C++2 Aktualizacja komponentów standardowej biblioteki3 Ułatwienie używania wątków4 Typy krotkowe5 Tablice mieszające6 Wyrażenia regularne7 Sprytne wskaźniki ogólnego przeznaczenia8 Rozszerzalne mechanizmy generowania liczb losowych9 Referencja adapterowa10 Polimorficzne adaptery dla obiektów funkcyjnych11 Cechy typów dla metaprogramowania12 Jednolite metody ustalenia typów zwracanych wartości wobiektach funkcyjnych

Mirosław Głowacki (AGH, UJK) Programowanie w języku c++ 2018 40 / 48

Cechy typów dla metaprogramowania

Wiele algorytmów może operować na różnych typach danych, aszablony C++ umożliwiają programowanie generyczne i czyniąkod bardziej zwięzłym.

Niemniej jednak często w algorytmach zachodzi potrzebauzyskania informacji o używanych właśnie typach.

Takie informacje mogą być uzyskane podczas instancjonowaniaklas szablonowych przy użyciu cech typów .

Cechy typów mogą identyfikować kategorię obiektu i wszystkiewłasności klasy lub struktury.

Są one zdefiniowane w pliku nagłówkowym <type traits> .

W dwóch następnych przykładach przedstawiono zastosowanieszablonów is_floating_point i is_integral w celuwywołania funkcji o żądanych cechach typów.

Mirosław Głowacki (AGH, UJK) Programowanie w języku c++ 2018 41 / 48

Cechy typów dla metaprogramowania

# include <iostream># include <type_traits>class A {};using namespace std;int main(){cout << boolalpha;cout << is_floating_point<A>::value << endl;cout << is_floating_point<float>::value << endl;cout << is_floating_point<int>::value << endl;return 0;

}

falsetruefalse

Mirosław Głowacki (AGH, UJK) Programowanie w języku c++ 2018 42 / 48

Cechy typów dla metaprogramowania

W kolejnym przykładzie funkcja szablonowa mojAlg będzieinstancjonować jeden z dwóch proponowanych algorytmówalgStr w zależności od typów danych.

# include <iostream># include <type_traits>using namespace std;template<bool B> struct algStr{ // Szablon podstawowytemplate<typename T1, typename T2>char templFun(T1&, T2&){return '1';}

};template<> struct algStr<false>{ // Specjalizacjatemplate<typename T1, typename T2>char templFun(T1*, T2*){return '2';}

};

Mirosław Głowacki (AGH, UJK) Programowanie w języku c++ 2018 43 / 48

Cechy typów dla metaprogramowania

template<typename T1, typename T2> char mojAlg(T1 A, T2 B){algStr<is_integral<T1>::value &&

is_floating_point<T2>::value> mojaStr;return mojaStr.templFun(A, B); }

int main(){int A = 1; float B = 3.14;cout << mojAlg(A, B) << endl;cout << mojAlg(&A, &B) <<endl;return 0;

}

Przedstawiony program spowoduje następujący strumień wyjściowy:

12

Mirosław Głowacki (AGH, UJK) Programowanie w języku c++ 2018 44 / 48

Spis treści1 Zmiany w bibliotece standardowej C++2 Aktualizacja komponentów standardowej biblioteki3 Ułatwienie używania wątków4 Typy krotkowe5 Tablice mieszające6 Wyrażenia regularne7 Sprytne wskaźniki ogólnego przeznaczenia8 Rozszerzalne mechanizmy generowania liczb losowych9 Referencja adapterowa10 Polimorficzne adaptery dla obiektów funkcyjnych11 Cechy typów dla metaprogramowania12 Jednolite metody ustalenia typów zwracanych wartości wobiektach funkcyjnych

Mirosław Głowacki (AGH, UJK) Programowanie w języku c++ 2018 45 / 48

Jednolite metody ustalenia typów zwracanych

Określanie zwracanego typu szablonowego obiektu funkcyjnegow fazie kompilacji nie jest intuicyjne.Ma to zwłaszcza miejsce jeśli typ zwracany zależy odparametrów funkcji.Jako przykład można zaprezentować kod programu:

# include <iostream># include <type_traits>struct dwaTypy{double operator()(int i) const {return 1.;};int operator()(double d) const {return 2;}; };

template<typename T> struct mojaKlasa{template<typename Arg> Arg operator()(Arg& A) const{return mojePole(A); }

private:T mojePole; };

Mirosław Głowacki (AGH, UJK) Programowanie w języku c++ 2018 46 / 48

Jednolite metody ustalenia typów zwracanych

int main(){int i = 1;double d = 1.25;mojaKlasa<dwaTypy> mojObiekt;std::cout << mojObiekt(i) << std::endl;std::cout << mojObiekt(d) << std::endl;return 0;

}

Tworzenie instancji mojaKlasa<dwaTypy> spowoduje, że typ

zwracany metody operator() struktury mojaKlasa niebędzie taki sam jak w klasie dwaTypy i kompilator możewygenerować ostrzeżenia o konwersji pomiędzy int i double .

Mirosław Głowacki (AGH, UJK) Programowanie w języku c++ 2018 47 / 48

C++11 adoptuje klasę szablonową std::result_of , którapozwala na określenie i użycie typu zwracanego z obiektufunkcyjnego dla każdej deklaracji.Struktura mojaKlasa może w tym celu użyć obiektu tej klasydo określenia zwracanego typu obiektu funkcyjnego:

template<typename T> struct mojaKlasa{template<typename Arg>typename std::result_of<T(Arg)>::typeoperator()(Arg& A) const{return mojePole(A); }

private:T mojePole; };

Wynikiem działania obu wersji programu jest strumieńwyjściowy:

12Mirosław Głowacki (AGH, UJK) Programowanie w języku c++ 2018 48 / 48