Der Grund dafür ist, dass theoretisch die Funktionsvorlage mit einem Typ aufgerufen werden könnte, der über ein Datenmember oder eine Memberfunktion namens Iterator verfügt. Wenn der Compiler die Vorlage analysiert, die enthält, weiß er nichts über die Typen, die von dem Code übergeben werden, der später kommt. Dies bedeutet, dass, bis der Compiler weiß, was Container ist und welche Member es hat, gibt es keine Möglichkeit zu wissen, ob Container::iterator ein Typ ist oder nicht. Tatsächlich sagen die Regeln von C++, dass der Compiler, bis anders angegeben, Container::iterator annehmen muss, kein Typ. Die Lösung besteht darin, dem Compiler einen Hinweis über das Typename-Schlüsselwort zu geben: Wenn Sie die Operator+- oder Operator-Funktionen aufrufen, bewirkt diese Annahme, dass der Compiler einen Aufruf der Nicht-Vorlagenfunktionen generiert. Aber der Linker gibt Ihnen einen “undefinierten externen” Fehler, weil Sie diese Nicht-Template-Funktionen nie wirklich definiert haben. Als Beispiel betrachten Sie die Headerdatei foo.h, die die folgende Vorlagenfunktionsdeklaration enthält: Als Beispiel betrachten Sie die Headerdatei Foo.h, die die folgende Vorlagenklasse enthält. Beachten Sie, dass die Methode Foo::f() inline ist und die Methoden Foo::g() und Foo::h() nicht. Hinweis: Eine “Vorlagenfunktion” ist die Instanziierung einer “Funktionsvorlage”. Bevor Wir zeigen, wie Sie dies tun, stellen Wir sicher, dass Sie sich nicht selbst in den Fuß schießen. Unterscheidet sich das Verhalten der Funktion für Ihre Benutzer? Mit anderen Worten, ist das beobachtbare Verhalten in irgendeiner substanziellen Weise anders? Wenn ja, schießen Sie sich wahrscheinlich selbst in den Fuß und Sie werden wahrscheinlich Ihre Benutzer verwirren – Sie sind wahrscheinlich besser dran, verschiedene Funktionen mit unterschiedlichen Namen zu verwenden – verwenden Sie keine Vorlagen, verwenden Sie keine Überlastung.

Wenn der Code für int z. B. etwas in einen Container einfügt und das Ergebnis sortiert, aber der Code für std::string etwas aus einem Container entfernt und das Ergebnis nicht sortiert, sollten diese beiden Funktionen kein überladenes Paar sein – ihr beobachtbares Verhalten ist anders, sodass sie unterschiedliche Namen haben sollten. Wenn Sie nun erzwingen möchten, dass die eigentlichen Argumente heraufgestuft werden, bevor der Compiler den Vorlagentyp ableitet, können Sie die oben genannte Technik verwenden. Wenn Sie z.B. einfach g(42) nennen, erhalten Sie g(42), aber wenn Sie 42 bis g() übergeben möchten, könnten Sie dies sagen: g(42). (Natürlich können Sie den Parameter auch explizit heraufstufen, z. B. g(long(42)) oder sogar g(42L), aber das ruiniert das Beispiel.) Da nicht abhängige Typen und nicht abhängige Member in den abhängigen Vorlagenbasisklassen nicht gefunden werden, durchsucht der Compiler den einschließenden Bereich, z. B. den einschließenden Namespace. Dies kann dazu führen, dass es stillschweigend(!) das Falsche tut.

Natürlich muss die Vorlage tatsächlich irgendwo verwendet werden: Eine strukturierte Bindungsdeklaration führt dann die Bindung auf eine von drei möglichen Arten aus, abhängig von E: Das Wiederholen des obigen immer und immer wieder für Array of float, of char, of std::string, of Array-of-std::string, etc., würde mühsam. Stattdessen fügen Sie vor der Klassendefinition den Vorlagentyp”T> hinzu (das T kann ein beliebiger Bezeichner sein, T ist nur der am häufigsten verwendete, insbesondere in Beispielen). Anstatt dann int oder float oder char zu verwenden, wenn auf den Datentyp verwiesen wird, verwenden Sie stattdessen T. Anstatt nur auf die Klasse als Array zu verweisen, ist es Array wenn sie auf die Vorlage verweist, oder Array, Array usw., wenn auf eine bestimmte Instanziierung verwiesen wird. Nicht nur das, es gibt einige Techniken (Template-Meta-Programmierung oder TMP), die unter den richtigen Umständen die Effizienz des generierten Codes verbessern können. Der grundgedanke besteht darin, den Compiler dazu zu bringen, mehr Arbeit zur Kompilierungszeit zu erledigen, sodass zur Laufzeit weniger Arbeit geleistet werden muss. Eine Vorlage ist ein Cookie-Cutter, der angibt, wie man Cookies schneidet, die alle ziemlich gleich aussehen (obwohl die Cookies aus verschiedenen Teigarten hergestellt werden können, haben sie alle die gleiche Grundform). Auf die gleiche Weise ist eine Klassenvorlage ein Cookie-Cutter für eine Beschreibung, wie eine Familie von Klassen erstellt wird, die alle im Grunde gleich aussehen, und eine Funktionsvorlage beschreibt, wie eine Familie ähnlich aussehender Funktionen erstellt wird.