Initialisierung und Variablen Deklaration



  • @Swordfish sagte in Initialisierung und Variablen Deklaration:

    @john-0 Du kannst natürlich die Eigenschaft "statically typed" solange verdrehen bis sie in Dein Konzept passt.

    Es ist eine anerkannte Definition in der Informatik. Nur bei einigen Größen der C++ Programmierung will man davon nichts wissen. Fakt ist, bei C++ werden Typprüfungen zur Laufzeit vorgenommen, und zwar immer dann, wenn der dynamic_cast genutzt wird. Wenn Du diese Definition unzutreffend findest, welche Definition benutzt Du? Wie beschreibst Du statische Typisierung und wie verträgt sich damit dynamic_cast?

    Just go on. Heck, mit Deiner Herangehensweise ist nichtmal C statically typed.

    C hat keinerlei Sprachelemente, die es zur Laufzeit erlauben würden eine Typprüfung vorzunehmen. Deshalb C ist komplett statisch typisiert. Allerdings werden in diversen Projekten OOP und somit dynamische Typprüfung in C nach programmiert. Nur wie gesagt, ohne jede Unterstützung durch die Programmiersprache selbst.



  • @john-0 sagte in Initialisierung und Variablen Deklaration:

    Wenn Du diese Definition unzutreffend findest, welche Definition benutzt Du? Wie beschreibst Du statische Typisierung und wie verträgt sich damit dynamic_cast?

    T foo;
    

    foo ist vom Typ T. Und foo wird auch immer vom Typ T bleiben.



  • @Swordfish sagte in Initialisierung und Variablen Deklaration:

    foo ist vom Typ T. Und foo wird auch immer vom Typ T bleiben.

    Damit hast Du gerade CLOS zu einer statisch typisierten Sprache gemacht.

    Nachtrag: Du würdest somit nur Sprachen als dynamisch typisiert klassifizieren, die es erlauben zur Laufzeit bestehende Typen zu verändern z.B. JavaScript. Für das klassische Paradigma der dynamisch typisierten Programmiersprachen SmallTalk trifft das nämlich nicht zu. Ok, Du kannst natürlich darüber argumentieren, dass man in die Variable foo andere Objekte speichern kann, aber exakt das gleiche ist in C++ für Basiszeiger gegeben.



  • @john-0 sagte in Initialisierung und Variablen Deklaration:

    Damit hast Du gerade CLOS zu einer statisch typisierten Sprache gemacht.

    Ich habe garnicht gewusst daß das gültiges Lisp ist.



  • ist es bei templates nicht die aufgabe des compilers, irgendwie zu ermitteln, welcher datentyp da jetzt verwendet wird? das ändert doch nichts daran, dass der assembler dann mov rax, addw etc. übergeben bekommt und der datentyp feststeht, oder doch?
    also "der datentyp" ist ja sowieso schon mal etwas, das nachher im programm nicht mehr existiert.🙄



  • Wenn ich verstanden habe was du meinst nein. Ein template ist ein Platzhalter für den typ einer Funktion oder variablen bei der Verwendung von auto finde der Compiler den Typ automatisch



  • also ich hab jetzt nicht die mega-ahnung von compilerbau, aber ich vermute jetzt mal, dass bei dem programm

    
    template <typename T>
    void swap(T &a, T &b)
    {
    //swappen halt
    }
    
    int main()
    {
         double da, db;
         unsigned int uia, uib;
    
         /*
         irgendwelche initialisierungen
         */
    
         swap(da, db);
         swap(uia, uib);
    
         /*
         weitere swap-aufrufe, änderungen der werte, k.a.
         */
    
         return 0;
    }
    

    zwei versionen von swap erstellt werden: eine für den datentyp double und eine für den datentyp unsigned int. da aber nur eine version von swap im quelltext auftaucht, müsste ja theoretisch der compiler ermitteln, welcher datentyp an swap übergeben wird und dann die entsprechende swap-funktion aufrufen.


  • Mod

    Genau so ist es. Der Compiler weiß ja schließlich, was für einen Typ die Variablen haben, daher kann er das machen. Und das ist auch der Grund, wieso die Templatedefinition immer vorliegen muss, wenn man das Template instanziiert. Der Compiler kann keinen Platzhaltercode erzeugen, der für alle Datentypen passt.

    (Es gibt da natürlich diese eine Variante dieses einen Compilers, wo tatsächlich generischer Platzhaltercode erzeugt wird. Da hat ein Typ jahrelang dran geschrieben, bloß um zu zeigen, dass das berüchtigte extern template aus dem C++98-Standard, an dem sich alle anderen Compilerbauer vergeblich versucht haben, doch möglich ist)



  • @Abe Ein Template ist kein Platzhalter sondern wie der Name schon sagt eine Vorlage. Die Vorlage verwendet dann Platzhalter, die sog. Template-Parameter. Und an vielen Stellen passiert schon genau das was @Wade1234 geschrieben hat, nämlich dass der Compiler anhand von genau definierten Regeln automatisch ermittelt was für die Platzhalter eingesetzt werden soll.

    Beim Beispiel von @Wade1234 oben heisst das Template swap und hat einen Platzhalter namens T. Bei der ersten Verwendung von swap ermittelt der Compiler dann dass double für den Platzhalter T eingesetzt werden muss und bei der zweiten ist es dann unsigned int.

    Nun vergleich das mit:

    template <typename T>
    void swap(T &a, T &b)
    {
    }
    
    int main()
    {
        double da, db;
        unsigned int uia, uib;
    
        // Automatische Ermittlung des Typs direkt über die Verwendung eines Funktions-Tempaltes
        swap(da, db);   // -> swap<double>(double&, double&)
        swap(uia, uib); //  -> swap<unsigned int>(unsigned int&, unsigned int&)
    
        // Automatische Ermittlung des Typs mit auto
        auto daCopy = da;   //  -> double
        swap<decltype(daCopy)>(daCopy, db);    //  -> swap<double>(double&, double&)
        auto uiaCopy = uia; //  -> unsigned int
        swap<decltype(uiaCopy)>(uiaCopy, uib); //  -> swap<unsigned int>(unsigned int&, unsigned int&)
    
         // ...
    }
    

    Der Sinn der 2. Variante ist nur zur Verdeutlichung wie sich auto und Template Argument Deduction ähneln, schreiben würde man das so natürlich nicht.



  • Also ich hab das jezt mit einem vector versucht dort muss ich den typ vorher angeben. Das Hab ich auch nur gesagt um mir selbst nicht so blöd vorzukommen



  • @Abe
    Geht neuerdings auch mit Klassentemplates:

    #include <vector>
    #include <iostream>
    
    int main() {
        std::vector v{ 1u, 2u, 3u };
        std::cout << "typ: " << typeid(decltype(v[1])).name() << std::endl;
        for (auto&& e : v)
            std::cout << e << std::endl;
    
        std::vector w{ 1.0, 2.0, 3.0 };
        std::cout << "typ: " << typeid(decltype(w[1])).name() << std::endl;
        for (auto&& e : w)
            std::cout << e << std::endl;
    }
    

    https://godbolt.org/z/e2_qKU
    😉



  • @Wade1234 sagte in Initialisierung und Variablen Deklaration:

    ist es bei templates nicht die aufgabe des compilers, irgendwie zu ermitteln, welcher datentyp da jetzt verwendet wird?

    Jein, der Compilter versucht an Hand einiger recht komplizierter Regeln den Typ zu deduzieren. Das hängt von den sichtbaren Namensräumen den Parameter etc. ab. Falls das nicht gelingt eindeutig den Typ zu bestimmen muss man von Hand den Typ explizit angeben.


Anmelden zum Antworten