Template in C ++, warum muss enum verwendet werden

8

Ich habe eine kurze Frage zu Punkt 48 in Scott Meyers "Effective C ++". Ich verstehe einfach nicht den Code aus dem Buch kopiert,

%Vor%

Warum muss ich enum in der Vorlagenprogrammierung verwenden? Gibt es einen alternativen Weg, dies zu tun? Danke für die Hilfe im Voraus.

    
Ming 11.08.2012, 18:26
quelle

4 Antworten

8

Sie könnten static const int auch verwenden:

%Vor%

Das sollte auch in Ordnung sein. Das Ergebnis ist in beiden Fällen gleich.

Oder Sie können eine vorhandene Klassenvorlage verwenden, z. B. std::integral_constant (in C ++ 11 nur) wie:

%Vor%     
Nawaz 11.08.2012 18:28
quelle
4

Ich sehe, dass die anderen Antworten die alternativen Ansätze gut abdecken, aber niemand erklärt, warum enum (oder static const int ) erforderlich ist.

Betrachten Sie zunächst das folgende Nicht-Template-Äquivalent:

%Vor%

Sie sollten es leicht verstehen können. Es ist jedoch ein Nachteil, dass der Wert des Faktors zur Laufzeit berechnet wird, d. H. Nach dem Ausführen des Programms führt der Compiler die rekursiven Funktionsaufrufe und Berechnungen aus.

Die Idee des Template-Ansatzes besteht darin, zur Kompilierungszeit die gleichen Berechnungen durchzuführen und das Ergebnis in die resultierende ausführbare Datei einzufügen. Mit anderen Worten, das vorgestellte Beispiel löst etwas Ähnliches auf:

%Vor%

Aber um das zu erreichen, müssen Sie den Compiler dazu bringen, die Berechnungen auszuführen. Und um das zu tun, müssen Sie das Ergebnis irgendwo speichern lassen.

Der enum ist genau dafür da. Ich werde versuchen, das zu erklären, indem ich darauf hinwies, was dort nicht funktionieren würde.

Wenn Sie versucht haben, ein reguläres int zu verwenden, würde es nicht funktionieren, weil ein nicht-statisches Element wie int nur in einem instanziierten Objekt sinnvoll ist. Und Sie können ihm keinen Wert zuweisen, sondern das in einem Konstruktor. Eine einfache int wird nicht funktionieren.

Sie benötigen etwas, auf das in einer uninstantiierten Klasse zugegriffen werden könnte. Sie könnten static int ausprobieren, aber es funktioniert immer noch nicht. clang würde Ihnen eine ziemlich einfache Beschreibung des Problems geben:

%Vor%

Wenn Sie diese Definitionen tatsächlich außer Linie bringen, wird der Code kompiliert, aber es ergibt sich zwei 0 s. Das liegt daran, dass diese Form die Berechnung von Werten für die Initialisierung des Programms verzögert und die korrekte Reihenfolge nicht garantiert. Es ist wahrscheinlich, dass ein Factorial<n-1>::value s vor der Berechnung erhalten wurde und somit 0 zurückgegeben wurde. Außerdem ist es immer noch nicht das, was wir wirklich wollen.

Schließlich, wenn Sie static const int dort setzen, wird es wie erwartet funktionieren. Das liegt daran, dass static const zur Kompilierzeit berechnet werden muss, und genau das wollen wir. Lassen Sie uns den Code erneut eingeben:

%Vor%

Zuerst instanziert Factorial<5> ; static const int erzwingt, dass der Compiler seinen Wert zum Zeitpunkt des Compilers berechnet. Effektiv instanziiert es den Typ Factorial<4> , wenn er einen anderen Wert berechnen muss. Und das geht so lange, bis es Factorial<0> erreicht, wo der Wert ohne weitere Instanziierungen berechnet werden kann.

Also, das war der alternative Weg und die Erklärung. Ich hoffe, es war zumindest ein bisschen hilfreich, den Code zu verstehen.

Sie können sich diese Art von Vorlagen als Ersatz für die rekursive Funktion vorstellen, die ich zu Beginn geschrieben habe. Sie ersetzen nur:

  • return x; mit static const int value = ... ,
  • f(x-1) mit t<x-1>::value ,
  • und if (n == 0) mit der Spezialisierung struct Factorial<0> .

Und für das enum selbst, wie bereits erwähnt, wurde es im Beispiel verwendet, um dasselbe Verhalten wie static const int durchzusetzen. Es ist so, weil alle enum -Werte zur Kompilierungszeit bekannt sein müssen, so dass jeder angeforderte Wert zur Kompilierungszeit berechnet werden muss.

    
Michał Górny 11.08.2012 23:21
quelle
2

Um genauer zu sein, existiert der "enum hack", weil die korrektere Art, dies mit static const int zu tun, von vielen Compilern dieser Zeit nicht unterstützt wurde. Es ist redundant in modernen Compilern.

    
Puppy 11.08.2012 21:53
quelle
1

Sie können static const int verwenden, wie Nawaz sagt. Ich vermute, der Grund, warum Scott Myers eine Enumeration benutzt, ist, dass die Compiler-Unterstützung für die In-Class-Initialisierung von statischen Const-Ganzzahlen ein bisschen eingeschränkt war, als er das Buch schrieb. Also ein Enum war eine sicherere Option.

    
jahhaj 11.08.2012 21:44
quelle

Tags und Links