Frage zu Templates
-
Hi,
ich versuche C++ richtig zu lernen und habe dieses Beispiel von Stroustrup:template<class In, class Out> void copy(In from, In too_far, Out to) { while (from != too_far) { *to = *from; ++to; ++from; } }Was mich wundert, ist, dass Pointer verwendet werden, obwohl sie bei der Parameterliste gar nicht als solche deklariert wurden.
Das hier kompiliert allerdings auch ohne zu murren (Warnungen eingeschalten):
template<class In, class Out> void copy(In *from, In *too_far, Out *to) { while (from != too_far) { *to = *from; ++to; ++from; } }Was ist nun richtig und weshalb?
L. G.,
IBV
-
Das Template nimmt alles, was sich wie ein Pointer dereferenziern lässt, also insbesondere auch Pointer. Iteratoren überschreiben operator*, sie können also auch benutzt werden.
Wenn du Pointer übergibst, ist In gleich Typ*. Schreibst du In* (wie im zweiten Fall) ist In nur Typ.
-
-
Hi,
beim Übersetzen eines Templates wird Dir der Compiler nur solche syntaktischen Fehler anmeckern, die er ohne Kenntnis der Templateparameter klären kann.
Erst beim Instanziieren des Templates, wird er Dir auch die anderen Fehler anzeigen können.
Das erste Beispiel kannst Du mit allen Typen instanziieren, die einen Dereferenzoperator kennen. Im zweiten Beispiel mußt Du Zeiger an copy übergeben.
mfg Martin
-
manni66 schrieb:
Iteratoren überschreiben operator*, sie können also auch benutzt werden.
Ist das wirklich so? begin() und end() geben doch Pointer zurück.
mgaeckler schrieb:
Das erste Beispiel kannst Du mit allen Typen instanziieren, die einen Dereferenzoperator kennen. Im zweiten Beispiel mußt Du Zeiger an copy übergeben.
Fände ich sogar richtiger, da das zweite Beispiel sowas wie Typsicherheit bietet und das erste Beispiel eher zu Fehlern tendiert. Das ist so wie Ducktyping bei dynamisch typisierten Sprachen.
L. G.,
IBV
-
IBV schrieb:
manni66 schrieb:
Iteratoren überschreiben operator*, sie können also auch benutzt werden.
Ist das wirklich so? begin() und end() geben doch Pointer zurück.
Nein.
begin()undend()liefern Iteratoren. Pointer sind Iteratoren. Es gibt aber auch Iteratoren, die keine Pointer sind. Iteratoren sind über gewisse Eigenschaften definiert. Sie können mit*dereferenziert und mit++inkrementiert werden. Das gilt für Pointer, aber auch Klassen, die eben diese Operatoren überschreiben. Beispielsweise ist ein Iterator auf einstd::setkein Pointer. Dennoch kann ich den mit dem gezeigtencopyverwenden. Zumindest in der Stroustroup-Version. In deiner geht das nicht, da er eben kein Pointer ist.
-
IBV schrieb:
Fände ich sogar richtiger, da das zweite Beispiel sowas wie Typsicherheit bietet und das erste Beispiel eher zu Fehlern tendiert. Das ist so wie Ducktyping bei dynamisch typisierten Sprachen.
Das erste Beispiel ist doch ein Paradebeispiel für Ducktyping. Es verhält sich wie ein Pointer, also kann es wie ein Pointer benutzt werden. Und ansonsten gibt's eine Fehlermeldung (zur Compilezeit!), weil man etwas benutzt hat, das nicht wie ein Pointer funktioniert. Ob dahinter letztlich ein Pointer, ein Iterator oder sonstwas steht ist dem Funktionstemplate egal, Hauptsache es kann das Verhalten liefern, das die Funktion braucht. Das zweite Beispiel geht nur mit Pointern.PS: In C++ würde man aber eher sagen, dass die Funktion etwas erwartet, dass sich wie ein Iterator verhält, nicht etwas, das sich wie ein Pointer verhält. Denn Iterator ist allgemeiner, ein Pointer ist ein Iterator, aber nicht jeder Iterator ist ein Pointer. Gerade das macht das zweite Beispiel auch so schlecht, denn es ist doch gar nicht wichtig, ob es wirklich ein Pointer ist. Das erste Beispiel kümmert sich nur um die Iteratoreigenschaften (Dereferenzierbar, Inkrementierbar, ...), die unter anderem auch von Pointern erfüllt werden.
-
Ok, dann hat sich das für mich geklärt. Danke an alle Beteiligten!

L. G.,
IBV
