Wenn Sie eine Vorlage in C ++ verwenden, die einen ganzzahligen Wert als Parameter verwendet, gibt es Anforderungen an eine Integer-Variable, die als Parameter verwendet wird, die sich von der Verwendung der Variablen als Parameter in einem Funktionsaufruf unterscheidet?
Dies ist ein Follow-up zu Frage hier . Ich möchte speziell adressieren, wenn es einen Unterschied gibt WRT Variablen als "extern const int" für Funktionen oder Vorlagen deklariert?
Ich kann sehen, dass für einige Template-Fälle der Parameterwert zur Kompilierzeit benötigt wird. Ist das immer wahr? Gibt es eine Möglichkeit, nur für bestimmte Verwendungszwecke des Parameterwerts anzugeben, dass der Wert zur Laufzeit verwendet wird?
Das Folgende stammt vom Standard.
14.3.2.1:
Ein Template-Argument für einen Nicht-Template-Template-Template-Template-Template ist:
- ein ganzzahliger Konstantenausdruck des Integral- oder Aufzählungstyps; oder
- der Name eines nicht-type Template-Parameters; oder
- die Adresse eines Objekts oder einer Funktion mit externer Verknüpfung, einschließlich Funktionsvorlagen und Funktionsschablonen-IDs, aber nicht-statische Klassenmitglieder ausgenommen, ausgedrückt als & amp; ID-Ausdruck, wo die & amp; ist optional, wenn der Name auf eine Funktion oder ein Array verweist oder wenn der entsprechende Template-Parameter eine Referenz ist; oder
- ein Zeiger auf das Element, wie in 5.3.1.
beschrieben
5.19.1:
An mehreren Stellen benötigt C ++ Ausdrücke, die zu einer Integral- oder Enumerationskonstante ausgewertet werden: als Array-Grenzen (8.3.4, 5.3.4), als Case-Ausdrücke (6.4.2), als Bitfeldlängen (9.6), als Enumerator-Initialisierer (7.2), als statische Member-Initialisierer (9.4.2) und als Integral- oder Enumerations-Nicht-Typ-Template-Argumente (14.3).
%Vor%Ein ganzzahliger Konstantenausdruck kann nur Literale (2.13), Enumeratoren, const-Variablen oder statische Datenelemente von Integral- oder Enumerationstypen, die mit konstanten Ausdrücken (8.5) initialisiert sind, Nicht-Typ-Template-Parameter von Integral- oder Enumerationstypen und sizeof enthalten Ausdrücke. Fließende Literale (2.13.3) können nur auftreten, wenn sie in Integral- oder Aufzählungstypen umgewandelt werden. Geben Sie nur Konvertierungen in Integral- oder Enumera- tionstypen können verwendet werden. Insbesondere dürfen, außer in sizeof-Ausdrücken, Funktionen, Klassenobjekte, Zeiger oder Referenzen nicht verwendet werden, und Zuweisungs-, Inkrement-, Dekrement-, Funktionsaufruf- oder Kommaoperatoren dürfen nicht verwendet werden.
In Bezug auf deinen vorherigen Beitrag glaube ich das Wesen im Teil "const Variablen ... initialisiert mit ..." (und ich glaube nicht, dass extern initialisiert wird).
> Es muss ein ganzzahliger konstanter Ausdruck sein. Das erklärt das Standarddokument bei 5.19
:
Ein ganzzahliger Konstantenausdruck kann nur Literale (2.13), Enumeratoren, const-Variablen oder statische Datenelemente von Integral- oder Enumerationstypen, die mit konstanten Ausdrücken (8.5) initialisiert sind, Nicht-Typ-Template-Parameter von Integral- oder Enumerationstypen und sizeof enthalten Ausdrücke. Fließende Literale (2.13.3) können nur auftreten, wenn sie in Integral- oder Enumerationstypen umgewandelt werden. Es können nur Konvertierungen in Integral- oder Aufzählungstypen verwendet werden.
Beachten Sie, dass "Integral" ein anderer Begriff für "Integer" ist, aber nicht gleich "Int" ist. "char" hat zum Beispiel einen ganzzahligen / ganzzahligen Typ, ist aber offensichtlich nicht der int-Typ. Konkret ist folgendes erlaubt:
10 or 10L or anything like that
enum { THIS, OR, THAT };
int const this_one = 10;
sizeof(char)
Jeder dieser Parameter kann als Vorlageargument für einen Parameter verwendet werden, der einen integrierten Typ des entsprechenden Typs aufweist. Einige Conversions werden jedoch weiterhin angewendet. Wenn also ein int gewünscht wird und du ein char übergibst, wird das char automatisch an int übergeben. Gleiches, wenn Sie einen Enumerator bereitstellen und ein Int.
Also nach diesen Regeln, wenn du
hast %Vor%Und es sieht keine Definition, die diese Konstante mit einem ganzzahligen konstanten Ausdruck initialisiert, es kann nicht als Template-Argument verwendet werden. Aber es kann natürlich als ein Funktionsargument verwendet werden. Diese müssen zur Kompilierzeit nicht bekannt sein, da diese nicht Teil eines Typs sind. Sobald Sie eine Vorlagenspezialisierung benennen, werden die von Ihnen verwendeten Argumente Teil des Typs:
%Vor% Beachten Sie, dass andere Möglichkeiten sind, um SomeName
als Argument zu übergeben. Jedoch kann nicht von einem Integer-Template-Parameter akzeptiert werden. Sie können das Obige durch einen Referenzparameter akzeptieren, zum Beispiel
Und es würde die SomeName
von oben akzeptieren. Anstelle eines Wertes wurde nun ein bestimmter Ort ausgewählt, der für das gesamte Programm eindeutig ist (da die Variable extern
linkage hat).
Es ist immer der Fall, dass der Wert von int zur Kompilierzeit benötigt wird.
Da jede Template-Instanziierung ein separater Stück kompilierter Code ist (selbst für Integer-Template-Parameter), muss diese Integer beim Kompilieren verfügbar sein (und es muss garantiert sein, dass sie sich nie ändert).
Dies ist auch der Grund, warum es keine gute Idee ist, keine Integer-Template-Parameter zu verwenden, wenn Sie eine große Anzahl einzigartiger Werte verwenden wollen - Sie können schnell eine riesige ausführbare Datei erhalten.
Tags und Links const c++ templates parameters extern