STL - Standard Template Library 2 (STL od źródeł , czyli specyfikacja biblioteki)

Preview:

DESCRIPTION

STL - Standard Template Library 2 (STL od źródeł , czyli specyfikacja biblioteki). Autor: Błażej Chodarcewicz rainbow.mimuw.edu.pl/~bc189380/STL/. Standard C++ (STL). Organizacja pracująca nad standardem http://anubis.dkuug.dk/jtc1/sc22/wg21/ Wersja Draft 1996 r. - PowerPoint PPT Presentation

Citation preview

STL - Standard Template Library 2(STL od źródeł, czyli specyfikacja biblioteki)

Autor: Błażej Chodarcewiczrainbow.mimuw.edu.pl/~bc189380/STL/

Standard C++ (STL)

Organizacja pracująca nad standardem http://anubis.dkuug.dk/jtc1/sc22/wg21/

Wersja Draft 1996 r.

ISO-IEC 14882 Programming.Language.C++ (1998) ISO/IEC 14882:2003

Jak to działa?

Iteratory

Uogólnienie wstaźników Umożliwiają pracę z kontenerami w ujednolicony sposób Biblioteka formalizuje interfejs, semantykę oraz założenia

złożonościowe Semantyka iteratorów jest uogólnieniem semantyki

wskaźników Wyrażenie *i – wartością jest obiekt pewnej klasy,

enumeracja lub typ wbudowany T, zwany value type of iterator

Wszystkie iteratory i, dla których (*i).m jest zdefiniowane, wspierają także wyrażenie i->m

Dla każdego iteratora typu X, dla którego zdefiniowana jest równość, jest dostępny typ difference type iteratora

Rodzaje iteratorów

input iteratorsoutput iteratorsforward iteratorsbidirectional iteratorsrandom access iterators

Relacje pomiędzy iteratorami

Input Output

Forward

Bidirectional

Random Access

Iteratory zmienialne i niezmienialne

mutable, constant iterators*i jako referencja lub referencja do stałejIteratory stałe nie spełniają wymagań output

iterators

past-the-end value

Dla każdego iteratora istnieje wartość wskazująca na element za ostatnim elementem kolekcji, z którą związany jest iterator

dereferencable values Biblioteka nigdy nie zakłada, że past-the-end value jest

dereferencable

Kilka definicji

Iterator i jest reachable z iteratora i wtw., gdy istnieje skończona sekwencja aplikacji wyrażenia ++i, po której mamy i == j.

Jeśłi i jest reachable z j, to i i j odnoszą się do tej samej kolekcji Range – para iteratorów, które określają początek i koniec obliczeń Range [i, i) – empty range W ogólności range [i, j) odnosi się do elementów struktury

danych zaczynających się od elementu wskazywanego przez i, kończących się na elemencie wskazywanym przez j bez tego elementu

Range [i, j) jest prawidłowe wtw., gdy j jest reachable z i. Aplikacja algorytmu dla nieprawidłowego Range jest nieokreślona

Kilka założeń

Złożoność (zamortyzowana) wszystkich operacji wymaganych dla danej kategorii iteratora jest stała

Na następnych slajdach występują:a, b oznaczają wartości iteratora X, n oznacza wartość typu difference type Distance; u, tmp i m oznaczają identyfikatory, r oznacza wartość X&, t oznacza wartość typu wartości iteratora - T.

Input iterator - wymagania

Operacja Typ Semantyka, założeniaX u(a); X post: u jest kopią a

Destruktor musi być zdefiniowany i dostępny.

u = a; X wynik: u post: u jest kopią a

a == b convertible to bool

== jest relacją równości (w matematycznym sensie) zdefiniowaną na dziedzinie wartości iteratora

a != b convertible to bool

bool(a==b) != bool(a!=b) dla dziedziny ==

*a T pre: a jest dereferenceable

Jeśli a==b i (a,b) należy do dziedziny relacji ==, wtedy *a jest takie samo jak *b.

a->m pre: (*a).m jest dobrze zdefiniowaneSemantyka jest taka sama jak (*a).m

Input iterator – wymagania c.d.

Operacja Typ Semantyka, założenia++r X& pre: r jest dereferenceable

post: r jest dereferenceable lub r jest wartością past-the-end

post: każda kopia poprzednij wartości r nie musi już być ani dereferenceable, ani nawet nie musi

być w dziedzinie ==

(void)r++ taka sama jak (void)++r

*r++ T { T tmp = *r; ++r; return tmp; }

Input iterator – uwagi

a == b nie implikuje ++a == ++bAlgorytmy nigdy nie powinny próbować

przechodzi po tym samym iteratorze dwa razyTyp wartości T nie musi być typem lvalue

(Przykład istream_iterator)

Output iterator - wymagania

Operacja Zwracany typ

Semantyka, założenia

X(a) X a = t jest takie samo jak X(a) = tZakłada się obecność destruktora

X u(a); SGI: pre: a musi być zainicjalizowane

post: *a = t jest takie samo jak *u = tX u = a;

*a = t nieużywany SGI: pre: a jest dereferencable

po poprzednim przypisaniu było wykonane zwiększenie a

++r X& &r == &++r

r++ konwertowalny do const

X&

{ X tmp = r; const X& ++r; return tmp; }

*r++ = t nieużywany

Output iterator - uwagi

operator * może zostać użyty jedynie po lewej stronie wyrażenia przypisania

przypisanie poprzez wartość iteratora odbywa się tylko raz

nigdy nie należy przechodzić po tych samych wartościach iteratora więcej niż raz

== i != mogą być niezdefiniowane

Forward iterator - wymagania

Operacja Typ Semantyka, założeniaX u; u może być niezainicjowane, zakładane jest istnienie

destruktora

X u(a);X u = a;

X równoważne: X u; u = a;

post: u == a

X(a) X X(a) == a

a == b convertible to bool

== jest relacją równości (w matematycznym sensie) zdefiniowaną na dziedzinie wartości iteratora

a != b convertible to bool

!(a==b)

r = a X& post: r == a

Forward iterator – wymagania c.d.

Operacja Typ Semantyka, założenia*a T& pre: a jest dereferenceable

Jeśli a == b, to *a == *bJeśli X jest typem mutowalnym, to *a = t jest

poprawne

a->m pre: (*a).m jest dobrze zdefiniowaneSemantyka jest taka sama jak (*a).m

++r X& pre: r jest dereferenceablepost: r jest dereferenceable lub r jest wartością

past-the-endJeśli r == s i r jest dereferencable, to ++r ==

++s.&r == &++r

r++ konwertowalny do const X&

{ X tmp = r; ++r; return tmp; }

*r++ T&

Bidirectional iterator – dodatkowe wymagania

Operacja Typ Semantyka, założenia

--r X& pre: istnieje s takie, że r == ++s.post: r jest dereferenceable.

Jeśli –r == --s, to r == s.&r == &--r.--(++r) = r.

r-- konwertowalny do const X&

{ X tmp = r; --r; return tmp; }

*r-- konwertowalny do T

Random access iterator - wymagania

Operacja Typ Semantyka, założeniar += n X& { Distance m = n;

if (m >= 0) while (m--) ++r; else while (m++) --r;

return r; }

a + nn + a

X { X tmp = a;return tmp += n; }

założenie: a + n == n + a

r -= n X& return r += -n;

a – n X { X tmp = a;return tmp -= n; }

b – a Distance pre: Istnieje wartość n typu Distance taka, że

a + n == b.

b == a + (b – a).

(a < b) ? distance(a, b) : -distance(b, a).

Random access iterator – wymagania c.d.

Operacja Typ Semantyka, założeniaa[n] konwertowalny

do T*(a + n)

a < b konwertowalny do bool

true wtw., gdy b – a > 0.> jest relacją porządku liniowego.

a > b konwertowalny do bool

równoważne z b < a.

> jest relacją porządku liniowego

a <= b konwertowalny do bool

takie samo jak: !(a > b)

a >= b konwertowalny do bool

takie samo jak: !(a < b)

Przykłady

int main(){int array [1000], *i; int n = 0; i = array;while (cin >> *i) ++i;++i;sort (array, i); for (j = array; i != j; j++) cout << *j << "\n";

}

Przykład

int main () {

vector<int> v; int input; while (cin >> input) v.push_back (input);sort(v.begin(), v.end()); for (vector<int>::iterator i = v.begin(); i != v.end(); i++)

cout << *i << "\n"; }

Obiekty funkcyjne

Obiekty funkcyjne to obiekty, które mają zdefiniowany operator ()

Są ważną częścią biblioteki STL, zapewniają one efektywność Wszędzie tam, gdzie szablony algorytmów oczekują

wskaźników do funkcji, można stosować obiekty funkcyjne Używanie obiektów funkcyjnych razem z szablonami funkcji

zwiększa siłę wyrazu biblioteki, a także zwiększa efektywność kodu

Obiekty funkcyjne – przykłady

dodanie elementów dwóch wektorów (double) a, b do siebie

transform(a.begin(), a.end(), b.begin(), a.begin(), plus<double>());

zanegowanie wszystkich elementów a:

transform(a.begin(), a.end(), a.begin(), negate<double>());

Obiekty funkcyjne

template <class Arg, class Result> struct unary_function {

typedef Arg argument_type;typedef Result result_type;

};

template <class Arg1, class Arg2, class Result> struct binary_function {

typedef Arg1 first_argument_type;typedef Arg2 second_argument_type;typedef Result result_type;

};

Obiekty funkcyjne – przykłady

template <class T> struct plus : binary_function<T,T,T> { T operator()(const T& x, const T& y) const;

};

Obiekt funkcyjny obliczający x + y.

template <class T> struct negate : unary_function<T,T> { T operator()(const T& x) const;

};

Obiekt funkcyjny obliczający –x.

Obiekty funkcyjne – przykłady

template <class Operation> class binder1st : public unary_function<Operation::second_argument_type, Operation::result_type> { protected:

Operation op; Operation::first_argument_type value;

public: binder1st(const Operation& x, const

Operation::first_argument_type& y); result_type operator()(const argument_type& x) const;

}; Konstruktor inicjalizuje op na x, value na y Operator () zwraca op(value, x) template <class Operation, class T>

binder1st<Operation> bind1st(const Operation& op, const T& x);

EqualityComparable

Typ T jest EqualityComparable jeśli ma zdefiniowany operator ==, którego wynik jest konwertowalny do bool oraz

== jest relacją równości spełniającą założenia:- Dla każdego a: a == a- Jeśli a == b, to b == a- Jeśli a == b i b == c, to a == c

Algorytmy Non-mutating template <class InputIterator, class UnaryFunction>

UnaryFunction for_each(InputIterator first, InputIterator last, UnaryFunction f);

Efekt: Zaaplikowanie f do wyników dereferencii kolejnych wartości iteratora w przedziale [first, last), zaczynając od first i kontynuując aż do last - 1. Wymagania: f nie powinno wywoływać żadnych funkcji, które nie są zadeklarowane jako stałe dla wartości iteratora. Zwraca: f. Złożoność: f jest wywoływana dokładnie last - first razy. Uwaga: Jeśli f zwraca jakąś wartość wynik jest ignorwany.

template <class InputIterator, class EqualityComparable>iterator_traits<InputIterator>::difference_type count(InputIterator first, InputIterator last, const EqualityComparable& value); Wymagania: Typ T jest EqualityComparable.Efekt: Zwraca liczbę iteratorów i z przedziału [first, last), dla których warunek: *i == value.

Algorytmy Non-mutating

template<class InputIterator, class EqualityComparable> InputIterator find(InputIterator first, InputIterator last, const EqualityComparable& value)Wymagania: Typ T is EqualityComparable.Wynik: Pierwszy iterator i z przedziału [first, last), dla którego prawdziwy jest warunek: *i == value. Jeśli żaden iterator z tego przedziału nie spełnia tego warunku zwracany jest last.

template<class InputIterator, class OutputIterator> OutputIterator copy(InputIterator first, InputIterator last, OutputIterator result); Efekt: kopiuje elementy z przedziału [first, last) do [result, result+(last-first)) zaczynając od first i kontynuując aż do last. Dla każdej nieujemnej liczby n < (last-first), wykonuje *(result+n) = *(first+n). Wynik: result + (last - first). Wymagania: result nie powinien być z przedziału [first, last). Złożoność: dokładnie last - first przypisań.

Przykład:

template<class T> struct print : public unary_function<T, void>{ print(ostream& out) : os(out), count(0) {} void operator() (T x) { os << x << ' '; ++count; } ostream& os; int count;};

int main(){ int A[] = {1, 4, 2, 8, 5, 7}; const int N = sizeof(A) / sizeof(int);

print<int> P = for_each(A, A + N, print<int>(cout)); cout << endl << P.count << " objects printed." << endl;}

Gdzie szukać informacji?

Musser Saini, STL Tutorial and Reference Lippman, "Istota jezyka C++„N.M.Josuttis, C++ bibliotek standardowa

podrecznik programistywww-d0.fnal.gov/~dladams/cxx_standard.pdfhttp://anubis.dkuug.dk/jtc1/sc22/open/n2356/

Gdzie szukać informacji?

http://www.sgi.com/tech/stl/ - implementacja STL firmy Silicon Graphics, Inc. (SGI)

http://www.informatik.hs-bremen.de/~brey/stlbe.html - książka "Designing Components with the C++ STL"

http://www.xraylith.wisc.edu/~khan/software/stl/STL.newbie.html - strona o STL z 1995 roku

http://www.cs.brown.edu/people/jak/proglang/cpp/stltut/tut.html - prosty tutorial

http://www.cs.rpi.edu/~wiseb/xrds/ovp2-3b.html - krótki opis STL'a http://pages.cpsc.ucalgary.ca/~kremer/STL/1024x768/index.html -

strona o STL'u

Dziękuję za uwagę!