DIGITAL
.h
) implementiert werden. Dies liegt daran, dass Templates erst übersetzt werden, wenn man sie "instanziiert", also konkrete Werte für die Template-Argumente einsetzt. Ein typischer Nachteil davon ist, dass in großen Projekten mit vielen Templates die Compilezeit und Dateigröße der kompilierten Dateien zunimmt, da jede Datei, die ein Template instanziiert, eine Kopie des kompilierten Template-Codes enhält.
Auf Blatt 3 haben wir gesehen, wie man struct
s zur sinnvollen Gruppierung von Daten einsetzen kann. Braucht man viele solcher Gruppierungen, kann die Anzahl an struct
s schnell dazu führen, dass man die Übersicht verliert. Wir wollen jetzt mithilfe von Templates eine Alternative zu struct
s implementieren und deren Tradeoffs diskutieren. Als Basis verwenden wir folgende Deklaration:
template <typename F, typename S>
struct pair {
F first;
S second;
void swap(pair<F, S>& other) {
// ...
}
};
template <typename F, typename S> inline
bool operator ==(const pair<F, S>& lhs, const pair<F, S>& rhs) {
// ...
}
template <typename F, typename S> inline
bool operator !=(const pair<F, S>& lhs, const pair<F, S>& rhs) {
// ...
}
template <typename T> inline
void flip(pair<T, T> &p) {
// ...
}
first
und second
initialisiert.==
und !=
.swap
, die ein anderes pair
mit denselben Typparametern akzeptiert und jeweils first
und second
zwischen den Paaren austauscht.pair
eine freistehende Funktion flip
, die innerhalb eines Paares die Werte von first
und second
vertauscht. T
und nicht F
und S
als Templateargument?pair
ist dem Programmierer des Codes der Fehler unterlaufen, dass ein 2D-Punkt an eine Funktion übergeben wird, die eigentlich einen Bruch kürzen soll. Der Compiler kann diesen Fehler nicht erkennen, da für ihn beide Paare dieselbe Bedeutung haben. struct
s (eins für Punkte, eins für Brüche) so um, dass dieser Fehler zur Compilezeit gefunden wird. Überlegen Sie sich gleichzeitig sinnvolle Namen für die Membervariablen Ihrer struct
s (nicht first
und second
!)#include <cstdint>
#include <numeric>
pair<int64_t, int64_t> project_point_onto_second_axis(const pair<int64_t, int64_t> &p) {
return pair<int64_t, int64_t>(p.first, 0);
}
pair<int64_t, int64_t> cancel_fraction(const pair<int64_t, int64_t> &p) {
// find greatest common divisor (c++17 and later)
int64_t gcd = std::gcd(p.first, p.second);
return pair<int64_t, int64_t>(p.first / gcd, p.second / gcd);
}
int main() {
// this is a fraction
pair<int64_t, int64_t> a(10, 4);
// this is a 2D point on an integer grid
pair<int64_t, int64_t> p(-2, 3);
pair<int64_t, int64_t> b = project_point_onto_second_axis(p);
pair<int64_t, int64_t> c = cancel_fraction(b);
std::cout << c.first << " " << c.second << "\n";
}