Die Wiederverwendung von algorithmischem Code ist schwierig, und generische Programmierung verspricht eine Lösung. Der Vortrag gibt eine Einführung in die generische Programmierung mit C++ anhand eines einfachen Beispiels, das aber doch seine Tücken hat.
Reuse of algorithmic code is difficult, and generic programming is a potential solution. The talk gives a gentle introduction to generic programming in C++, using a simple example which however has some pitfalls.
Web page with further information: http://www.berti-cmm.de/en/techinfo/generic-programming/
11. C-Stil generics
Motivation
Traditionelle
Ansaetze
C-Stil generics
DS-Standardisierung
Macros
OO
Wiederverwendung
ist ein Problem!
generic idea
Liften
Generische
Programmierung
Fazit
Generische Programmierung 7 / 60
void* interfaces & casting
Z.B. C-Standard-Bibliothek quicksort:
void qsort (void *base , size_t n, size_t sz ,
int (* less )( const void*,const void *));
Unser sum w¨urde so aussehen:
void sum (void* v, int n, int sz , void* res ,
void (* plus )( void*, void*, void *));
12. C-Stil generics
Motivation
Traditionelle
Ansaetze
C-Stil generics
DS-Standardisierung
Macros
OO
Wiederverwendung
ist ein Problem!
generic idea
Liften
Generische
Programmierung
Fazit
Generische Programmierung 7 / 60
void* interfaces & casting
Z.B. C-Standard-Bibliothek quicksort:
void qsort (void *base , size_t n, size_t sz ,
int (* less )( const void*,const void *));
Unser sum w¨urde so aussehen:
void sum (void* v, int n, int sz , void* res ,
void (* plus )( void*, void*, void *));
→ Nicht typ-sicher
13. C-Stil generics
Motivation
Traditionelle
Ansaetze
C-Stil generics
DS-Standardisierung
Macros
OO
Wiederverwendung
ist ein Problem!
generic idea
Liften
Generische
Programmierung
Fazit
Generische Programmierung 7 / 60
void* interfaces & casting
Z.B. C-Standard-Bibliothek quicksort:
void qsort (void *base , size_t n, size_t sz ,
int (* less )( const void*,const void *));
Unser sum w¨urde so aussehen:
void sum (void* v, int n, int sz , void* res ,
void (* plus )( void*, void*, void *));
→ Nicht typ-sicher
→ Muss typ-spezifische Infos explizit ¨ubergeben (sz)
14. C-Stil generics
Motivation
Traditionelle
Ansaetze
C-Stil generics
DS-Standardisierung
Macros
OO
Wiederverwendung
ist ein Problem!
generic idea
Liften
Generische
Programmierung
Fazit
Generische Programmierung 7 / 60
void* interfaces & casting
Z.B. C-Standard-Bibliothek quicksort:
void qsort (void *base , size_t n, size_t sz ,
int (* less )( const void*,const void *));
Unser sum w¨urde so aussehen:
void sum (void* v, int n, int sz , void* res ,
void (* plus )( void*, void*, void *));
→ Nicht typ-sicher
→ Muss typ-spezifische Infos explizit ¨ubergeben (sz)
→ keine M¨oglichkeit von Typ-Spezialisierungen
22. Wiederverwendung mit Makros
Motivation
Traditionelle
Ansaetze
C-Stil generics
DS-Standardisierung
Macros
OO
Wiederverwendung
ist ein Problem!
generic idea
Liften
Generische
Programmierung
Fazit
Generische Programmierung 9 / 60
#define MAX(a, b) ( (a) <= (b) ? (a) : (b) )
F¨ur die Summe wird’s schon schwierig:
#define SUM(v, n, type) ????
23. Wiederverwendung mit Makros
Motivation
Traditionelle
Ansaetze
C-Stil generics
DS-Standardisierung
Macros
OO
Wiederverwendung
ist ein Problem!
generic idea
Liften
Generische
Programmierung
Fazit
Generische Programmierung 9 / 60
#define MAX(a, b) ( (a) <= (b) ? (a) : (b) )
F¨ur die Summe wird’s schon schwierig:
#define SUM(v, n, type) ????
Also eher
#define DEFINE_SUM (type)
type sum_ ## type (type* v, int n) { type res = 0; ... }
DEFINE_SUM (float )
DEFINE_SUM (double )
24. Wiederverwendung mit Makros
Motivation
Traditionelle
Ansaetze
C-Stil generics
DS-Standardisierung
Macros
OO
Wiederverwendung
ist ein Problem!
generic idea
Liften
Generische
Programmierung
Fazit
Generische Programmierung 9 / 60
#define MAX(a, b) ( (a) <= (b) ? (a) : (b) )
F¨ur die Summe wird’s schon schwierig:
#define SUM(v, n, type) ????
Also eher
#define DEFINE_SUM (type)
type sum_ ## type (type* v, int n) { type res = 0; ... }
DEFINE_SUM (float )
DEFINE_SUM (double )
→ Makro-Definition ausserhalb der Sprache
25. Wiederverwendung mit Makros
Motivation
Traditionelle
Ansaetze
C-Stil generics
DS-Standardisierung
Macros
OO
Wiederverwendung
ist ein Problem!
generic idea
Liften
Generische
Programmierung
Fazit
Generische Programmierung 9 / 60
#define MAX(a, b) ( (a) <= (b) ? (a) : (b) )
F¨ur die Summe wird’s schon schwierig:
#define SUM(v, n, type) ????
Also eher
#define DEFINE_SUM (type)
type sum_ ## type (type* v, int n) { type res = 0; ... }
DEFINE_SUM (float )
DEFINE_SUM (double )
→ Makro-Definition ausserhalb der Sprache
→ keine M¨oglichkeit von Typ-Spezialisierungen
26. Wiederverwendung mit Makros
Motivation
Traditionelle
Ansaetze
C-Stil generics
DS-Standardisierung
Macros
OO
Wiederverwendung
ist ein Problem!
generic idea
Liften
Generische
Programmierung
Fazit
Generische Programmierung 9 / 60
#define MAX(a, b) ( (a) <= (b) ? (a) : (b) )
F¨ur die Summe wird’s schon schwierig:
#define SUM(v, n, type) ????
Also eher
#define DEFINE_SUM (type)
type sum_ ## type (type* v, int n) { type res = 0; ... }
DEFINE_SUM (float )
DEFINE_SUM (double )
→ Makro-Definition ausserhalb der Sprache
→ keine M¨oglichkeit von Typ-Spezialisierungen
→ Explizite Vorab-Instantiierung n¨otig
27. Kapselung vs. Wiederverwendung
Motivation
Traditionelle
Ansaetze
C-Stil generics
DS-Standardisierung
Macros
OO
Wiederverwendung
ist ein Problem!
generic idea
Liften
Generische
Programmierung
Fazit
Generische Programmierung 10 / 60
Objektorientierung heisst oft Datenkapselung
class Array {
virtual Num sum() = 0;
// ...
};
class DoubleArray : Array {
virtual double sum();
};
class IntArray : Array {
virtual int sum();
};
28. Kapselung vs. Wiederverwendung
Motivation
Traditionelle
Ansaetze
C-Stil generics
DS-Standardisierung
Macros
OO
Wiederverwendung
ist ein Problem!
generic idea
Liften
Generische
Programmierung
Fazit
Generische Programmierung 10 / 60
Objektorientierung heisst oft Datenkapselung
class Array {
virtual Num sum() = 0;
// ...
};
class DoubleArray : Array {
virtual double sum();
};
class IntArray : Array {
virtual int sum();
};
→ Neu-Implementierung von sum pro Subklasse
29. Kapselung vs. Wiederverwendung
Motivation
Traditionelle
Ansaetze
C-Stil generics
DS-Standardisierung
Macros
OO
Wiederverwendung
ist ein Problem!
generic idea
Liften
Generische
Programmierung
Fazit
Generische Programmierung 10 / 60
Objektorientierung heisst oft Datenkapselung
class Array {
virtual Num sum() = 0;
// ...
};
class DoubleArray : Array {
virtual double sum();
};
class IntArray : Array {
virtual int sum();
};
→ Neu-Implementierung von sum pro Subklasse
→ ¨ubertriebene Datenkapselung verhindert Wiederverwendung:
Algorithmen-Implementierung ist in Klasse vergraben
30. Kapselung vs. Wiederverwendung
Motivation
Traditionelle
Ansaetze
C-Stil generics
DS-Standardisierung
Macros
OO
Wiederverwendung
ist ein Problem!
generic idea
Liften
Generische
Programmierung
Fazit
Generische Programmierung 10 / 60
Objektorientierung heisst oft Datenkapselung
class Array {
virtual Num sum() = 0;
// ...
};
class DoubleArray : Array {
virtual double sum();
};
class IntArray : Array {
virtual int sum();
};
→ Neu-Implementierung von sum pro Subklasse
→ ¨ubertriebene Datenkapselung verhindert Wiederverwendung:
Algorithmen-Implementierung ist in Klasse vergraben
→ Beispiel: std::string::find xxx()
32. Objekt-orientierte Versuche: Polymorphie
Motivation
Traditionelle
Ansaetze
C-Stil generics
DS-Standardisierung
Macros
OO
Wiederverwendung
ist ein Problem!
generic idea
Liften
Generische
Programmierung
Fazit
Generische Programmierung 11 / 60
class Num { virtual Num& operator+=(Num&) = 0; };
class Dbl : Num { Num& operator+=(Num&); };
class Int : Num { Num& operator+=(Num&); };
33. Objekt-orientierte Versuche: Polymorphie
Motivation
Traditionelle
Ansaetze
C-Stil generics
DS-Standardisierung
Macros
OO
Wiederverwendung
ist ein Problem!
generic idea
Liften
Generische
Programmierung
Fazit
Generische Programmierung 11 / 60
class Num { virtual Num& operator+=(Num&) = 0; };
class Dbl : Num { Num& operator+=(Num&); };
class Int : Num { Num& operator+=(Num&); };
Num* sum(Num** v, int n){
Num* s = v[0]->zero ();
for(int i=0; i<n; ++i)
*s += *v[i];
return s;
}
Dbl* v[8] = { new Dbl(0), ..};
Num* s = sum(v, 8) // Error
34. Objekt-orientierte Versuche: Polymorphie
Motivation
Traditionelle
Ansaetze
C-Stil generics
DS-Standardisierung
Macros
OO
Wiederverwendung
ist ein Problem!
generic idea
Liften
Generische
Programmierung
Fazit
Generische Programmierung 11 / 60
class Num { virtual Num& operator+=(Num&) = 0; };
class Dbl : Num { Num& operator+=(Num&); };
class Int : Num { Num& operator+=(Num&); };
Num* sum(Num** v, int n){
Num* s = v[0]->zero ();
for(int i=0; i<n; ++i)
*s += *v[i];
return s;
}
Dbl* v[8] = { new Dbl(0), ..};
Num* s = sum(v, 8) // Error
Num* v[7] = { new Dbl(0), ..};
Num* s1 = sum(v, 8); // OK
35. Objekt-orientierte Versuche: Polymorphie
Motivation
Traditionelle
Ansaetze
C-Stil generics
DS-Standardisierung
Macros
OO
Wiederverwendung
ist ein Problem!
generic idea
Liften
Generische
Programmierung
Fazit
Generische Programmierung 11 / 60
class Num { virtual Num& operator+=(Num&) = 0; };
class Dbl : Num { Num& operator+=(Num&); };
class Int : Num { Num& operator+=(Num&); };
Num* sum(Num** v, int n){
Num* s = v[0]->zero ();
for(int i=0; i<n; ++i)
*s += *v[i];
return s;
}
Dbl* v[8] = { new Dbl(0), ..};
Num* s = sum(v, 8) // Error
Num* v[7] = { new Dbl(0), ..};
Num* s1 = sum(v, 8); // OK
v[9] = new Int (5);
Num* s2 = sum(v, 8); // Bumm
36. Objekt-orientierte Versuche: Polymorphie
Motivation
Traditionelle
Ansaetze
C-Stil generics
DS-Standardisierung
Macros
OO
Wiederverwendung
ist ein Problem!
generic idea
Liften
Generische
Programmierung
Fazit
Generische Programmierung 11 / 60
class Num { virtual Num& operator+=(Num&) = 0; };
class Dbl : Num { Num& operator+=(Num&); };
class Int : Num { Num& operator+=(Num&); };
Num* sum(Num** v, int n){
Num* s = v[0]->zero ();
for(int i=0; i<n; ++i)
*s += *v[i];
return s;
}
Dbl* v[8] = { new Dbl(0), ..};
Num* s = sum(v, 8) // Error
Num* v[7] = { new Dbl(0), ..};
Num* s1 = sum(v, 8); // OK
v[9] = new Int (5);
Num* s2 = sum(v, 8); // Bumm
37. Objekt-orientierte Versuche: Polymorphie
Motivation
Traditionelle
Ansaetze
C-Stil generics
DS-Standardisierung
Macros
OO
Wiederverwendung
ist ein Problem!
generic idea
Liften
Generische
Programmierung
Fazit
Generische Programmierung 11 / 60
class Num { virtual Num& operator+=(Num&) = 0; };
class Dbl : Num { Num& operator+=(Num&); };
class Int : Num { Num& operator+=(Num&); };
Num* sum(Num** v, int n){
Num* s = v[0]->zero ();
for(int i=0; i<n; ++i)
*s += *v[i];
return s;
}
Dbl* v[8] = { new Dbl(0), ..};
Num* s = sum(v, 8) // Error
Num* v[7] = { new Dbl(0), ..};
Num* s1 = sum(v, 8); // OK
v[9] = new Int (5);
Num* s2 = sum(v, 8); // Bumm
→ Wir verlieren Typsicherheit
38. Objekt-orientierte Versuche: Polymorphie
Motivation
Traditionelle
Ansaetze
C-Stil generics
DS-Standardisierung
Macros
OO
Wiederverwendung
ist ein Problem!
generic idea
Liften
Generische
Programmierung
Fazit
Generische Programmierung 11 / 60
class Num { virtual Num& operator+=(Num&) = 0; };
class Dbl : Num { Num& operator+=(Num&); };
class Int : Num { Num& operator+=(Num&); };
Num* sum(Num** v, int n){
Num* s = v[0]->zero ();
for(int i=0; i<n; ++i)
*s += *v[i];
return s;
}
Dbl* v[8] = { new Dbl(0), ..};
Num* s = sum(v, 8) // Error
Num* v[7] = { new Dbl(0), ..};
Num* s1 = sum(v, 8); // OK
v[9] = new Int (5);
Num* s2 = sum(v, 8); // Bumm
→ Wir verlieren Typsicherheit
→ Vorgegebene Typ-Hierarchie: Eingebaute Typen haben verloren.
39. Wiederverwendung ist ein Problem!
Motivation
Traditionelle
Ansaetze
C-Stil generics
DS-Standardisierung
Macros
OO
Wiederverwendung
ist ein Problem!
generic idea
Liften
Generische
Programmierung
Fazit
Generische Programmierung 12 / 60
✖ Wiederverwendung von Algorithmen schwierig, keine
befriedigenden traditionellen Ans¨atze:
➔ Implementierungen sind ¨uberspezifiziert
➔ Typinformationen fehlen / m¨uhsam zu beschaffen
➔ Implementierungen oder Daten sind gekapselt
➔ Code wird repliziert
40. Wiederverwendung ist ein Problem!
Motivation
Traditionelle
Ansaetze
C-Stil generics
DS-Standardisierung
Macros
OO
Wiederverwendung
ist ein Problem!
generic idea
Liften
Generische
Programmierung
Fazit
Generische Programmierung 12 / 60
✖ Wiederverwendung von Algorithmen schwierig, keine
befriedigenden traditionellen Ans¨atze:
➔ Implementierungen sind ¨uberspezifiziert
➔ Typinformationen fehlen / m¨uhsam zu beschaffen
➔ Implementierungen oder Daten sind gekapselt
➔ Code wird repliziert
✖ sum ist ein ganz einfacher Fall . . .
➔ Komplexere Datenstrukturen
➔ Komplexere Algorithmen
➔ Komplexere Hardware
42. Idee der generischen Programmierung
Motivation
Traditionelle
Ansaetze
C-Stil generics
DS-Standardisierung
Macros
OO
Wiederverwendung
ist ein Problem!
generic idea
Liften
Generische
Programmierung
Fazit
Generische Programmierung 14 / 60
43. Idee der generischen Programmierung
Motivation
Traditionelle
Ansaetze
C-Stil generics
DS-Standardisierung
Macros
OO
Wiederverwendung
ist ein Problem!
generic idea
Liften
Generische
Programmierung
Fazit
Generische Programmierung 14 / 60
Algorithms are as insensitive to changes of data structure as
possible.
Alexander Stepanov
44. Idee der generischen Programmierung
Motivation
Traditionelle
Ansaetze
C-Stil generics
DS-Standardisierung
Macros
OO
Wiederverwendung
ist ein Problem!
generic idea
Liften
Generische
Programmierung
Fazit
Generische Programmierung 14 / 60
Algorithms are as insensitive to changes of data structure as
possible.
Alexander Stepanov
Ziel:
Mache Implementierungen so allgemein wie m¨oglich . . .
45. Idee der generischen Programmierung
Motivation
Traditionelle
Ansaetze
C-Stil generics
DS-Standardisierung
Macros
OO
Wiederverwendung
ist ein Problem!
generic idea
Liften
Generische
Programmierung
Fazit
Generische Programmierung 14 / 60
Algorithms are as insensitive to changes of data structure as
possible.
Alexander Stepanov
Ziel:
Mache Implementierungen so allgemein wie m¨oglich . . .
aber nicht allgemeiner.
46. Idee der generischen Programmierung
Motivation
Traditionelle
Ansaetze
C-Stil generics
DS-Standardisierung
Macros
OO
Wiederverwendung
ist ein Problem!
generic idea
Liften
Generische
Programmierung
Fazit
Generische Programmierung 14 / 60
Algorithms are as insensitive to changes of data structure as
possible.
Alexander Stepanov
Ziel:
Mache Implementierungen so allgemein wie m¨oglich . . .
aber nicht allgemeiner.
Enttarne & entferne (k¨unstliche) Einschr¨ankungen . . .
¨Ubersetze vielf¨altige Syntax der Daten in einheitliche Sprache
. . .
48. Was ist liften?
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 16 / 60
49. Was ist liften?
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 16 / 60
Lifting seeks to discover a generic algorithm by answering the
following fundamental question: What are the minimal
requirements that my data types need to fulfill for the
algorithm to operate correctly and efficiently?
Doug Gregor, generic-programming.org
50. Was ist liften?
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 16 / 60
Lifting seeks to discover a generic algorithm by answering the
following fundamental question: What are the minimal
requirements that my data types need to fulfill for the
algorithm to operate correctly and efficiently?
Doug Gregor, generic-programming.org
Most developers are not cut out to create these generic
components, but most can use them. The process for creating
them is a non-process. You fiddle, you scratch your head, [. . . ]
you rip your code up over and over (and over and over).
Marshall Cline, The C++ FAQ
51. Wie man eine Implementierung generisch macht
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 17 / 60
Die (impliziten) Annahmen von sum:
double sum(double *v, int n) {
double s = 0.0;
for(int i = 0; i < n; ++i) {
s += v[i];
}
return s;
}
✖ Typ ist double
✖ Daten stehen in array
✖ (ohne L¨ucken)
52. Wie man eine Implementierung generisch macht
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 17 / 60
Die (impliziten) Annahmen von sum:
double sum(double *v, int n) {
double s = 0.0;
for(int i = 0; i < n; ++i) {
s += v[i];
}
return s;
}
✖ Typ ist double
✖ Daten stehen in array
✖ (ohne L¨ucken)
53. Wie man eine Implementierung generisch macht
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 17 / 60
Die (impliziten) Annahmen von sum:
double sum(double *v, int n) {
double s = 0.0;
for(int i = 0; i < n; ++i) {
s += v[i];
}
return s;
}
✖ Typ ist double
✖ Daten stehen in array
✖ (ohne L¨ucken)
54. Wie man eine Implementierung generisch macht
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 17 / 60
Die (impliziten) Annahmen von sum:
double sum(double *v, int n) {
double s = 0.0;
for(int i = 0; i < n; ++i) {
s += v[i];
}
return s;
}
✖ Typ ist double
✖ Daten stehen in array
✖ (ohne L¨ucken)
55. Wie man eine Implementierung generisch macht
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 17 / 60
Die (impliziten) Annahmen von sum:
double sum(double *v, int n) {
double s = 0.0;
for(int i = 0; i < n; ++i) {
s += v[i];
}
return s;
}
✖ Typ ist double
✖ Daten stehen in array
✖ (ohne L¨ucken)
56. Generische Summe: Weg mit double
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 18 / 60
Weg mit der Typ-ist-double Einschr¨ankung:
double sum(double* v, int n) {
double s = 0.0;
for(int i = 0; i < n; ++i) {
s = s + v[i];
}
return s;
}
57. Generische Summe: Weg mit double
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 18 / 60
Weg mit der Typ-ist-double Einschr¨ankung:
double sum(double* v, int n) {
double s = 0.0;
for(int i = 0; i < n; ++i) {
s = s + v[i];
}
return s;
}
Das war einfach. Vielleicht zu einfach . . . ?
58. Generische Summe: Weg mit double
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 18 / 60
Weg mit der Typ-ist-double Einschr¨ankung:
template<class T>
T sum(T* v, int n) {
T s = 0;
for(int i = 0; i < n; ++i) {
s = s + v[i];
}
return s;
}
Das war einfach. Vielleicht zu einfach . . . ?
59. Generische Summe: Weg mit arrays ...
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 19 / 60
Weg mit der Array-Einschr¨ankung . . .
template <class T>
T sum(T* v, int n) {
T s = 0;
for(int i = 0; i < n; ++i) {
s = s + v[i];
}
return s;
}
60. Generische Summe: Weg mit arrays ...
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 19 / 60
Weg mit der Array-Einschr¨ankung . . .
template <class T>
T sum(T* v, int n) {
T s = 0;
for(int i = 0; i < n; ++i) {
s = s + v[i];
}
return s;
}
61. Generische Summe: Weg mit arrays ...
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 19 / 60
Weg mit der Array-Einschr¨ankung . . .
template <class T>
T sum(T* v, int n) {
T s = 0;
for(int i = 0; i < n; ++i) {
s = s + *v;
++v;
}
return s;
}
62. Generische Summe: Weg mit arrays ...
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 19 / 60
Weg mit der Array-Einschr¨ankung . . .
template <class T>
T sum(T* v, int n) {
T s = 0;
for(int i = 0; i < n; ++i) {
s = s + *v;
++v;
}
return s;
}
63. Generische Summe: Weg mit arrays ...
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 19 / 60
Weg mit der Array-Einschr¨ankung . . .
template <class T>
T sum(T* v, T* end) { // end == v + n
T s = 0;
while(v != end) {
s = s + *v;
++v;
}
return s;
}
64. Generische Summe: Weg mit arrays ...
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 20 / 60
Weg mit der array-Einschr¨ankung . . .
template <class T>
T sum(T* v, T* end) {
T s = 0;
while (v != end) {
s = s + *v;
++v;
}
return s;
}
Was muss das Argument v k¨onnen?
65. Generische Summe: Weg mit arrays ...
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 20 / 60
Weg mit der array-Einschr¨ankung . . .
template <class T>
T sum(T* v, T* end) {
T s = 0;
while (v != end) {
s = s + *v;
++v;
}
return s;
}
Was muss das Argument v k¨onnen?
✖ Vergleich, v != end
66. Generische Summe: Weg mit arrays ...
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 20 / 60
Weg mit der array-Einschr¨ankung . . .
template <class T>
T sum(T* v, T* end) {
T s = 0;
while (v != end) {
s = s + *v;
++v;
}
return s;
}
Was muss das Argument v k¨onnen?
✖ Vergleich, v != end
✖ Dereferenz, *v (nur lesend)
67. Generische Summe: Weg mit arrays ...
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 20 / 60
Weg mit der array-Einschr¨ankung . . .
template <class T>
T sum(T* v, T* end) {
T s = 0;
while (v != end) {
s = s + *v;
++v;
}
return s;
}
Was muss das Argument v k¨onnen?
✖ Vergleich, v != end
✖ Dereferenz, *v (nur lesend)
✖ Inkrement, ++v (Pr¨afix-Variante)
68. Generische Summe: Weg mit arrays ...
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 20 / 60
Weg mit der array-Einschr¨ankung . . .
template <class T>
T sum(T* v, T* end) {
T s = 0;
while (v != end) {
s = s + *v;
++v;
}
return s;
}
Was muss das Argument v k¨onnen?
✖ Vergleich, v != end
✖ Dereferenz, *v (nur lesend)
✖ Inkrement, ++v (Pr¨afix-Variante)
69. Concept: Iterator
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 21 / 60
Neue Abstraktion: Iterator (verallgemeinert Array-Zeiger)
70. Concept: Iterator
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 21 / 60
Neue Abstraktion: Iterator (verallgemeinert Array-Zeiger)
concept Iterator { // kein C++
Iterator & operator ++();
value_type operator *();
};
bool operator !=( Iterator const &, Iterator const &);
71. Concept: Iterator
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 21 / 60
Neue Abstraktion: Iterator (verallgemeinert Array-Zeiger)
concept Iterator { // kein C++
Iterator & operator ++();
value_type operator *();
};
bool operator !=( Iterator const &, Iterator const &);
Sehr geringe Anforderungen, kann breit unterst¨utzt werden!
72. Concept: Iterator
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 21 / 60
Neue Abstraktion: Iterator (verallgemeinert Array-Zeiger)
concept Iterator { // kein C++
Iterator & operator ++();
value_type operator *();
};
bool operator !=( Iterator const &, Iterator const &);
Sehr geringe Anforderungen, kann breit unterst¨utzt werden!
F¨ur Erbsenz¨ahler:
operator* wird nur 1x an jeder Position aufgerufen (single pass)
73. Iteratoren: Beispiel
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 22 / 60
Beispiel: Einfach verkettete Liste
74. Iteratoren: Beispiel
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 22 / 60
Beispiel: Einfach verkettete Liste
struct List { // rudimentaer
int data;
List* next; // == 0 am Listen -Ende
};
75. Iteratoren: Beispiel
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 22 / 60
Beispiel: Einfach verkettete Liste
struct List { // rudimentaer
int data;
List* next; // == 0 am Listen -Ende
};
struct ListIt { // implementiert Iterator -Concept
List* curr;
int operator*() const { return curr ->data; }
ListIt & operator++() {
curr = curr ->next; return *this; }
};
76. Iteratoren: Beispiel
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 22 / 60
Beispiel: Einfach verkettete Liste
struct List { // rudimentaer
int data;
List* next; // == 0 am Listen -Ende
};
struct ListIt { // implementiert Iterator -Concept
List* curr;
int operator*() const { return curr ->data; }
ListIt & operator++() {
curr = curr ->next; return *this; }
};
inline bool operator!=( ListIt const & a, ListIt const & b)
{ return a.curr != b.curr; }
77. Iteratoren: Beispiel
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 22 / 60
Beispiel: Einfach verkettete Liste
struct List { // rudimentaer
int data;
List* next; // == 0 am Listen -Ende
};
struct ListIt { // implementiert Iterator -Concept
List* curr;
int operator*() const { return curr ->data; }
ListIt & operator++() {
curr = curr ->next; return *this; }
};
inline bool operator!=( ListIt const & a, ListIt const & b)
{ return a.curr != b.curr; }
ListIt erlaubt nur Lese-Zugriffe
78. Generische Summe: Weg mit arrays ...
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 23 / 60
Weg mit der Array-Einschr¨ankung . . .
template <class T >
T sum(T* v, T* end) {
T s = 0;
while (v != end) {
s += *v;
v++;
}
return s;
}
79. Generische Summe: Weg mit arrays ...
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 23 / 60
Weg mit der Array-Einschr¨ankung . . .
template <class Iter>
??? sum(Iter v, Iter end) {
??? s = 0;
while (v != end) {
s += *v;
v++;
}
return s;
}
80. Generische Summe: Weg mit arrays ...
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 23 / 60
Weg mit der Array-Einschr¨ankung . . .
template <class Iter>
??? sum(Iter v, Iter end) {
??? s = 0;
while (v != end) {
s += *v;
v++;
}
return s;
}
Leider gibt es ein kleines Problem . . .
81. Den Werte-Typ zur¨uck bekommen: Variante 1
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 24 / 60
Versuch 1: Extra Parameter
82. Den Werte-Typ zur¨uck bekommen: Variante 1
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 24 / 60
Versuch 1: Extra Parameter
template <class Iter ,class T>
T
sum(Iter v, Iter end , T init) {
T s = init;
while (v != end) {
s = s + *v;
v++;
}
return s;
}
83. Den Werte-Typ zur¨uck bekommen: Variante 1
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 24 / 60
Versuch 1: Extra Parameter
template <class Iter ,class T>
T
sum(Iter v, Iter end , T init) {
T s = init;
while (v != end) {
s = s + *v;
v++;
}
return s;
}
+ Volle Kontrolle ¨uber Werte-Typ und Init-Wert
84. Den Werte-Typ zur¨uck bekommen: Variante 1
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 24 / 60
Versuch 1: Extra Parameter
template <class Iter ,class T>
T
sum(Iter v, Iter end , T init) {
T s = init;
while (v != end) {
s = s + *v;
v++;
}
return s;
}
+ Volle Kontrolle ¨uber Werte-Typ und Init-Wert
− zwingender Zusatz-Parameter
85. Den Werte-Typ zur¨uck bekommen: Variante 1
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 24 / 60
Versuch 1: Extra Parameter
template <class Iter ,class T>
T
sum(Iter v, Iter end , T init) {
T s = init;
while (v != end) {
s = s + *v;
v++;
}
return s;
}
+ Volle Kontrolle ¨uber Werte-Typ und Init-Wert
− zwingender Zusatz-Parameter
− Typ T im Ruf-Kontext bekannt?? (generisch!)
86. Den Werte-Typ zur¨uckbekommen: Variante 2
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 25 / 60
Versuch 2: T als typedef aus dem Iterator
87. Den Werte-Typ zur¨uckbekommen: Variante 2
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 25 / 60
Versuch 2: T als typedef aus dem Iterator
class ListIt { typedef int value_type ; ... };
88. Den Werte-Typ zur¨uckbekommen: Variante 2
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 25 / 60
Versuch 2: T als typedef aus dem Iterator
class ListIt { typedef int value_type ; ... };
template <class Iter >
typename Iter::value type
sum(Iter v, Iter end) {
typename Iter::value type s = 0;
while (v != end) {
s = s + *v;
v++;
}
return s;
}
89. Den Werte-Typ zur¨uckbekommen: Variante 2
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 25 / 60
Versuch 2: T als typedef aus dem Iterator
class ListIt { typedef int value_type ; ... };
template <class Iter >
typename Iter::value type
sum(Iter v, Iter end) {
typename Iter::value type s = 0;
while (v != end) {
s = s + *v;
v++;
}
return s;
}
− Muss bestehende Klassen ¨andern
90. Den Werte-Typ zur¨uckbekommen: Variante 2
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 25 / 60
Versuch 2: T als typedef aus dem Iterator
class ListIt { typedef int value_type ; ... };
template <class Iter >
typename Iter::value type
sum(Iter v, Iter end) {
typename Iter::value type s = 0;
while (v != end) {
s = s + *v;
v++;
}
return s;
}
− Muss bestehende Klassen ¨andern
− Funktioniert nicht f¨ur Iter = T*
91. Den Werte-Typ zur¨uckbekommen: Variante 2
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 25 / 60
Versuch 2: T als typedef aus dem Iterator
class ListIt { typedef int value_type ; ... };
template <class Iter >
typename Iter::value type
sum(Iter v, Iter end) {
typename Iter::value type s = 0;
while (v != end) {
s = s + *v;
v++;
}
return s;
}
− Muss bestehende Klassen ¨andern
− Funktioniert nicht f¨ur Iter = T*
Brauche nicht-intrusive Abbildung Iter → value type
92. Den Werte-Typ zur¨uckbekommen: Variante 3
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 26 / 60
Versuch 3: Abbildung value : IteratorTyp → WerteTyp
93. Den Werte-Typ zur¨uckbekommen: Variante 3
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 26 / 60
Versuch 3: Abbildung value : IteratorTyp → WerteTyp
Allgemeiner Fall: I → I::value type
94. Den Werte-Typ zur¨uckbekommen: Variante 3
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 26 / 60
Versuch 3: Abbildung value : IteratorTyp → WerteTyp
Allgemeiner Fall: I → I::value type
template <class I> struct value
{ typedef typename I:: value_type value_type ; };
95. Den Werte-Typ zur¨uckbekommen: Variante 3
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 26 / 60
Versuch 3: Abbildung value : IteratorTyp → WerteTyp
Allgemeiner Fall: I → I::value type
template <class I> struct value
{ typedef typename I:: value_type value_type ; };
F¨ur Zeiger: T* → T
96. Den Werte-Typ zur¨uckbekommen: Variante 3
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 26 / 60
Versuch 3: Abbildung value : IteratorTyp → WerteTyp
Allgemeiner Fall: I → I::value type
template <class I> struct value
{ typedef typename I:: value_type value_type ; };
F¨ur Zeiger: T* → T
template <class T> struct value <T*> {typedef T type ;};
97. Den Werte-Typ zur¨uckbekommen: Variante 3
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 26 / 60
Versuch 3: Abbildung value : IteratorTyp → WerteTyp
Allgemeiner Fall: I → I::value type
template <class I> struct value
{ typedef typename I:: value_type value_type ; };
F¨ur Zeiger: T* → T
template <class T> struct value <T*> {typedef T type ;};
Unser Iterator: ListIt → int
98. Den Werte-Typ zur¨uckbekommen: Variante 3
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 26 / 60
Versuch 3: Abbildung value : IteratorTyp → WerteTyp
Allgemeiner Fall: I → I::value type
template <class I> struct value
{ typedef typename I:: value_type value_type ; };
F¨ur Zeiger: T* → T
template <class T> struct value <T*> {typedef T type ;};
Unser Iterator: ListIt → int
template <> struct value <ListIt > {typedef int type ;};
99. Den Werte-Typ zur¨uckbekommen: Variante 3
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 26 / 60
Versuch 3: Abbildung value : IteratorTyp → WerteTyp
Allgemeiner Fall: I → I::value type
template <class I> struct value
{ typedef typename I:: value_type value_type ; };
F¨ur Zeiger: T* → T
template <class T> struct value <T*> {typedef T type ;};
Unser Iterator: ListIt → int
template <> struct value <ListIt > {typedef int type ;};
In C++11 ist das etwas einfacher:
100. Den Werte-Typ zur¨uckbekommen: Variante 3
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 26 / 60
Versuch 3: Abbildung value : IteratorTyp → WerteTyp
Allgemeiner Fall: I → I::value type
template <class I> struct value
{ typedef typename I:: value_type value_type ; };
F¨ur Zeiger: T* → T
template <class T> struct value <T*> {typedef T type ;};
Unser Iterator: ListIt → int
template <> struct value <ListIt > {typedef int type ;};
In C++11 ist das etwas einfacher:
template <class I> struct value // C++11
{ typedef decltype (I(). operator *()) type; }
(Die Bed. dass I einen Default-Konstruktor hat, kann man loswerden. Einen Ref-Qualifier muss man ggf.
beseitigen.)
101. Den Wertetyp zur¨uckbekommen
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 27 / 60
Versuch 3: Typ-Abbildung im Einsatz
102. Den Wertetyp zur¨uckbekommen
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 27 / 60
Versuch 3: Typ-Abbildung im Einsatz
template <class Iter >
typename value<Iter>::type
sum(Iter v, Iter end) {
typename value<Iter>::type s = 0;
while (v != end) {
s = s + *v;
v++;
}
return s;
}
103. Den Wertetyp zur¨uckbekommen
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 27 / 60
Versuch 3: Typ-Abbildung im Einsatz
template <class Iter >
typename value<Iter>::type
sum(Iter v, Iter end) {
typename value<Iter>::type s = 0;
while (v != end) {
s = s + *v;
v++;
}
return s;
}
(In der Standard-Library liefert iterator traits die
Funktionalit¨at von value).
104. Auf zum Summieren ...
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 28 / 60
vector <int > v(10, 42);
assert (sum(v.begin (), v.end ()) == 420);
105. Auf zum Summieren ...
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 28 / 60
vector <int > v(10, 42);
assert (sum(v.begin (), v.end ()) == 420);
List L; // ... fill L ...
// Annahme List :: begin (), end () implementiert
int sl = sum(L.begin (), L.end ());
106. Auf zum Summieren ...
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 28 / 60
vector <int > v(10, 42);
assert (sum(v.begin (), v.end ()) == 420);
List L; // ... fill L ...
// Annahme List :: begin (), end () implementiert
int sl = sum(L.begin (), L.end ());
cout << "type numbers :n"
double s = sum(istream_iterator <double >( cin),
istream_iterator <double >());
cout << "sum of numbers : " << s << endl;
107. Auf zum Summieren ...
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 28 / 60
vector <int > v(10, 42);
assert (sum(v.begin (), v.end ()) == 420);
List L; // ... fill L ...
// Annahme List :: begin (), end () implementiert
int sl = sum(L.begin (), L.end ());
cout << "type numbers :n"
double s = sum(istream_iterator <double >( cin),
istream_iterator <double >());
cout << "sum of numbers : " << s << endl;
vector <string > words ; // fill words ...
string all = sum(words .begin (), words .end ()); // Ups
Was passiert?
108. Richtiges neutrales Element?
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 29 / 60
template <class Iter >
typename value <Iter >:: type
sum(Iter v, Iter end) {
typename value <Iter >:: type s = 0;
while (v != end) {
s = s + *v;
v++;
}
return s;
}
109. Richtiges neutrales Element?
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 29 / 60
template <class Iter >
typename value <Iter >:: type
sum(Iter v, Iter end) {
typename value <Iter >:: type s = 0;
while (v != end) {
s = s + *v;
v++;
}
return s;
}
Der richtige Anfangswert f¨ur strings ist der leere string.
110. Richtiges neutrales Element?
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 29 / 60
template <class Iter >
typename value <Iter >:: type
sum(Iter v, Iter end) {
typename value <Iter >:: type s = 0;
while (v != end) {
s = s + *v;
v++;
}
return s;
}
Der richtige Anfangswert f¨ur strings ist der leere string.
Brauche neutrales Element zu (T, +)
111. Das richtige neutrale Element finden
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 30 / 60
Wieder gibt es mehrere M¨oglichkeiten:
112. Das richtige neutrale Element finden
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 30 / 60
Wieder gibt es mehrere M¨oglichkeiten:
1. Einfach das erste Element des Inputs nehmen
113. Das richtige neutrale Element finden
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 30 / 60
Wieder gibt es mehrere M¨oglichkeiten:
1. Einfach das erste Element des Inputs nehmen
2. zus¨atzliches init-Argument
114. Das richtige neutrale Element finden
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 30 / 60
Wieder gibt es mehrere M¨oglichkeiten:
1. Einfach das erste Element des Inputs nehmen
2. zus¨atzliches init-Argument
3. Typ-Abbildung analog zu value
115. Variante 1: Initialisierung mit erstem Element
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 31 / 60
template <class Iter >
typename value <Iter >:: type
sum(Iter v, Iter end) {
typename value <Iter >:: type s = *v; ++v;
while (v != end) {
s = s + *v;
v++;
}
return s;
}
116. Variante 1: Initialisierung mit erstem Element
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 31 / 60
template <class Iter >
typename value <Iter >:: type
sum(Iter v, Iter end) {
assert(v != end);
typename value <Iter >:: type s = *v; ++v;
while (v != end) {
s = s + *v;
v++;
}
return s;
}
Nachteil: Kann keine leeren Sequenzen verarbeiten.
117. Variante 2: Neutrales Element explizit ¨ubergeben
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 32 / 60
template <class Iter ,class T>
T
sum(Iter v, Iter end , T init) {
T s = init;
while (v != end) {
s = s + *v;
v++;
}
return s;
}
118. Variante 2: Neutrales Element explizit ¨ubergeben
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 32 / 60
template <class Iter ,class T>
T
sum(Iter v, Iter end , T init) {
T s = init;
while (v != end) {
s = s + *v;
v++;
}
return s;
}
+ Volle Kontrolle ¨uber Werte-Typ und Init-Wert
119. Neutrales Element explizit ¨ubergeben: Beispiele
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 33 / 60
vector <string > w; // ... fuelle w ...
string text = sum(w.begin (), w.end(), string ());
120. Neutrales Element explizit ¨ubergeben: Beispiele
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 33 / 60
vector <string > w; // ... fuelle w ...
string text = sum(w.begin (), w.end(), string ());
float a[] = {0.5, 1.0, 1.5 };
float s = sum(a, a+3, 0); // hmm ...
121. Neutrales Element explizit ¨ubergeben: Beispiele
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 33 / 60
vector <string > w; // ... fuelle w ...
string text = sum(w.begin (), w.end(), string ());
float a[] = {0.5, 1.0, 1.5 };
float s = sum(a, a+3, 0); // hmm ...
Die init-Variante ist hochgef¨ahrlich!
122. Neutrales Element explizit ¨ubergeben: Beispiele
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 33 / 60
vector <string > w; // ... fuelle w ...
string text = sum(w.begin (), w.end(), string ());
float a[] = {0.5, 1.0, 1.5 };
float s = sum(a, a+3, 0); // hmm ...
Die init-Variante ist hochgef¨ahrlich!
vector <unsigned char > w = wuerfel_werfen (N);
123. Neutrales Element explizit ¨ubergeben: Beispiele
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 33 / 60
vector <string > w; // ... fuelle w ...
string text = sum(w.begin (), w.end(), string ());
float a[] = {0.5, 1.0, 1.5 };
float s = sum(a, a+3, 0); // hmm ...
Die init-Variante ist hochgef¨ahrlich!
vector <unsigned char > w = wuerfel_werfen (N);
unsigned s1 = sum(w.begin (),w.end ()); // ohne init
124. Neutrales Element explizit ¨ubergeben: Beispiele
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 33 / 60
vector <string > w; // ... fuelle w ...
string text = sum(w.begin (), w.end(), string ());
float a[] = {0.5, 1.0, 1.5 };
float s = sum(a, a+3, 0); // hmm ...
Die init-Variante ist hochgef¨ahrlich!
vector <unsigned char > w = wuerfel_werfen (N);
unsigned s1 = sum(w.begin (),w.end ()); // ohne init
unsigned s2 = sum(w.begin (),w.end () ,0); // mit init
125. Neutrales Element explizit ¨ubergeben: Beispiele
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 33 / 60
vector <string > w; // ... fuelle w ...
string text = sum(w.begin (), w.end(), string ());
float a[] = {0.5, 1.0, 1.5 };
float s = sum(a, a+3, 0); // hmm ...
Die init-Variante ist hochgef¨ahrlich!
vector <unsigned char > w = wuerfel_werfen (N);
unsigned s1 = sum(w.begin (),w.end ()); // ohne init
unsigned s2 = sum(w.begin (),w.end () ,0); // mit init
... hat aber auch ihr Gutes!
126. Variante 3: Neutrales Element mit Typemap
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 34 / 60
neutral elem sum: ValueType → neutrales Element
127. Variante 3: Neutrales Element mit Typemap
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 34 / 60
neutral elem sum: ValueType → neutrales Element
template <class T> struct neutral_elem_sum
{ static T value () { return T(0);} };
128. Variante 3: Neutrales Element mit Typemap
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 34 / 60
neutral elem sum: ValueType → neutrales Element
template <class T> struct neutral_elem_sum
{ static T value () { return T(0);} };
template <> struct neutral_elem_sum <std :: string >
{ static std :: string value ()
{ return std :: string (); } };
129. Variante 3: Neutrales Element mit Typemap
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 34 / 60
neutral elem sum: ValueType → neutrales Element
template <class T> struct neutral_elem_sum
{ static T value () { return T(0);} };
template <> struct neutral_elem_sum <std :: string >
{ static std :: string value ()
{ return std :: string (); } };
template <> struct neutral_elem_sum <vec3 >
{ static vec3 zero () { return vec3 (0 ,0 ,0);} };
130. Variante 3: Neutrales Element mit Typemap
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 34 / 60
neutral elem sum: ValueType → neutrales Element
template <class T> struct neutral_elem_sum
{ static T value () { return T(0);} };
template <> struct neutral_elem_sum <std :: string >
{ static std :: string value ()
{ return std :: string (); } };
template <> struct neutral_elem_sum <vec3 >
{ static vec3 zero () { return vec3 (0 ,0 ,0);} };
template <class T> struct neutral_elem_sum <matrix <T> >
{ static matrix <T> zero ()
{ return matrix <T>(n=???, m=??? ,0); } };
131. Das richtige neutrale Element finden: Fazit
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 35 / 60
Welcher Ansatz ist jetzt am besten?
Pro Con
init mehr Kontrolle Bricht Interface
init nicht immer bekannt
Allgemeiner Gef¨ahrlich
1. Element OK alle Typen Bed.: Seq. = ∅
Type-Map OK alle Seq. Bed.: Typ hat neutrales E.
132. Das richtige neutrale Element finden: Fazit
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 35 / 60
Welcher Ansatz ist jetzt am besten?
Pro Con
init mehr Kontrolle Bricht Interface
init nicht immer bekannt
Allgemeiner Gef¨ahrlich
1. Element OK alle Typen Bed.: Seq. = ∅
Type-Map OK alle Seq. Bed.: Typ hat neutrales E.
✖ init Variante: allgemeine Basis-Version
133. Das richtige neutrale Element finden: Fazit
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 35 / 60
Welcher Ansatz ist jetzt am besten?
Pro Con
init mehr Kontrolle Bricht Interface
init nicht immer bekannt
Allgemeiner Gef¨ahrlich
1. Element OK alle Typen Bed.: Seq. = ∅
Type-Map OK alle Seq. Bed.: Typ hat neutrales E.
✖ init Variante: allgemeine Basis-Version
✖ Type-Map Variante als Convenience
134. Das richtige neutrale Element finden: Fazit
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 35 / 60
Welcher Ansatz ist jetzt am besten?
Pro Con
init mehr Kontrolle Bricht Interface
init nicht immer bekannt
Allgemeiner Gef¨ahrlich
1. Element OK alle Typen Bed.: Seq. = ∅
Type-Map OK alle Seq. Bed.: Typ hat neutrales E.
✖ init Variante: allgemeine Basis-Version
✖ Type-Map Variante als Convenience
✖ 1. Element Variante bei Typ ohne neutrales Element
135. Ist die Summe jetzt generisch genug?
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 36 / 60
136. Ist die Summe jetzt generisch genug?
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 36 / 60
struct employee {
double salary ;
int id;
};
vector <employee > staff ;
// double salaries = sum(staff .begin (), staff .end ());
137. Ist die Summe jetzt generisch genug?
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 36 / 60
struct employee {
double salary ;
int id;
};
vector <employee > staff ;
// double salaries = sum(staff .begin (), staff .end ());
vector <string > words = { "Das", "ist", "ein", "Satz "};
string text = sum(words .begin (), words .end ());
// " DasisteinSatz "
138. Ist die Summe jetzt generisch genug?
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 36 / 60
struct employee {
double salary ;
int id;
};
vector <employee > staff ;
// double salaries = sum(staff .begin (), staff .end ());
vector <string > words = { "Das", "ist", "ein", "Satz "};
string text = sum(words .begin (), words .end ());
// " DasisteinSatz "
double max_salary = ??
139. Ist die Summe jetzt generisch genug?
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 36 / 60
struct employee {
double salary ;
int id;
};
vector <employee > staff ;
// double salaries = sum(staff .begin (), staff .end ());
vector <string > words = { "Das", "ist", "ein", "Satz "};
string text = sum(words .begin (), words .end ());
// " DasisteinSatz "
double max_salary = ??
Nein!
140. Die Summe wird noch generischer ...
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 37 / 60
template <class Iter , class T>
T sum(Iter v, Iter end , T init) {
T s = init;
while (v != end) {
s = s + *v;
v++;
}
return s;
}
141. Die Summe wird noch generischer ...
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 37 / 60
template <class Iter , class T>
T sum(Iter v, Iter end , T init) {
T s = init;
while (v != end) {
s = s + v->salary;
v++;
}
return s;
}
142. Die Summe wird noch generischer ...
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 37 / 60
template <class Iter , class T>
T sum(Iter v, Iter end , T init) {
T s = init;
while (v != end) {
s = s + " " + *v;
v++;
}
return s;
}
143. Die Summe wird noch generischer ...
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 37 / 60
template <class Iter , class T>
T sum(Iter v, Iter end , T init) {
T s = init;
while (v != end) {
s = max(s,*v);
v++;
}
return s;
}
144. Die Summe wird noch generischer ...
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 37 / 60
template <class Iter , class T>
T sum(Iter v, Iter end , T init) {
T s = init;
while (v != end) {
s = ;
v++;
}
return s;
}
Alles von der Form s = op(s,*v).
145. Summe XXL: Reduce
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 38 / 60
template <class Iter , class T>
T sum(Iter v, Iter end , T init) {
T s = init;
while (v != end) {
s = s + *v;
v++;
}
return s;
}
146. Summe XXL: Reduce
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 38 / 60
template <class Iter , class T, class Op>
T reduce( Iter v, Iter end , T init, Op op) {
T s = init;
while (v != end) {
s = op(s,*v);
v++;
}
return s;
}
147. Was kann reduce?
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 39 / 60
vector <employee > staff ;
double salaries = reduce (staff .begin (), staff .end (),0.0,
[]( double s, employee e)
{return s + e.salary ;} );
148. Was kann reduce?
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 39 / 60
vector <employee > staff ;
double salaries = reduce (staff .begin (), staff .end (),0.0,
[]( double s, employee e)
{return s + e.salary ;} );
vector <string > w = { "Das", "ist", "ein", "Satz "};
string text = reduce (w.begin (), w.end(), string (),
[]( string s, string t)
{return s + " " + t;} );
// " Das ist ein Satz" -> beachte fuehrenden space
149. Was kann reduce?
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 39 / 60
vector <employee > staff ;
double salaries = reduce (staff .begin (), staff .end (),0.0,
[]( double s, employee e)
{return s + e.salary ;} );
vector <string > w = { "Das", "ist", "ein", "Satz "};
string text = reduce (w.begin (), w.end(), string (),
[]( string s, string t)
{return s + " " + t;} );
// " Das ist ein Satz" -> beachte fuehrenden space
double max_salary =
reduce (staff .begin (), staff .end(), ???,
[]( double s, employee e)
{return max(s, e.salary );} );
150. Was kann reduce?
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 39 / 60
vector <employee > staff ;
double salaries = reduce (staff .begin (), staff .end (),0.0,
[]( double s, employee e)
{return s + e.salary ;} );
vector <string > w = { "Das", "ist", "ein", "Satz "};
string text = reduce (w.begin (), w.end(), string (),
[]( string s, string t)
{return s + " " + t;} );
// " Das ist ein Satz" -> beachte fuehrenden space
double max_salary =
reduce (staff .begin (), staff .end(), ???,
[]( double s, employee e)
{return max(s, e.salary );} );
Das neutrale Element verfolgt uns!
151. Wieder ¨Arger mit init
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 40 / 60
Wie sieht das richtige init f¨ur das Maximum aus?
152. Wieder ¨Arger mit init
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 40 / 60
Wie sieht das richtige init f¨ur das Maximum aus?
F¨ur init muss gelten: max(x,init) == x (f¨ur alle x)
153. Wieder ¨Arger mit init
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 40 / 60
Wie sieht das richtige init f¨ur das Maximum aus?
F¨ur init muss gelten: max(x,init) == x (f¨ur alle x)
Also init <= x (f¨ur alle x)
154. Wieder ¨Arger mit init
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 40 / 60
Wie sieht das richtige init f¨ur das Maximum aus?
F¨ur init muss gelten: max(x,init) == x (f¨ur alle x)
Also init <= x (f¨ur alle x)
Wie kommen wir an diesen Wert init f¨ur beliebige Typen T?
155. Wieder ¨Arger mit init
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 40 / 60
Wie sieht das richtige init f¨ur das Maximum aus?
F¨ur init muss gelten: max(x,init) == x (f¨ur alle x)
Also init <= x (f¨ur alle x)
Wie kommen wir an diesen Wert init f¨ur beliebige Typen T?
Vielleicht hilft std::numeric limits?
156. Wieder ¨Arger mit init
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 40 / 60
Wie sieht das richtige init f¨ur das Maximum aus?
F¨ur init muss gelten: max(x,init) == x (f¨ur alle x)
Also init <= x (f¨ur alle x)
Wie kommen wir an diesen Wert init f¨ur beliebige Typen T?
Vielleicht hilft std::numeric limits?
template <class T> struct numeric_limits {
static T min ();
static T max ();
...
157. Wieder ¨Arger mit init
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 40 / 60
Wie sieht das richtige init f¨ur das Maximum aus?
F¨ur init muss gelten: max(x,init) == x (f¨ur alle x)
Also init <= x (f¨ur alle x)
Wie kommen wir an diesen Wert init f¨ur beliebige Typen T?
Vielleicht hilft std::numeric limits?
template <class T> struct numeric_limits {
static T min ();
static T max ();
...
Teilweise. numeric limits<T>::min() liefert
158. Wieder ¨Arger mit init
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 40 / 60
Wie sieht das richtige init f¨ur das Maximum aus?
F¨ur init muss gelten: max(x,init) == x (f¨ur alle x)
Also init <= x (f¨ur alle x)
Wie kommen wir an diesen Wert init f¨ur beliebige Typen T?
Vielleicht hilft std::numeric limits?
template <class T> struct numeric_limits {
static T min ();
static T max ();
...
Teilweise. numeric limits<T>::min() liefert
Wenn T ganzzahlig: Minimalen Wert
159. Wieder ¨Arger mit init
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 40 / 60
Wie sieht das richtige init f¨ur das Maximum aus?
F¨ur init muss gelten: max(x,init) == x (f¨ur alle x)
Also init <= x (f¨ur alle x)
Wie kommen wir an diesen Wert init f¨ur beliebige Typen T?
Vielleicht hilft std::numeric limits?
template <class T> struct numeric_limits {
static T min ();
static T max ();
...
Teilweise. numeric limits<T>::min() liefert
Wenn T ganzzahlig: Minimalen Wert
Wenn T Fliesskomma: Minimalen positiven Wert
160. Ein neutrales Element f¨urs Maximum ...
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 41 / 60
vector <int > vi; // ...
int maxi = reduce (vi.begin (), vi.end(),
std::numeric limits<int>::min(),
std :: max );
161. Ein neutrales Element f¨urs Maximum ...
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 41 / 60
vector <int > vi; // ...
int maxi = reduce (vi.begin (), vi.end(),
std::numeric limits<int>::min(),
std :: max );
vector <float > vf; // ...
float maxf = reduce (vf.begin (), vf.end(),
- std::numeric limits<float>::max(),
std :: max );
162. Ein neutrales Element f¨urs Maximum ...
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 41 / 60
vector <int > vi; // ...
int maxi = reduce (vi.begin (), vi.end(),
std::numeric limits<int>::min(),
std :: max );
vector <float > vf; // ...
float maxf = reduce (vf.begin (), vf.end(),
- std::numeric limits<float>::max(),
std :: max );
Das ist t¨odlich!
163. Ein neutrales Element f¨urs Maximum
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 42 / 60
Brauchen einheitliche Syntax: uniform limits
164. Ein neutrales Element f¨urs Maximum
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 42 / 60
Brauchen einheitliche Syntax: uniform limits
Typ T Wert v. uniform limits<T>::min()
integral std::numeric limits<T>::min()
Fliesskomma -std::numeric limits<T>::max()
sonstig undefiniert (Anwender)
165. Ein neutrales Element f¨urs Maximum
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 42 / 60
Brauchen einheitliche Syntax: uniform limits
Typ T Wert v. uniform limits<T>::min()
integral std::numeric limits<T>::min()
Fliesskomma -std::numeric limits<T>::max()
sonstig undefiniert (Anwender)
template <class T> // C++11 Abkuerzung
using nl = std :: numeric_limits <T>;
166. Ein neutrales Element f¨urs Maximum
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 42 / 60
Brauchen einheitliche Syntax: uniform limits
Typ T Wert v. uniform limits<T>::min()
integral std::numeric limits<T>::min()
Fliesskomma -std::numeric limits<T>::max()
sonstig undefiniert (Anwender)
template <class T> // C++11 Abkuerzung
using nl = std :: numeric_limits <T>;
Allgemeiner Fall
template <class T,
bool is_spec ,
bool is_int >
struct uniform_limits { };
167. Ein neutrales Element f¨urs Maximum
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 42 / 60
Brauchen einheitliche Syntax: uniform limits
Typ T Wert v. uniform limits<T>::min()
integral std::numeric limits<T>::min()
Fliesskomma -std::numeric limits<T>::max()
sonstig undefiniert (Anwender)
template <class T> // C++11 Abkuerzung
using nl = std :: numeric_limits <T>;
Allgemeiner Fall
template <class T,
bool is_spec = nl<T>::is specialized,
bool is_int = nl<T>::is integer>
struct uniform_limits { };
168. Ein neutrales Element f¨urs Maximum
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 43 / 60
template <class T,
bool is_spec = nl <T >:: is_specialized ,
bool is_int = nl <T >:: is_integer >
struct uniform_limits { };
169. Ein neutrales Element f¨urs Maximum
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 43 / 60
template <class T,
bool is_spec = nl <T >:: is_specialized ,
bool is_int = nl <T >:: is_integer >
struct uniform_limits { };
Version f¨ur integrale Typen
template <class T>
struct uniform_limits <T, true , true >
{ static T min () { return nl <T >:: min (); } };
170. Ein neutrales Element f¨urs Maximum
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 43 / 60
template <class T,
bool is_spec = nl <T >:: is_specialized ,
bool is_int = nl <T >:: is_integer >
struct uniform_limits { };
Version f¨ur integrale Typen
template <class T>
struct uniform_limits <T, true , true >
{ static T min () { return nl <T >:: min (); } };
Version f¨ur Fliesskomma-Zahlen
template <class T>
struct uniform_limits <T, true , false >
{ static T min () { return -nl <T>:: max (); } };
171. Los geht’s mit dem Maximum
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 44 / 60
vector <int > vi; // ...
int maxi = reduce (vi.begin (), vi.end(),
std::numeric limits<int>::min(),
std :: max );
172. Los geht’s mit dem Maximum
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 44 / 60
vector <int > vi; // ...
int maxi = reduce (vi.begin (), vi.end(),
uniform limits<int>::min(),
std :: max );
173. Los geht’s mit dem Maximum
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 44 / 60
vector <int > vi; // ...
int maxi = reduce (vi.begin (), vi.end(),
uniform limits<int>::min(),
std :: max );
vector <float > vf; // ...
float maxf = reduce (vf.begin (), vf.end(),
- std::numeric limits<float>::max(),
std :: max );
174. Los geht’s mit dem Maximum
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 44 / 60
vector <int > vi; // ...
int maxi = reduce (vi.begin (), vi.end(),
uniform limits<int>::min(),
std :: max );
vector <float > vf; // ...
float maxf = reduce (vf.begin (), vf.end(),
uniform limits<float>::min(),
std :: max );
175. Los geht’s mit dem Maximum
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 44 / 60
vector <int > vi; // ...
int maxi = reduce (vi.begin (), vi.end(),
uniform limits<int>::min(),
std :: max );
vector <float > vf; // ...
float maxf = reduce (vf.begin (), vf.end(),
uniform limits<float>::min(),
std :: max );
Besser. Aber umst¨andlich.
176. Los geht’s mit dem Maximum
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 44 / 60
vector <int > vi; // ...
int maxi = reduce (vi.begin (), vi.end(),
uniform limits<int>::min(),
std :: max );
vector <float > vf; // ...
float maxf = reduce (vf.begin (), vf.end(),
uniform limits<float>::min(),
std :: max );
Besser. Aber umst¨andlich.
Brauchen (Typ, Op) → neutrales Element . . .
177. Los geht’s mit dem Maximum
Motivation
Traditionelle
Ansaetze
Liften
Wie man eine
Implementierung
generisch macht
Weg mit double
Weg mit array
Generische Summe
Nutzung
Neutrales Element
Reduce
Reduce und
neutrales Element
Max: Neutrales
Element
Reduce wrapup
Fazit
Generische
Programmierung
Fazit
Generische Programmierung 44 / 60
vector <int > vi; // ...
int maxi = reduce (vi.begin (), vi.end(),
uniform limits<int>::min(),
std :: max );
vector <float > vf; // ...
float maxf = reduce (vf.begin (), vf.end(),
uniform limits<float>::min(),
std :: max );
Besser. Aber umst¨andlich.
Brauchen (Typ, Op) → neutrales Element . . .
. . . aber nicht mehr heute ;-)