24.08.2013 Aufrufe

003-Folien: Standard Template Library und Templates

003-Folien: Standard Template Library und Templates

003-Folien: Standard Template Library und Templates

MEHR ANZEIGEN
WENIGER ANZEIGEN

Erfolgreiche ePaper selbst erstellen

Machen Sie aus Ihren PDF Publikationen ein blätterbares Flipbook mit unserer einzigartigen Google optimierten e-Paper Software.

<strong>Template</strong>s <strong>und</strong> STL<br />

VL MRT-2, SS 2013<br />

Professur für Prozessleittechnik


Übersicht<br />

• Neugestaltung des endlichen Zustandsautomaten mit<br />

Containern der <strong>Standard</strong> <strong>Template</strong> <strong>Library</strong> (statt Arrays)<br />

• C++ Konzepte:<br />

– Konzepte der <strong>Standard</strong> <strong>Template</strong> <strong>Library</strong><br />

– Eigene <strong>Template</strong>s erzeugen<br />

– Spezialisierung von <strong>Template</strong>s<br />

– Boost<br />

• Entwurfsmuster:<br />

– Container <strong>und</strong> Iteratoren<br />

24.04.2013 MRT2 (c) 2013, UR Folie 2


<strong>Standard</strong> <strong>Template</strong> <strong>Library</strong> (STL)<br />

• Ziele der STL:<br />

– Hohe Wiederverwendung von Datenstrukturen <strong>und</strong> typsicherer<br />

Algorithmen auf diesen Datenstrukturen<br />

• Problem:<br />

– Es gibt unendlich viele Datentypen (Classes)<br />

– Es gibt erstaunlich viele Möglichkeiten Sammlungen von Daten<br />

anzulegen (Collections)<br />

– Es gibt eine immense Vielfalt von Dingen die wir mit den Daten<br />

tun wollen (Algorithmen)<br />

TU Dresden, 21.04.13 MRT2 2006-2011 (c) UR Folie 3


Beispiele für Algorithmen auf Sammlungen<br />

• Sortiere die Einträge eines Wörterbuchs<br />

• Suche die Telefonnummer zu einem Namen<br />

• Finde den höchsten Temperaturmesswert der vergangenen<br />

10 Jahre<br />

• Finde alle Werte > 8000<br />

• Finde die erste Instanz mit einem Wert von 17<br />

• Finde den ersten Unterschied in zwei Sequenzen<br />

• Berechne das paarweise Produkt der Elemente zweier<br />

Sequenzen<br />

• Berechne die Summe der Elemente<br />

• ...<br />

TU Dresden, 21.04.13 MRT2 2006-2011 (c) UR Folie 4


Gr<strong>und</strong>legende Konzepte der STL<br />

• Container: Objekte zur Verwaltung anderer Objekte<br />

– abgelegt als Wert (Wertsemantik) oder als Referenz<br />

– formuliert als <strong>Template</strong>-Klassen<br />

– Algorithmennamen (werden zur Compilezeit ausgewertet) sind für<br />

gleichartige Operationen, aber unterschiedliche Container gleich.<br />

Beispiel: Die Methode size() gibt die Anzahl der Elemente eines<br />

Containers zurück, sei er nun vom Typ vector,list oder map).<br />

• Iteratoren: Zugriff auf Containerelement über Iteratoren<br />

– sind normale Zeiger oder zeigerähnliche Objekte<br />

– können sich von einem zum nächsten Element weiterbewegen, Methode<br />

bleibt aber verborgen<br />

– Beispiel: in einem Vektor: ++ das einfache Weiterschalten zur nächsten<br />

Position im Speicher; in einem binären Suchbaum: ++ Entlangwandern<br />

im Baum)<br />

• Algorithmen: arbeiten mit Iteratoren, die auf Container zugreifen<br />

– Allgemeinheit des Entwurfs, arbeiten auch mit normalen Zeigern<br />

TU Dresden, 21.04.13 MRT2 2006-2011 (c) UR Folie 5


Wir nutzen in dem Automaten bereits<br />

Container <strong>und</strong> Iterator<br />

• Zeichenketten sind Containertemplates<br />

string f("--0002*30+-+1234=");<br />

• Klassisch: Iteration über C-String mit Zeiger (C):<br />

for (const char* cp = f.c_str(); *cp != 0; ++cp) { c =<br />

*cp; a.run(); }<br />

• STL-Iterator: Iteration über Container mit Iterator (C++):<br />

for (string::iterator it=f.begin(); it != f.end();<br />

++it) { c = *it; a.run(); }<br />

• Ab C++ C11: Iteration über Range<br />

for (const char cf : f) { c = cf; a.run(); }<br />

24.04.2013 MRT2 (c) 2013, UR Folie 6


Wichtige Klassen der STL<br />

• Sequenz-Container:<br />

– : basic_string, string, wstring - Zeichenketten<br />

– : deque – Liste mit zwei Enden<br />

• schnelles Anfügen von Elementen, kein wahlfreier Zugriff<br />

– : list<br />

• schnelles Anfügen von Elementen, kein wahlfreier Zugriff<br />

– : vector<br />

• schnelles Anfügen nur am Ende, wahlfreier Zugriff<br />

• Assoziative Container<br />

– : map, multimap<br />

• Paare von Schlüsseln. Einfügen, Löschen, Suchen O(log(N))<br />

– : set, multiset<br />

• Schlüssel. Komplexität wie map<br />

24.04.2013 MRT2 (c) 2013, UR Folie 7


Sequenz<br />

• Jede STL-Sammlung ist eine Sequenz<br />

– Eine Sequenz hat ein Anfang <strong>und</strong> ein Ende<br />

– Es gibt eine Möglichkeit vom Anfang zum Ende zu kommen<br />

– Anfang <strong>und</strong> Ende sind jeweils durch einen Iterator festgelegt.<br />

• Ein Iterator ist ein Objekt, das ein Element einer Sequenz<br />

identifiziert<br />

begin: end:<br />

...<br />

TU Dresden, 21.04.13 MRT2 2006-2011 (c) UR Folie 8


Iterator<br />

• Ein Iterator „zeigt“ auf ein Element einer Sammlung (oder<br />

das nach dem letzten)<br />

• Iteratoren können verglichen werden (==)<br />

• Durch dreferenzieren bekommt man das Element, auf das<br />

der Iterator zeigt (*)<br />

• Der Iterator kann auf das nächste Element der Sammlung<br />

vorwärts bewegt werden (++)<br />

TU Dresden, 21.04.13 MRT2 2006-2011 (c) UR Folie 9


Iteratoren verbinden<br />

• Iteratoren verbinden Datenstrukturen mit Algorithmen<br />

sort, find, search, copy, ...<br />

Iterator<br />

vector, list, map, array, ..., meinContainer<br />

TU Dresden, 21.04.13 MRT2 2006-2011 (c) UR Folie 10


Automaton: TransitionTable als Container<br />

der STL<br />

• Anforderungen an die TransitionTable<br />

– Elemente: Zeiger auf konstante Transition-Objekte<br />

– Neue Elemente: am Ende anfügen<br />

– Durchsuchen: linear von Anfang bis Ende<br />

• list ist ein geeigneter Container<br />

für Zeiger auf unveränderliche Objekte<br />

vom Typ Transition:<br />

#include <br />

class Automaton {<br />

list tt;<br />

Automaton(const State& startState);<br />

void add(const Transition& t);<br />

...<br />

< Parameter >:<br />

Liste, deren<br />

Elemente Zeiger auf<br />

unveränderliche<br />

Transitionsobjekte<br />

sind<br />

Referenz auf ein<br />

unveränderliches<br />

Tranisitionsobjekt<br />

24.04.2013 MRT2 (c) 2013, UR Folie 11


Automaton: TransitionTable<br />

• Modifikation Automaton.h<br />

#include <br />

class Automaton {<br />

list tt;<br />

Automaton(const State& startState);<br />

void add(const Transition& t);<br />

• Modifikation Implementierung<br />

Automaton::add(const Transition& t) {<br />

tt.push_back(&t); }<br />

Automaton::run() { // [...]<br />

for (const Transition* pt : tt) {<br />

if ( &(pt->start) == pCurrentState ) {<br />

Referenz wird wie<br />

Variable behandelt,<br />

deshalb Adresse<br />

bestimmen<br />

push_back: Element<br />

an Container<br />

anhängen<br />

Über alle Elemente<br />

der Liste<br />

24.04.2013 MRT2 (c) 2013, UR Folie 12


STL: Übersicht Container-Methoden<br />

TU Dresden, 21.04.13 MRT2 2006-2011 (c) UR Folie 13


Initialisierung TransitionTable<br />

• Objektinitialisierung<br />

Automaton a(s0);<br />

a.add(Transition(s0, s0, guardPlus));<br />

a.add(Transition(s0, s1, guardMinus, behavior_lOp_Sign));<br />

a.add(Transition(s0, s2, guardDigit, behavior_lOp_Digit));<br />

a.add(Transition(s1, s0, guardMinus, behavior_lOp_Sign));<br />

a.add(Transition(s1, s2, guardDigit, behavior_lOp_Digit));<br />

a.add(Transition(s2, s2, guardDigit, behavior_lOp_Digit));<br />

a.add(Transition(s2, s3, guardOp, behavior_Op1));<br />

// ...<br />

24.04.2013 MRT2 (c) 2013, UR Folie 14


C++: <strong>Template</strong>s - Motivation<br />

• Für alle Typen, für die die Relation < definiert ist, kann eine<br />

min bzw. max-Funktion spezifiziert werden.<br />

• Das ist mit Überladen von Funktionen in C++ gr<strong>und</strong>sätzlich<br />

lösbar:<br />

string& min(string& a, string& b) {<br />

return (a < b) ? a : b;<br />

}<br />

double& min(double& a, double& b) {<br />

}<br />

return (a < b) ? a : b;<br />

• u.s.w für alle Datentypen, für die bool T& operator


C++: Funktionstemplates<br />

string& min(string& a,<br />

string& b)<br />

{<br />

}<br />

return (a < b) ? a : b;<br />

double& min(double& a,<br />

double& b)<br />

{<br />

return (a < b) ? a : b;<br />

}<br />

• Funktionstemplate =<br />

typunabhängige Formel<br />

• Aus der Formel erzeugt der<br />

Compiler typspezifische<br />

Versionen (wenn benötigt)!<br />

template <br />

T& min(T& a, T& b)<br />

{<br />

}<br />

Parameterliste des<br />

<strong>Template</strong>s<br />

return (a < b) ? a : b;<br />

TU Dresden, 21.04.13 MRT2 2006-2011 (c) UR Folie 16


C++: <strong>Template</strong>parameterliste (1/2)<br />

• Zur Erinnerung: Funktionsparameterliste<br />

– Definiert lokale Variablen eines bestimmten Typs<br />

– Variablen werden nicht initialisiert<br />

– Belegung zur Laufzeit bei Aufruf<br />

• <strong>Template</strong>parameterliste<br />

– Liefert Typen oder Werte, die bei der Definition der Funktion<br />

oder Klasse verwendet werden können:<br />

template T& min(T& a, T& b);<br />

– Die Verwendung im Programm bestimmt, welcher Typ mit T<br />

gemeint ist.<br />

TU Dresden, 21.04.13 MRT2 2006-2011 (c) UR Folie 17


C++: <strong>Template</strong>parameterliste (2)<br />

• Typparameter<br />

– Repräsentation eines zur Zeit der Programmierung<br />

unbekannten Datentypy<br />

– Eingeleitet durch Schlüsselwort typename oder class<br />

• Nichttypparameter<br />

– Repräsentation eines zur Zeit der Programmierung<br />

unbekannten Werts<br />

– Eingeleitet durch Typspezifizierer, z.B. int, size_t<br />

TU Dresden, 21.04.13 MRT2 2006-2011 (c) UR Folie 18


C++: Regeln für <strong>Template</strong>parameter<br />

• Gültigkeitsbereich folgt den normalen Regeln des<br />

Versteckens von Namen<br />

typedef double T;<br />

template <br />

T& min(T& a, T& b)<br />

{<br />

}<br />

T tmp = a;<br />

return (a < b) ? a : b;<br />

Das globale typedef von T als<br />

double wird durch den<br />

Typparameter T versteckt.<br />

• Ein Name der als <strong>Template</strong>parameter benutzt wird, darf<br />

innerhalb des <strong>Template</strong>s nicht für etwas anderes benutzt<br />

werden!<br />

TU Dresden, 21.04.13 MRT2 2006-2011 (c) UR Folie 19


C++: <strong>Template</strong>deklaration<br />

• <strong>Template</strong>s können wie Klassen oder Funktionen auch nur<br />

deklariert werden<br />

template T &min(T &a, T &b);<br />

• In der Definition muss der Name des <strong>Template</strong>parameters<br />

nicht gleich sein!<br />

template U &min(U &a, U &b) { /**/ };<br />

TU Dresden, 21.04.13 MRT2 2006-2011 (c) UR Folie 20


Anwendung Automaton<br />

• Problembeschreibung: State <strong>und</strong> Transition sind<br />

zugeschnitten auf Verhaltensspezifikationen vom Typ<br />

typedef function Behavior;<br />

• Herausforderung: Beschreibung der Klassen als <strong>Template</strong>,<br />

damit der Compiler typsicheren Code für<br />

Strategiefunktionen erzeugt, beispielsweise zur Übergabe<br />

von const char, int, container, shared memory...<br />

State s0("s0",...);<br />

Automaton a(s0);<br />

TU Dresden, 21.04.13 MRT2 2006-2011 (c) UR Folie 21


Vorbereitung (1/3) CalcAsFSM<br />

• Schritt 1: Die ad-hoc Realisierung des Speichers als globale<br />

Variablen <strong>und</strong> Funktionen war keine gute Praxis<br />

• Kapseln in Klasse Calc<br />

typedef char const cc;<br />

class Calc {<br />

// rechter Operand - Wert <strong>und</strong> Vorzeichen<br />

int rOp;<br />

int rSign;<br />

// ...<br />

Das wird später<br />

unser <strong>Template</strong>parameter!<br />

void behavior_rOp_Digit(const AutomatonElement& ae, cc& c) {<br />

rOp = rOp * 10 + c - '0';<br />

}<br />

24.04.2013 MRT2 (c) 2013, UR Folie 22


Vorbereitung (2/3) Automaton<br />

• Schritt 2: Verwendung von std::function in Automaton für<br />

die vereinheitlichte Behandlung von Methoden <strong>und</strong><br />

Funktionen<br />

• Behavior.h<br />

#include <br />

using namespace std;<br />

Rückgabewert<br />

Argumentliste<br />

// Typdefinition für<br />

typedef std::function Behavior;<br />

void defaultBehavior(const AutomatonElement&, const char&);<br />

// default behavior<br />

24.04.2013 MRT2 (c) 2013, UR Folie 23


Vorbereitung (3/3) CalcAsFSM<br />

• Schritt 3: Definition der Strategy durch Binden der<br />

Methoden der Klasse Calc an das Object<br />

calc<br />

#include <br />

using namespace std;<br />

using namespace std::placeholders;<br />

int main() {<br />

// ...<br />

Calc calc();<br />

// ...<br />

State s0("0",<br />

defaultBehavior,<br />

defaultBehavior,<br />

std::bind(&Calc::behavior_logState,&calc,_1,_2);<br />

Binden der Argumente<br />

std::placeholders::_1,<br />

std::placeholders::_2,<br />

std::function auch für<br />

Funktionszeiger<br />

Methode<br />

Instanzreferenz<br />

Argumentliste ermöglicht<br />

Umsortieren, Variablen<br />

24.04.2013 MRT2 (c) 2013, UR Folie 24


<strong>Template</strong>s für leere Verhaltensfunktionen<br />

(Behavior.h, AutomatonElement.h)<br />

• <strong>Template</strong>-Typdefinition für Behavior (leider erst ab C++11)<br />

template <br />

using Behavior = std::function<<br />

void(constAutomatonElement&, T&)>;<br />

( Bis dahin jeweils lokal in den Klassen zu definieren)<br />

• Verhaltensspezifikationen für „Nichts Tun“<br />

template <br />

void defaultBehavior(const AutomatonElement& ae, T&<br />

arg) {<br />

#ifdef DEBUG<br />

clog


Klassentemplate für State<br />

(analog für Transition)<br />

template <br />

class State: public AutomatonElement {<br />

typedef std::function Behavior;<br />

private:<br />

Behavior enterFunc;<br />

public:<br />

State(const string& id, Behavior enterFunc =<br />

defaultBehavior, [...]) :<br />

AutomatonElement(id), enterFunc(enterFunc), [...] { }<br />

inline void enter(T& arg) const {<br />

enterFunc(*this, arg);<br />

private:<br />

static const string myType;<br />

}<br />

template <br />

const string State::myType = "state";<br />

<strong>Template</strong>parameter<br />

T<br />

Wird bei lokaler<br />

Typdefinition des<br />

Funktionszeigers<br />

eingesetzt!<br />

Nachgestellt:<br />

Direkte<br />

Spezifikation der<br />

Funktion ohne<br />

Argumentliste!<br />

Alle Methoden die<br />

T verwenden!<br />

Implementierungen<br />

müssen auch als<br />

<strong>Template</strong> formuliert<br />

werden<br />

24.04.2013 MRT2 (c) 2013, UR Folie 26


Klassentemplate für Automaton<br />

template <br />

class Automaton {<br />

private:<br />

State const * pCurrentState;<br />

list< Transition const * > tt;<br />

int currentStateTicks;<br />

bool first;<br />

public:<br />

};<br />

Automaton(State const & startState);<br />

~Automaton();<br />

void add(Transition const & t);<br />

void run(T& arg);<br />

Bei allen betroffene<br />

Datentypen<br />

„durchziehen“<br />

Ein geschachteltes<br />

<strong>Template</strong>!<br />

24.04.2013 MRT2 (c) 2013, UR Folie 27


Implementierungen (1/3)<br />

template <br />

Automaton::Automaton(State const & startState) :<br />

pCurrentState(&startState), currentStateTicks(0),<br />

first(true) { }<br />

template <br />

void Automaton::add(Transition const & t) {<br />

}<br />

tt.push_back(new Transition(t));<br />

template <br />

Automaton::~Automaton() {<br />

}<br />

for (typename list::iterator it=tt.begin();<br />

it != tt.end(); ++it) delete (*it);<br />

tt.clear(); // eventually clear tt<br />

Implementierungen<br />

sind ebenfalls<br />

<strong>Template</strong>s<br />

Lege Zeiger auf<br />

eine dynamisch<br />

erzeugte Kopie in<br />

der Sammlung ab<br />

Alles was mit new<br />

angelegt wurde<br />

muss selbst mit<br />

delete aufgeräumt<br />

werden !!!!<br />

24.04.2013 MRT2 (c) 2013, UR Folie 28


Implementierungen (2/3)<br />

template <br />

Automaton::Automaton(State const & startState) :<br />

pCurrentState(&startState), currentStateTicks(0),<br />

first(true) { }<br />

template <br />

void Automaton::add(Transition const & t) {<br />

}<br />

tt.push_back(new Transition(t));<br />

template <br />

Automaton::~Automaton() {<br />

}<br />

for (typename list::iterator it=tt.begin();<br />

it != tt.end(); ++it) delete (*it);<br />

tt.clear(); // eventually clear tt<br />

Hier benötigt der<br />

Compiler unsere<br />

Hilfe: er kann nicht<br />

selbst entscheiden<br />

ob er einen Typ<br />

oder eine Instanz<br />

anlegen soll.<br />

24.04.2013 MRT2 (c) 2013, UR Folie 29

Hurra! Ihre Datei wurde hochgeladen und ist bereit für die Veröffentlichung.

Erfolgreich gespeichert!

Leider ist etwas schief gelaufen!