type_traits



  • Hi 🙂

    Ich hab mal wieder eine Frage zum Buch http://www.thalia.at/shop/at_thalia_start/suchartikel/c_11/peter_pohmann/ISBN3-86802-106-X/ID35067343.html?fftrk=1%3A1%3A10%3A10%3A1&jumpId=27548972

    Ein Auszug aus einem Programm:

    template<typename T, typename IsIntegral>
    struct Equality {
    };
    
    template<typename T>
    struct Equality<T, std::true_type> {
       Equality(T a, T b) { // was wird denn hier aufgerufen????????
          value = (a == b);
       }
       bool value;
    };
    
    template<typename T>
    bool IsEqual(T a, T b) {
       return Equality<T, typename std::is_integral<T>::type>(a, b).value;
    }
    
    int a = 8;
    int b = 7;
    bool ri = IsEqual(a, b);
    

    Es geht um diesen Equality-Aufruf. Was wird denn da aufgerufen? Ein Konstruktor eines anderen structs 😕



  • da wird der konstruktor definiert.



  • Wenn das der Konstruktor ist, wozu brauche ich dann die Zeilen 1 bis 3?


  • Mod

    // was wird denn hier aufgerufen????????

    Da wird nichts aufgerufen, da wird ein Konstruktor definiert. Innerhalb der Definition einer partiellen Spezialisierung definiert man den Konstruktor ganz normal.

    Du könntest auch

    Equality<T, std::true_type>(T a, T b) { ... }
    

    Schreiben, um den Konstruktor zu definieren; ist es dann klarer? Man lässt die Qualifizierung mit der Argumentenliste im Allgemeinen weg

    Equality(T a, T b) {}
    

    Das darf man, weil innerhalb der Definition (und generell im Scope) eines Klassentemplates der Name des Templates automatisch auch - je nach Kontext - auf den Namen der momentan instantiierten Spezialisierung verweist. Diesen Namen nennt man dann injected-class-name.

    template<typename T>
    struct A
    {
    	using type = A; // type ist A<T>
    };
    
    A<int>::A::type b; // B ist vom Typ A<int>::A::type = A<int>
    


  • Wenn ich die Zeilen 1 bis 3 auskommentiere, bekomme ich eine Fehlermeldung: 'Equality' is not a class template

    Ok, brauche ich also. Wird da irgendwie unsichtbar was geerbt?



  • tröröö schrieb:

    Wenn ich die Zeilen 1 bis 3 auskommentiere, bekomme ich eine Fehlermeldung: 'Equality' is not a class template

    Ok, brauche ich also. Wird da irgendwie unsichtbar was geerbt?

    lies in deinem buch nach was (partielle) templatespezialisierung ist.



  • Jetzt dämmert mir was.

    Ich dachte, man KANN etwas spezialisieren. Mir war nicht klar, dass es die allgemeinere Form geben MUSS 🙂



  • tröröö schrieb:

    Jetzt dämmert mir was.

    Ich dachte, man KANN etwas spezialisieren. Mir war nicht klar, dass es die allgemeinere Form geben MUSS 🙂

    wenn du diese nicht wünschst, dann kannst du sie deklarieren ohne sie zu definieren.



  • tröröö schrieb:

    Ok, brauche ich also. Wird da irgendwie unsichtbar was geerbt?

    Nein, das nennt sich Template Spezialisierung, in diesem Fall sogar partielle Template Spezialisierung.
    Ich nehme ein Beispiel aus der Standardbibliothek.
    Du kennst mit Sicherheit std::vector.
    std::vector arbeitet mit allen Typen gleich, es speichert sie einfach. Allerdings kam irgendeiner auf die "tolle" Idee, das man denn für bool irgendwie optimieren könnte. Wie genau die Optimierung aussieht und wieso die Mist ist, ist hier irrelevant. Uns interessiert die Implementierung.
    Man hat also std::vector, der sieht in etwa so aus:

    template <typename T, class Allocator = std::default_allocator<T>>
    class vector
    {
      // die ganzen Funktionen etc.
    };
    

    Wie sorgt man nun dafür, dass er für bool anders funktioniert?
    Nun man spezialisiert das Template.
    Ignorieren wir mal für einen Moment den Allocator, dann sähe das so aus:

    // Basistemplate
    template <typename T>
    class vector {...};
    // Spezialiserung für bool
    template <> //< Kennzeichen einer Spezialisierung
    class vector<bool> // diese Klasse wird verwendet, wenn man den vector mit bool instanziiert
    {
      // spezielle Funktionen für bool
    };
    

    Instanziiert man nun vector mit bool, wird die Spezialisierung genommen.
    Wie sieht das nun für die Version mit Allocator aus?
    So:

    // Basistemplate
    template <typename T, class Allocator>
    class vector {...};
    // Spezialiserung für bool
    template <class Allocator> // (2)
    class vector<bool, Allocator> // (1)
    {...};
    

    Bei (1) sagen wir: Diese Spezialisierung gilt für alle vector, die mit bool und einem beliebigen Allocator instanziiert werden. Wie drücken wir aus, dass es ein beliebiger Allocator sein soll und nicht etwa std::default_allocator? Nun wie sonst auch: Mit einem Template. In (2) führen wir erneut den Namen Allocator ein um den als Platzhalter für einen beliebigen Typen nutzen zu können.
    In deinem Fall spezialisierst du nun Equality einfach für alle Instanziierungen mit einem beliebigen Typen und std::true_type als zweites Argument.

    Edit: Oh, hätte mir das auch sparen können.



  • tröröö schrieb:

    Ich dachte, man KANN etwas spezialisieren. Mir war nicht klar, dass es die allgemeinere Form geben MUSS 🙂

    Wenn Du nix hast, kannst Du nix spezialisieren.


Anmelden zum Antworten