templates? oder: initialisierungsliste und konstruktor
-
Hi,
ich habe eine sehr großes Array, das schon vor der Laufzeit initialisiert wird. Normalerweise mache ich das dann immer so:
class A { int member1; int member2; }; a[] = { {5, 4}, {3, 2}, }Das Problem ist, dass ich Member in der Klasse habe und vorher noch nicht weiß, ob da ein short/char pointer/nicht pointer reinkommt. Die Schreibarbeit, jedes mal eine Typenumwandlung zu machen ist mir zu groß. Daher hab ich eine zweite Klasse geschrieben, die einfach jeden Wert in ein int umwandelt, egal ob adresse oder wert.
Das ganze sieht dann so aus:#include <iostream.h> class A { private: class V16 { private: int value; public: V16() {} template<class T> V16(T val) {value = (int) val;} operator int() {return value;} operator int*() {return (int*) value;} }; public: A() {} V16 Val1; V16 Val2; }; void main() { A a; int b = 5; a.Val1 = &b; a.Val2 = b; cout << *a.Val1 << ";" << a.Val2 << endl; }Funktioniert auch wunderbar, bis man versucht, ein Array aus A zu machen, dann meckert der Compiler, dass man bei nicht-Aggregaten keine Initialisierungsliste verwenden darf.
Ich hab auch schon den Konstruktor mit operator= ersetzt, hat auch nicht funktioniert...Habt ihr eine Idee, wie man das sauber lösen kann?
Uli
-
Das Ding sieht auf jeden Fall scheußlich aus - spendier deiner Klasse lieber einen vernünftigen Konstruktor, statt solche Verknotungen hinzulegen:
class A { public: A(int v1,char v2='\0') : val1(v1),val2(v2) {} ... private: int val1; char val2; }; A avals[] = { A(4711), A(0x0815,' '), ... };
-
Gute Idee... Die ich kurz in Erwägung gezogen habe, aber dann Verworfen habe... Vielleicht verwend ich die Konstruktor Lösung aber trotzdem, wenn es wirklch nicht kompakter geht:
class A { public: template<class T1, class T2> A(T1 v1,T2 v2) : val1((int) v1),val2((int) v2) {} private: int val1; int val2; }; int b; A avals[] = { A(0x0815,' '), A(b, &b), }; void main() { }Das Problem ist, dass die Klasse im Original natürlich nicht A heißt, sondern einen längeren Namen hat, was aber mit einem typedef schnell gelöst ist (denke ich)...
-
Noch ein Problem mit meiner Tabelle, die mittlerweile schon wieder ein bisschen anders aussieht.
Mir ist aufgefallen, dass ich meine Einträge nicht nacheinander in die Tabelle schreiben kann, da es insgesamt 0xFFFF mögliche Einträge gibt, aber nur ein Teil des Arrays genutzt wird...
Das könnte ich so realisieren (siehe auch Code oben):
LangerNameFuerA avals[]; void Init() { typedef LangerNameFuerA A; avals[0x0000] = A(1, 2); avals[0x0ABC] = A(5, 6); }Im Hinblick auf den kompletten Sourcecode ist der Name LangerNameFuerA notwendig (Beispiel!), genauso wie avals... als typisch schreibfauler Programmierer habe ich für LangerNameFuerA bereits eine Lösung gefunden (typedef).
Wie kann ich das auch für avals machen, so dass ich für avals jedesmal nur noch a schreiben muss?
Mein Lösungsansatz wäre, einfach eine Referenz zu verwenden, aber leider hab ich keine Ahnung, wie ich Referenzen mit Arrays kombiniere... (Außer vielleicht ein Array aus Referenzen, die in einer Schleife initialisiert werden, sicher keine schöne Lösung, soweit es überhaupt möglich ist?!)Uli
-
Was ist das für ein Design, in dem du 'beliebige' Werte in einem int speichern willst? Wenn du int*, char, int, ... in dem selben Member unterbringen willst, nimm doch einfach eine union oder such im Natz nach Variant-Datentypen.
Wie kann ich das auch für avals machen, so dass ich für avals jedesmal nur noch a schreiben muss?
Nimm doch einen Pointer

sehr_langer_typname aeusserst_wichtige_variable[1000]; void init() { typedef sehr_langer_typname A; A* a = aeusserst_wichtige_variable; a[0] = A(4711); a[200] = ...; ... }PS: Werden dir die Namen von außen vorgegeben?
-
Wenn es dich interessiert:
Ich bin gerade bei einem Emulator und habe eine lange Opcode Tabelle... Manchmal wird als Parameter ein Register verwendet, auf das ich natürlich zeigen muss. Manchmal ist es aber auch ein konstanter Wert,
z.B. RST $00 / RST $08, gleiche Instruktion aber verschiedene Parameter... Die Klasse für die Tabelle heißt OpcodeType, was im Projekt, als ganzes betrachtet, auch Sinn macht, nicht aber für meine Tabelle, die dann jedesmal mit OpcodeType beginnen würde...Die Template Lösung finde ich daher nicht verkehrt. Im Allgemeinen fällt mir auf, das die Verwendung von Templates, Operatorenüberladungen, etc. bei den meisten Leuten als unschön gelten... Ich denke man kommt immer ohne aus (Es gibt ja auch andere Sprachen)
Die Idee mit dem Pointer ist gut, danke

Uli
-
MaximumAccessViolation schrieb:
Im Allgemeinen fällt mir auf, das die Verwendung von Templates, Operatorenüberladungen, etc. bei den meisten Leuten als unschön gelten...
Klar, Templates sind durchaus nützlich, nur sollte man wissen, wie man damit umzugehen hat (die Auflösung der Templates findet zur Compilezeit statt). Und sie sind vor allem keine Universallösung für ALLE Probleme.
Und Operator-Überladungen sind zumindest bei mir recht beliebt (wenn sie passen).Aber auf dein Problem zurückzukommen - da wäre wohl eine Klassenhierarchie mit virtuellen Methoden angebrachter und auch sicherer als dein template-Gefummel - jeder mögliche Befehl leitet sich von der (abstrakten) Basisklasse OpCode ab, die eine Schnittstelle zum verarbeiten, auslesen etc. von Befehlen anbietet, und kümmert sich selber darum, was für Parameter er benötigt und wie er damit umgeht.