Initialisierung und Variablen Deklaration
-
@Swordfish sagte in Initialisierung und Variablen Deklaration:
foo
ist vom TypT
. Undfoo
wird auch immer vom TypT
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.
-
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 namensT
. Bei der ersten Verwendung vonswap
ermittelt der Compiler dann dassdouble
für den PlatzhalterT
eingesetzt werden muss und bei der zweiten ist es dannunsigned 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; }
-
@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.