Verwendung eines int als Vorlageparameter, der bis zur Laufzeit nicht bekannt ist

7

Ich versuche eine Ganzzahl als Vorlageparameter für eine Klasse zu verwenden. Hier ist ein Beispiel für den Code:

%Vor%

Wenn ich so etwas mache, funktioniert es:

%Vor%

Nehmen wir jedoch an, dass ich den Wert von array_qty (den Vorlagenparameter) beim Kompilieren nicht kenne und ihn nur während der Laufzeit kenne. In diesem Fall würde ich im Wesentlichen eine int-Variable als Template-Argument übergeben. Der folgende Code funktioniert der Demonstration wegen nicht:

%Vor%

Ich bekomme den folgenden Fehler während der Kompilierzeit, wenn ich das obige versuche:

%Vor%

Ich habe versucht, test_array_qty in einen const zu konvertieren, während ich ihn als Template-Parameter übergebe, aber das scheint auch nicht der Trick zu sein. Gibt es eine Möglichkeit, dies zu tun, oder missbrauche ich Template-Parameter? Vielleicht müssen sie zur Kompilierzeit bekannt sein?

Das Ziel ist NICHT, diesen spezifischen Ansatz zu lösen, sondern einen Weg zu finden, die Länge des Arrays auf eine int-Variable zu setzen, die beim Instanziieren der Klasse angegeben werden kann. Wenn es eine Möglichkeit gibt, dies über einen Template-Parameter zu tun, wäre das ideal.

Bitte beachten Sie, dass ich dafür ein Array verwenden muss, und NICHT einen Vektor, der als Vorschlag enden könnte. Außerdem ist array_qty immer ein Wert zwischen 0 und 50 - falls das einen Unterschied macht.

Bearbeiten:

Ich habe angegeben, dass ich dafür keinen Vektor verwenden kann, weil ich dafür keinen Vektor verwenden kann. Ja, ich habe es bewertet. In jedem Fall ist diese Frage keine Untersuchung von "Arrays vs Vektoren". Ich möchte vermeiden, dass diese Frage viele Kommentare und Antworten hat, die mir sagen, "benutze einfach einen Vektor". Das ist so, als würde man zu Edison gehen und sagen "benutze einfach eine Kerze". Gute Programmierung ist eine Erkundung dessen, was möglich ist, und nicht nur eine Aussage über das, was bekannt ist. Wenn wir das aufgrund der Unmöglichkeit nicht herausfinden können, ist das eine Sache. Die Möglichkeit einer Lösung dafür nicht zu erforschen, weil "ein Vektor einfacher wäre" ist nicht.

Außerdem verstehe ich nicht, warum es einen Downvote gibt. Dies ist eine absolut gültige Frage, die in kohärenter Weise gestellt wird.

    
user396404 19.01.2013, 18:30
quelle

4 Antworten

9

Dies kann effektiv gemacht werden. Aber vertrau mir, wenn ich sage, dass du die falsche Frage stellst. Also, was folgt, beantwortet deine Frage, auch wenn es fast immer eine schlechte Idee ist, es zu tun.

Was Sie in Wirklichkeit tun können, ist, 50 verschiedene Programme zu erstellen, eines für jede der 50 möglichen Größen, und dann bedingt zu dem gewünschten zu springen.

%Vor%

Rufen Sie switcher<50>::run( value ); auf und wenn der Wert 0 bis 50 ist, wird prog<value>::run() aufgerufen. Innerhalb von prog::run ist der Vorlagenparameter ein Kompilierzeitwert.

Horrid Hack, und Chancen sind Sie besser dran wäre mit einer anderen Lösung, aber es ist, was Sie gefragt haben.

Hier ist eine C ++ 14-Tabellen-basierte Version:

%Vor%

magic_switch_t<N>{}( f, 3, blah1, blah2, etc ) ruft f(index_t<3>{}, blah1, blah2, etc) auf.

Einige C ++ 14-Compiler ersticken bei der Erweiterung des variardic-Packs, die ein Lambda enthält. Es ist nicht wichtig, Sie können eine Problemumgehung durchführen, aber die Problemumgehung ist hässlich.

Die C ++ 14-Funktionen sind alle optional: Sie können alles in C ++ 11 implementieren, aber wieder, hässlich.

Der Wert f sollte grundsätzlich ein Funktionsobjekt sein (entweder ein Lambda, das auto als erstes Argument annimmt, oder ein manuelles Argument). Das direkte Übergeben eines Funktionsnamens funktioniert nicht gut, da das oben beschriebene am besten funktioniert, wenn das erste Argument zu einem Kompilierzeitwert wird.

Sie können eine Funktionsvorlage mit einem Lambda-Objekt oder einem Funktionsobjekt als Hilfe umbrechen.

    
Yakk 19.01.2013, 18:58
quelle
5

Für C ++ 11 sind nicht typisierte Vorlagenargumente auf Folgendes beschränkt (§14.3.2 / 1):

  

Ein Template-Argument für einen Nicht-Template-Template-Template-Template-Template-Template-Parameter darf eins sein von:

     
  • für einen Nicht-Typ-Template-Parameter des Integral- oder Enumerationstyps, einen konvertierten konstanten Ausdruck (5.19) des Typs des Template-Parameters; oder
  •   
  • der Name eines nicht-type Template-Parameters; oder
  •   
  • ein konstanter Ausdruck (5.19), der die Adresse eines Objekts mit statischer Speicherdauer und externer oder interner Verknüpfung oder eine Funktion mit externer oder interner Verknüpfung angibt, einschließlich Funktionsvorlagen und Funktionsschablonen-IDs, jedoch nicht-statische Klassenmitglieder ausschließend, ausgedrückt (Klammern ignoriert) als & amp; ID-Ausdruck, außer dass der & amp; kann weggelassen werden, wenn der Name auf eine Funktion oder ein Array verweist und ausgelassen wird, wenn der entsprechende Template-Parameter eine Referenz ist; oder
  •   
  • ein konstanter Ausdruck, der zu einem Nullzeigerwert (4.10) führt; oder
  •   
  • ein konstanter Ausdruck, der zu einem Nullelement-Zeigerwert (4.11) führt; oder
  •   
  • ein Zeiger auf das Element, wie in 5.3.1.
  • beschrieben   

In C ++ 98 und 03 ist die Liste noch eingeschränkter. Fazit: Was Sie versuchen, ist einfach nicht erlaubt.

    
Jerry Coffin 19.01.2013 18:43
quelle
3

Template-Argumente müssen Kompilierungszeitkonstanten sein, die als "konstante Ausdrücke" oder kurz " constexpr s" bezeichnet werden. Es gibt also keine Möglichkeit, Vorlagen zu verwenden.

Sie können ein Array dynamischer Größe verwenden und seine Größe in int speichern.

Oder verwenden Sie einfach vector . Stellen Sie sicher, dass Sie die Größe im Konstruktor initialisieren, indem Sie die gewünschte Größe an den Vektorkonstruktor übergeben!

    
Csq 19.01.2013 18:32
quelle
2

Tut mir leid, das ist nicht möglich. Das Template-Argument muss ein konstanter Ausdruck sein, der zur Kompilierzeit bekannt ist.

    
oefe 19.01.2013 18:34
quelle

Tags und Links