JGU Logo JGU Logo JGU Logo JGU Logo

Institut für Informatik

Michael Wand
Christian Ali Mehmeti-Göpel
Wintersemester 2020/21DIGITAL

Blatt 05

Aufgabe 01
Einführung in die Softwareentwicklung



Aufgabe Tupel

Letzte Änderung: 07. December 2020, 14:33 Uhr
15 Punkteim Detail
Ansicht:   |  


Auf Blatt 3 haben wir gesehen, wie man structs zur sinnvollen Gruppierung von Daten einsetzen kann. Braucht man viele solcher Gruppierungen, kann die Anzahl an structs schnell dazu führen, dass man die Übersicht verliert. Wir wollen jetzt mithilfe von Templates eine Alternative zu structs implementieren und deren Tradeoffs diskutieren. Als Basis verwenden wir folgende Deklaration:


pair.h

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) {
    // ...
}

  1. Ergänzen Sie einen passenden Konstruktor, der zwei Argumente nimmt und damit first und second initialisiert.
  2. Implementieren Sie die Vergleichsoperatoren == und !=.
  3. Implementieren Sie die oben angedeutete Funktion swap, die ein anderes pair mit denselben Typparametern akzeptiert und jeweils first und second zwischen den Paaren austauscht.
  4. Implementieren Sie außerhalb von pair eine freistehende Funktion flip, die innerhalb eines Paares die Werte von first und second vertauscht.
    Warum haben wir nur T und nicht F und S als Templateargument?
  5. Betrachten Sie den untenstehenden Codeauszug. Durch unglückliche Variablenbenennung und exzessize Benutzung von 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.
    Schreiben Sie den Codeauszug unter Verwendung von zwei unterschiedlichen structs (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 structs (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";
    }