SlideShare ist ein Scribd-Unternehmen logo
1 von 230
Generische Programmierung 1 / 60
Generische Programmierung
Guntram Berti
Consulting mathematische Methoden
Bonn
20. Februar 2013
Motivation: Wiederverwendung
algorithmischen Codes
Motivation
Wiederwendung
algorithmischen
Codes: Ein Problem?
Das Problem:
Inhalt
Traditionelle
Ansaetze
Liften
Generische
Programmierung
Fazit
Generische Programmierung 2 / 60
Wiederwendung algorithmischen Codes: Ein Problem?
Motivation
Wiederwendung
algorithmischen
Codes: Ein Problem?
Das Problem:
Inhalt
Traditionelle
Ansaetze
Liften
Generische
Programmierung
Fazit
Generische Programmierung 3 / 60
Klassische Implementierung (eines simplen Algorithmus):
double sum(double * v, int n) {
double s = 0;
for(int i = 0; i < n; ++i)
s += v[i];
return s;
}
. . . ist das (wieder)verwendbar?
Wiederwendung algorithmischen Codes: Ein Problem?
Motivation
Wiederwendung
algorithmischen
Codes: Ein Problem?
Das Problem:
Inhalt
Traditionelle
Ansaetze
Liften
Generische
Programmierung
Fazit
Generische Programmierung 3 / 60
Klassische Implementierung (eines simplen Algorithmus):
double sum(double * v, int n) {
double s = 0;
for(int i = 0; i < n; ++i)
s += v[i];
return s;
}
. . . ist das (wieder)verwendbar?
typedef double vec3 [3]; vec3 *v3 = ...;
→ sum tut’s nicht f¨ur v3: Falsches Zugriffs-Muster
Wiederwendung algorithmischen Codes: Ein Problem?
Motivation
Wiederwendung
algorithmischen
Codes: Ein Problem?
Das Problem:
Inhalt
Traditionelle
Ansaetze
Liften
Generische
Programmierung
Fazit
Generische Programmierung 3 / 60
Klassische Implementierung (eines simplen Algorithmus):
double sum(double * v, int n) {
double s = 0;
for(int i = 0; i < n; ++i)
s += v[i];
return s;
}
. . . ist das (wieder)verwendbar?
typedef double vec3 [3]; vec3 *v3 = ...;
→ sum tut’s nicht f¨ur v3: Falsches Zugriffs-Muster
int * vi;
→ sum tut’s nicht f¨ur die integers in vi: Falscher Werte-Typ
Das Problem:
Motivation
Wiederwendung
algorithmischen
Codes: Ein Problem?
Das Problem:
Inhalt
Traditionelle
Ansaetze
Liften
Generische
Programmierung
Fazit
Generische Programmierung 4 / 60
sum ist (grotesk)
¨uberspezifiziert!
Inhalt
Motivation
Wiederwendung
algorithmischen
Codes: Ein Problem?
Das Problem:
Inhalt
Traditionelle
Ansaetze
Liften
Generische
Programmierung
Fazit
Generische Programmierung 5 / 60
✖ Ein Problem: Wiederverwendung algorithmischen Codes
✖ Traditionelle Medizin
✖ Der generische Ansatz in der Praxis . . .
✖ . . . und in der Theorie
✖ Diskussion
Traditionelle Kuren
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
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 *));
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 *));
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
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)
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
DS-Standardisierung und Code-Replizierung
Motivation
Traditionelle
Ansaetze
C-Stil generics
DS-Standardisierung
Macros
OO
Wiederverwendung
ist ein Problem!
generic idea
Liften
Generische
Programmierung
Fazit
Generische Programmierung 8 / 60
Implementierung f¨ur feste Anzahl Standard-Datenstrukturen
DS-Standardisierung und Code-Replizierung
Motivation
Traditionelle
Ansaetze
C-Stil generics
DS-Standardisierung
Macros
OO
Wiederverwendung
ist ein Problem!
generic idea
Liften
Generische
Programmierung
Fazit
Generische Programmierung 8 / 60
Implementierung f¨ur feste Anzahl Standard-Datenstrukturen
z.B. LAPACK: numerische lineare Algebra,
Extra-Implementierungen f¨ur float, double, complex, und
verschiedene Matrixtypen: sgetrf(), dgbequ()
DS-Standardisierung und Code-Replizierung
Motivation
Traditionelle
Ansaetze
C-Stil generics
DS-Standardisierung
Macros
OO
Wiederverwendung
ist ein Problem!
generic idea
Liften
Generische
Programmierung
Fazit
Generische Programmierung 8 / 60
Implementierung f¨ur feste Anzahl Standard-Datenstrukturen
z.B. LAPACK: numerische lineare Algebra,
Extra-Implementierungen f¨ur float, double, complex, und
verschiedene Matrixtypen: sgetrf(), dgbequ()
Unser Beispiel:
double sum_dbl_array (...);
int sum_int_array (...);
float sum_flt_list (...);
...
DS-Standardisierung und Code-Replizierung
Motivation
Traditionelle
Ansaetze
C-Stil generics
DS-Standardisierung
Macros
OO
Wiederverwendung
ist ein Problem!
generic idea
Liften
Generische
Programmierung
Fazit
Generische Programmierung 8 / 60
Implementierung f¨ur feste Anzahl Standard-Datenstrukturen
z.B. LAPACK: numerische lineare Algebra,
Extra-Implementierungen f¨ur float, double, complex, und
verschiedene Matrixtypen: sgetrf(), dgbequ()
Unser Beispiel:
double sum_dbl_array (...);
int sum_int_array (...);
float sum_flt_list (...);
...
→ Duplizierung f¨ur jeden Anwendungsfall
DS-Standardisierung und Code-Replizierung
Motivation
Traditionelle
Ansaetze
C-Stil generics
DS-Standardisierung
Macros
OO
Wiederverwendung
ist ein Problem!
generic idea
Liften
Generische
Programmierung
Fazit
Generische Programmierung 8 / 60
Implementierung f¨ur feste Anzahl Standard-Datenstrukturen
z.B. LAPACK: numerische lineare Algebra,
Extra-Implementierungen f¨ur float, double, complex, und
verschiedene Matrixtypen: sgetrf(), dgbequ()
Unser Beispiel:
double sum_dbl_array (...);
int sum_int_array (...);
float sum_flt_list (...);
...
→ Duplizierung f¨ur jeden Anwendungsfall
→ in der Praxis oft inline mit cut & paste
DS-Standardisierung und Code-Replizierung
Motivation
Traditionelle
Ansaetze
C-Stil generics
DS-Standardisierung
Macros
OO
Wiederverwendung
ist ein Problem!
generic idea
Liften
Generische
Programmierung
Fazit
Generische Programmierung 8 / 60
Implementierung f¨ur feste Anzahl Standard-Datenstrukturen
z.B. LAPACK: numerische lineare Algebra,
Extra-Implementierungen f¨ur float, double, complex, und
verschiedene Matrixtypen: sgetrf(), dgbequ()
Unser Beispiel:
double sum_dbl_array (...);
int sum_int_array (...);
float sum_flt_list (...);
...
→ Duplizierung f¨ur jeden Anwendungsfall
→ in der Praxis oft inline mit cut & paste
→ Wartbarkeit ist ein Albtraum
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) )
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) ????
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 )
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
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
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
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();
};
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
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
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()
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; };
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&); };
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
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
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
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
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
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.
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
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
Motivation
Traditionelle
Ansaetze
C-Stil generics
DS-Standardisierung
Macros
OO
Wiederverwendung
ist ein Problem!
generic idea
Liften
Generische
Programmierung
Fazit
Generische Programmierung 13 / 60
K¨onnen wir das besser?
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
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
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 . . .
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.
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
. . .
Eine Implementierung “liften”
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
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
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
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)
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)
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)
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)
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)
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;
}
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 . . . ?
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 . . . ?
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;
}
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;
}
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;
}
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;
}
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;
}
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?
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
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)
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)
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)
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
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 &);
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!
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)
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
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
};
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; }
};
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; }
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
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;
}
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;
}
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 . . .
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
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;
}
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
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
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!)
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
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 ; ... };
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;
}
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
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*
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
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
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
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 ; };
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
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 ;};
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
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 ;};
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:
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.)
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
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;
}
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).
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);
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 ());
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;
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?
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;
}
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.
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, +)
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:
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
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
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
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;
}
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.
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;
}
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
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 ());
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 ...
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!
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);
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
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
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!
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
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);} };
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 (); } };
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);} };
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); } };
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.
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
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
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
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
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 ());
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 "
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 = ??
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!
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;
}
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;
}
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;
}
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;
}
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).
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;
}
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;
}
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 ;} );
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
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 );} );
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!
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?
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)
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)
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?
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?
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 ();
...
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
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
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
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 );
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 );
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!
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
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)
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>;
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 { };
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 { };
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 { };
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 (); } };
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 (); } };
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 );
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 );
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 );
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 );
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.
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 . . .
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 ;-)
Einführung in die Generische Programmierung mit C++
Einführung in die Generische Programmierung mit C++
Einführung in die Generische Programmierung mit C++
Einführung in die Generische Programmierung mit C++
Einführung in die Generische Programmierung mit C++
Einführung in die Generische Programmierung mit C++
Einführung in die Generische Programmierung mit C++
Einführung in die Generische Programmierung mit C++
Einführung in die Generische Programmierung mit C++
Einführung in die Generische Programmierung mit C++
Einführung in die Generische Programmierung mit C++
Einführung in die Generische Programmierung mit C++
Einführung in die Generische Programmierung mit C++
Einführung in die Generische Programmierung mit C++
Einführung in die Generische Programmierung mit C++
Einführung in die Generische Programmierung mit C++
Einführung in die Generische Programmierung mit C++
Einführung in die Generische Programmierung mit C++
Einführung in die Generische Programmierung mit C++
Einführung in die Generische Programmierung mit C++
Einführung in die Generische Programmierung mit C++
Einführung in die Generische Programmierung mit C++
Einführung in die Generische Programmierung mit C++
Einführung in die Generische Programmierung mit C++
Einführung in die Generische Programmierung mit C++
Einführung in die Generische Programmierung mit C++
Einführung in die Generische Programmierung mit C++
Einführung in die Generische Programmierung mit C++
Einführung in die Generische Programmierung mit C++
Einführung in die Generische Programmierung mit C++
Einführung in die Generische Programmierung mit C++
Einführung in die Generische Programmierung mit C++
Einführung in die Generische Programmierung mit C++
Einführung in die Generische Programmierung mit C++
Einführung in die Generische Programmierung mit C++
Einführung in die Generische Programmierung mit C++
Einführung in die Generische Programmierung mit C++
Einführung in die Generische Programmierung mit C++
Einführung in die Generische Programmierung mit C++
Einführung in die Generische Programmierung mit C++
Einführung in die Generische Programmierung mit C++
Einführung in die Generische Programmierung mit C++
Einführung in die Generische Programmierung mit C++
Einführung in die Generische Programmierung mit C++
Einführung in die Generische Programmierung mit C++
Einführung in die Generische Programmierung mit C++
Einführung in die Generische Programmierung mit C++
Einführung in die Generische Programmierung mit C++
Einführung in die Generische Programmierung mit C++
Einführung in die Generische Programmierung mit C++
Einführung in die Generische Programmierung mit C++
Einführung in die Generische Programmierung mit C++
Einführung in die Generische Programmierung mit C++

Weitere ähnliche Inhalte

Andere mochten auch

Sobrefesta. Una tertúlia de mitja tarda. Festcat'12
Sobrefesta. Una tertúlia de mitja tarda. Festcat'12Sobrefesta. Una tertúlia de mitja tarda. Festcat'12
Sobrefesta. Una tertúlia de mitja tarda. Festcat'12Cristina Riera Jaume
 
universidad tecnic de cotopaxi
universidad tecnic de cotopaxiuniversidad tecnic de cotopaxi
universidad tecnic de cotopaxiNelson Caguana
 
Hidrodinámica o dinámica de fluidos
Hidrodinámica o dinámica de fluidosHidrodinámica o dinámica de fluidos
Hidrodinámica o dinámica de fluidosLorena Sänchez
 
Blu-ray, DVD- und CD-Neuheiten Februar 2015 Nr. 2 (Im Vertrieb der NAXOS Deut...
Blu-ray, DVD- und CD-Neuheiten Februar 2015 Nr. 2 (Im Vertrieb der NAXOS Deut...Blu-ray, DVD- und CD-Neuheiten Februar 2015 Nr. 2 (Im Vertrieb der NAXOS Deut...
Blu-ray, DVD- und CD-Neuheiten Februar 2015 Nr. 2 (Im Vertrieb der NAXOS Deut...NAXOS Deutschland GmbH
 
Senador Jesús Ignacio García Valencia. Municipio La Sierra, Cauca
Senador Jesús Ignacio García Valencia. Municipio La Sierra, CaucaSenador Jesús Ignacio García Valencia. Municipio La Sierra, Cauca
Senador Jesús Ignacio García Valencia. Municipio La Sierra, CaucaAlfonso José Luna Geller
 
Buen uso del internet
Buen uso del internetBuen uso del internet
Buen uso del internetmariaka2012
 
inspirato Konferenz Zukunft Apotheke 2014 - Das Programm
inspirato Konferenz Zukunft Apotheke 2014 - Das Programminspirato Konferenz Zukunft Apotheke 2014 - Das Programm
inspirato Konferenz Zukunft Apotheke 2014 - Das ProgrammStefanie Kurz
 
Dynamische Kataloganreicherung auf Basis von Linked Open Data
Dynamische Kataloganreicherung auf Basis von Linked Open DataDynamische Kataloganreicherung auf Basis von Linked Open Data
Dynamische Kataloganreicherung auf Basis von Linked Open Datah_jansen
 
Was macht virale videos viral einflussfaktoren auf die diffusion
Was macht virale videos viral einflussfaktoren auf die diffusionWas macht virale videos viral einflussfaktoren auf die diffusion
Was macht virale videos viral einflussfaktoren auf die diffusionFrank D
 

Andere mochten auch (17)

Sobrefesta. Una tertúlia de mitja tarda. Festcat'12
Sobrefesta. Una tertúlia de mitja tarda. Festcat'12Sobrefesta. Una tertúlia de mitja tarda. Festcat'12
Sobrefesta. Una tertúlia de mitja tarda. Festcat'12
 
universidad tecnic de cotopaxi
universidad tecnic de cotopaxiuniversidad tecnic de cotopaxi
universidad tecnic de cotopaxi
 
Gestion Por Procesos
Gestion Por ProcesosGestion Por Procesos
Gestion Por Procesos
 
Hidrodinámica o dinámica de fluidos
Hidrodinámica o dinámica de fluidosHidrodinámica o dinámica de fluidos
Hidrodinámica o dinámica de fluidos
 
Blu-ray, DVD- und CD-Neuheiten Februar 2015 Nr. 2 (Im Vertrieb der NAXOS Deut...
Blu-ray, DVD- und CD-Neuheiten Februar 2015 Nr. 2 (Im Vertrieb der NAXOS Deut...Blu-ray, DVD- und CD-Neuheiten Februar 2015 Nr. 2 (Im Vertrieb der NAXOS Deut...
Blu-ray, DVD- und CD-Neuheiten Februar 2015 Nr. 2 (Im Vertrieb der NAXOS Deut...
 
Senador Jesús Ignacio García Valencia. Municipio La Sierra, Cauca
Senador Jesús Ignacio García Valencia. Municipio La Sierra, CaucaSenador Jesús Ignacio García Valencia. Municipio La Sierra, Cauca
Senador Jesús Ignacio García Valencia. Municipio La Sierra, Cauca
 
Rdd carreras
Rdd carrerasRdd carreras
Rdd carreras
 
Tp aulico picasa rocco
Tp aulico picasa roccoTp aulico picasa rocco
Tp aulico picasa rocco
 
Buen uso del internet
Buen uso del internetBuen uso del internet
Buen uso del internet
 
Alfredo
AlfredoAlfredo
Alfredo
 
inspirato Konferenz Zukunft Apotheke 2014 - Das Programm
inspirato Konferenz Zukunft Apotheke 2014 - Das Programminspirato Konferenz Zukunft Apotheke 2014 - Das Programm
inspirato Konferenz Zukunft Apotheke 2014 - Das Programm
 
Jurisdiccion 3
Jurisdiccion 3Jurisdiccion 3
Jurisdiccion 3
 
Dynamische Kataloganreicherung auf Basis von Linked Open Data
Dynamische Kataloganreicherung auf Basis von Linked Open DataDynamische Kataloganreicherung auf Basis von Linked Open Data
Dynamische Kataloganreicherung auf Basis von Linked Open Data
 
Was macht virale videos viral einflussfaktoren auf die diffusion
Was macht virale videos viral einflussfaktoren auf die diffusionWas macht virale videos viral einflussfaktoren auf die diffusion
Was macht virale videos viral einflussfaktoren auf die diffusion
 
NAXOS-Neuheiten im August 2014
NAXOS-Neuheiten im August 2014NAXOS-Neuheiten im August 2014
NAXOS-Neuheiten im August 2014
 
Machine Automation Outline
Machine Automation OutlineMachine Automation Outline
Machine Automation Outline
 
28. OpenNetwork Event 2013
28. OpenNetwork Event 201328. OpenNetwork Event 2013
28. OpenNetwork Event 2013
 

Einführung in die Generische Programmierung mit C++

  • 1. Generische Programmierung 1 / 60 Generische Programmierung Guntram Berti Consulting mathematische Methoden Bonn 20. Februar 2013
  • 2. Motivation: Wiederverwendung algorithmischen Codes Motivation Wiederwendung algorithmischen Codes: Ein Problem? Das Problem: Inhalt Traditionelle Ansaetze Liften Generische Programmierung Fazit Generische Programmierung 2 / 60
  • 3. Wiederwendung algorithmischen Codes: Ein Problem? Motivation Wiederwendung algorithmischen Codes: Ein Problem? Das Problem: Inhalt Traditionelle Ansaetze Liften Generische Programmierung Fazit Generische Programmierung 3 / 60 Klassische Implementierung (eines simplen Algorithmus): double sum(double * v, int n) { double s = 0; for(int i = 0; i < n; ++i) s += v[i]; return s; } . . . ist das (wieder)verwendbar?
  • 4. Wiederwendung algorithmischen Codes: Ein Problem? Motivation Wiederwendung algorithmischen Codes: Ein Problem? Das Problem: Inhalt Traditionelle Ansaetze Liften Generische Programmierung Fazit Generische Programmierung 3 / 60 Klassische Implementierung (eines simplen Algorithmus): double sum(double * v, int n) { double s = 0; for(int i = 0; i < n; ++i) s += v[i]; return s; } . . . ist das (wieder)verwendbar? typedef double vec3 [3]; vec3 *v3 = ...; → sum tut’s nicht f¨ur v3: Falsches Zugriffs-Muster
  • 5. Wiederwendung algorithmischen Codes: Ein Problem? Motivation Wiederwendung algorithmischen Codes: Ein Problem? Das Problem: Inhalt Traditionelle Ansaetze Liften Generische Programmierung Fazit Generische Programmierung 3 / 60 Klassische Implementierung (eines simplen Algorithmus): double sum(double * v, int n) { double s = 0; for(int i = 0; i < n; ++i) s += v[i]; return s; } . . . ist das (wieder)verwendbar? typedef double vec3 [3]; vec3 *v3 = ...; → sum tut’s nicht f¨ur v3: Falsches Zugriffs-Muster int * vi; → sum tut’s nicht f¨ur die integers in vi: Falscher Werte-Typ
  • 6. Das Problem: Motivation Wiederwendung algorithmischen Codes: Ein Problem? Das Problem: Inhalt Traditionelle Ansaetze Liften Generische Programmierung Fazit Generische Programmierung 4 / 60 sum ist (grotesk) ¨uberspezifiziert!
  • 7. Inhalt Motivation Wiederwendung algorithmischen Codes: Ein Problem? Das Problem: Inhalt Traditionelle Ansaetze Liften Generische Programmierung Fazit Generische Programmierung 5 / 60 ✖ Ein Problem: Wiederverwendung algorithmischen Codes ✖ Traditionelle Medizin ✖ Der generische Ansatz in der Praxis . . . ✖ . . . und in der Theorie ✖ Diskussion
  • 9. 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
  • 10. 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 *));
  • 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
  • 15. DS-Standardisierung und Code-Replizierung Motivation Traditionelle Ansaetze C-Stil generics DS-Standardisierung Macros OO Wiederverwendung ist ein Problem! generic idea Liften Generische Programmierung Fazit Generische Programmierung 8 / 60 Implementierung f¨ur feste Anzahl Standard-Datenstrukturen
  • 16. DS-Standardisierung und Code-Replizierung Motivation Traditionelle Ansaetze C-Stil generics DS-Standardisierung Macros OO Wiederverwendung ist ein Problem! generic idea Liften Generische Programmierung Fazit Generische Programmierung 8 / 60 Implementierung f¨ur feste Anzahl Standard-Datenstrukturen z.B. LAPACK: numerische lineare Algebra, Extra-Implementierungen f¨ur float, double, complex, und verschiedene Matrixtypen: sgetrf(), dgbequ()
  • 17. DS-Standardisierung und Code-Replizierung Motivation Traditionelle Ansaetze C-Stil generics DS-Standardisierung Macros OO Wiederverwendung ist ein Problem! generic idea Liften Generische Programmierung Fazit Generische Programmierung 8 / 60 Implementierung f¨ur feste Anzahl Standard-Datenstrukturen z.B. LAPACK: numerische lineare Algebra, Extra-Implementierungen f¨ur float, double, complex, und verschiedene Matrixtypen: sgetrf(), dgbequ() Unser Beispiel: double sum_dbl_array (...); int sum_int_array (...); float sum_flt_list (...); ...
  • 18. DS-Standardisierung und Code-Replizierung Motivation Traditionelle Ansaetze C-Stil generics DS-Standardisierung Macros OO Wiederverwendung ist ein Problem! generic idea Liften Generische Programmierung Fazit Generische Programmierung 8 / 60 Implementierung f¨ur feste Anzahl Standard-Datenstrukturen z.B. LAPACK: numerische lineare Algebra, Extra-Implementierungen f¨ur float, double, complex, und verschiedene Matrixtypen: sgetrf(), dgbequ() Unser Beispiel: double sum_dbl_array (...); int sum_int_array (...); float sum_flt_list (...); ... → Duplizierung f¨ur jeden Anwendungsfall
  • 19. DS-Standardisierung und Code-Replizierung Motivation Traditionelle Ansaetze C-Stil generics DS-Standardisierung Macros OO Wiederverwendung ist ein Problem! generic idea Liften Generische Programmierung Fazit Generische Programmierung 8 / 60 Implementierung f¨ur feste Anzahl Standard-Datenstrukturen z.B. LAPACK: numerische lineare Algebra, Extra-Implementierungen f¨ur float, double, complex, und verschiedene Matrixtypen: sgetrf(), dgbequ() Unser Beispiel: double sum_dbl_array (...); int sum_int_array (...); float sum_flt_list (...); ... → Duplizierung f¨ur jeden Anwendungsfall → in der Praxis oft inline mit cut & paste
  • 20. DS-Standardisierung und Code-Replizierung Motivation Traditionelle Ansaetze C-Stil generics DS-Standardisierung Macros OO Wiederverwendung ist ein Problem! generic idea Liften Generische Programmierung Fazit Generische Programmierung 8 / 60 Implementierung f¨ur feste Anzahl Standard-Datenstrukturen z.B. LAPACK: numerische lineare Algebra, Extra-Implementierungen f¨ur float, double, complex, und verschiedene Matrixtypen: sgetrf(), dgbequ() Unser Beispiel: double sum_dbl_array (...); int sum_int_array (...); float sum_flt_list (...); ... → Duplizierung f¨ur jeden Anwendungsfall → in der Praxis oft inline mit cut & paste → Wartbarkeit ist ein Albtraum
  • 21. 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) )
  • 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()
  • 31. 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; };
  • 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
  • 41. Motivation Traditionelle Ansaetze C-Stil generics DS-Standardisierung Macros OO Wiederverwendung ist ein Problem! generic idea Liften Generische Programmierung Fazit Generische Programmierung 13 / 60 K¨onnen wir das besser?
  • 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 ;-)