Typkonvertierungsproblem
-
Wenn ich dich richtig versteh, dann ist es immer noch sowas:
template<class T, int i> void foo(T bar[i]) { ... }
-
Ich will aber nur einen Zeiger übergeben der z.B. vom Typ int[4] ist.
Also um das Gesammtproblem zu schildern:
Ich habe fünf void-Zeiger.
Jeder dieser zeigt auf ein erstes Element.
Je nach Zeiger ist das Element vom Typ:
float[3]
float
byte[4]
float[2]
shortNach dem ersten Element kommt nicht gleich das nächste im Speicher, sondern erst nach einer gewissen Anzahl von Bytes.
Die Anzahl an Elementen ist für alle Zeiger gleich.
Also:
float[n][3]
float[n]
byte[n][4]
float[n][2]
short[n]Ich möchte nun alle Elemente dieser Arrays in eine Datei speichern.
Da ich nicht für jeden Array Typ eine eigene Funktion schreiben sollte, möchte ich eine template Funktion benutzen.Tja, die Frage ist nun wie ich dies machen sollte.
-
PS.: Die Arrays sollen einzeln gespeichert werden, also nicht alle auf einmal.
-
template<class T, int i, int j> void foo(T bar[i][j]) { ... }
-
Noch mal genauer:
Im Speicher liegen 3xfloat hintereinander.
Darauf habe ich einen void-Zeiger.
Dies 3xfloat sind aber nur ein Element.
Nach n-Bytes kommen wieder 3xfloat.
Nach 2*n-Bytes kommen wieder 3xfloat.
Diese Elemente gibt es x mal.Das Ganze gibt es nicht nur mit 3xfloat, sonder noch in 4 weiteren Formaten(wie gezeigt) und deren Elementeanzahl ist immer x.
Eine Template Funktion soll fähig sein alle Elemente des jeweiligen Typs in einer Datei zu speichern.
Die Frage ist nun wie ich die Typenunterscheidung hinbekomme.Danke für all die Mühe!
-
Und um noch einmal zu sagen warum ich glaub das dies nicht hilft:
Michael E. schrieb:
Wenn ich dich richtig versteh, dann ist es immer noch sowas:
template<class T, int i> void foo(T bar[i]) { ... }
Hier würde man ja ein Array des Types T erstellen.
Ich habe aber nur den Zeiger auf das erste Element.
Und die möglichen Typen auf die der Zeiger zeigt, sind:float[3]
float
byte[4]
float[2]
short
-
Ich versteh immer noch nicht, wieso meine zwei Funktionen nicht helfen. Wie groß ist bei dir n?
-
Michael E. schrieb:
Ich versteh immer noch nicht, wieso meine zwei Funktionen nicht helfen.
Ich will an die Template Funktion doch nur einen Zeiger übergeben.
Der Typ worauf der Zeiger zeigt ist einer von denen:float[3]
float
byte[4]
float[2]
shortDein Template-Vorschlag würde bei der Übergabe eines Zeiger aber eine Array von Zeigern als Parameter annehmen, oder?
Wie groß ist bei dir n?
Irgend eine Zahl, z.B. 40.
-
Um das eigentliche Problem auf den Nenner zu bringen:
Wie kann ich am einfachsten einen Zeiger erstellen, der auf ein Objekt z.B. vom Typ float[3] zeigt?
Denn wenn ich folgendes mache...
float blah[3];
... ist blah ja ein Zeiger auf ein Objekt des Types float, nicht aber float[3] - so wie ich es brauche.
Wenn ich wie vorgeschlagen folgendes mache:
template<class T, int i> void foo(T bar[i]) { ... }
... ist der Parameter ja ein Array aus i Elementen des Types T.
Das bringt mir nichts weil ich ja einen Zeiger übergeben will und gleichzeitig den Typ (also z.B. float[3]) für das Template übermitteln muss.
-
sqrt(-1) schrieb:
Michael E. schrieb:
Ich versteh immer noch nicht, wieso meine zwei Funktionen nicht helfen.
Ich will an die Template Funktion doch nur einen Zeiger übergeben.
Der Typ worauf der Zeiger zeigt ist einer von denen:float[3]
float
byte[4]
float[2]
shortDein Template-Vorschlag würde bei der Übergabe eines Zeiger aber eine Array von Zeigern als Parameter annehmen, oder?
template<class T, int i> void foo(T bar[i]) // bekommt ein eindimensionales Array, also sozusagen T* { ... }
template<class T, int i, int j> void foo(T bar[i][j]) // erhält ein zweidimensionales Array, also sozusagen T** { ... }
Wie groß ist bei dir n?
Irgend eine Zahl, z.B. 40.[/quote]
Damit ist mir nicht geholfen. Ist das irgendeine ganz rein zufällige Zahl? Ich glaub eher nicht.
-
Also es funktioniert z.B. folgendes:
struct _ElementTypA { float Element[3]; }*ElementTypA; struct _ElementTypB { float Element; }*ElementTypB; ElementTypA = (_ElementTypA*)getVoidPointer(); ElementTypB = (_ElementTypB*)getVoidPointer(); schreibeArray(ElementTypA); schreibeArray(ElementTypB); template <class _ElementTyp> void schreibeArray(_ElementTyp* ElementTyp) { ElementType ArrayPuffer[100]; for(int i=0; i<100; i++) { ArrayPuffer[i] = *(ArrayPointer+i); } ... }
Strukturen sind wirken da jedoch ziemlich umständlich.
Gibt es da nicht etwas "schöneres"?
-
Achja, habe das oben gezeigt nicht getestet, der Compiler nimmt es jedoch an.
-
Wenn dein Compiler es schluckt, kann ich ja Schreibfehler ausschließen.
Was ist ElementType? Wie sieht getVoidPointer aus?
-
Ups, habe falschen Code genommen.
So sieht er richtig aus:struct _ElementTypA { float Element[3]; }*ElementTypA; struct _ElementTypB { float Element; }*ElementTypB; ElementTypA = (_ElementTypA*)getVoidPointer(); ElementTypB = (_ElementTypB*)getVoidPointer(); schreibeArray(ElementTypA); schreibeArray(ElementTypB); template <class _ElementTyp> void schreibeArray(_ElementTyp* ElementTyp) { ElementTyp ArrayPuffer[100]; for(int i=0; i<100; i++) { ArrayPuffer[i] = *(ArrayPointer+i); } ... }
Also ElementTyp, und nicht ElementType.
getVoidPointer() verdeutlicht einfach das ich einen void-Zeiger zuweise.
In Wirklichkeit wird der von einer Element-Typ spezifischen Funktion übergeben.
-
Raaahhh! Schon wieder ein Tippfehler:
struct _ElementTypA { float Element[3]; }*ElementTypA; struct _ElementTypB { float Element; }*ElementTypB; ElementTypA = (_ElementTypA*)getVoidPointer(); ElementTypB = (_ElementTypB*)getVoidPointer(); schreibeArray(ElementTypA); schreibeArray(ElementTypB); template <class _ElementTyp> void schreibeArray(_ElementTyp* ElementTyp) { _ElementTyp ArrayPuffer[100]; for(int i=0; i<100; i++) { ArrayPuffer[i] = *(ArrayPointer+i); } ... }
So, jetzt sollte es stimmen.
Keine Vorschläge für eine schönere Alternative zu den Strukturen?
-
Und dein Compiler soll das da geschluckt haben? Dann fehlen mir aber noch Infos. Was is ArrayPointer? Wo verwendest du den Parameter ElementTyp in der Funktion?
-
Arrr.... ArrayPointer war auch noch ein Relikt aus meinem ursprünglichen Code
[code]
struct _ElementTypA
{
float Element[3];
}*ElementTypA;struct _ElementTypB
{
float Element;
}*ElementTypB;ElementTypA = (_ElementTypA*)getVoidPointer();
ElementTypB = (_ElementTypB*)getVoidPointer();schreibeArray(ElementTypA);
schreibeArray(ElementTypB);template <class _ElementTyp> void schreibeArray(_ElementTyp* ElementTyp)
{
_ElementTyp ArrayPuffer[100];for(int i=0; i<100; i++)
{
ArrayPuffer[i] = *(ElementTyp+i);
}
...
}[code]Ob es jetzt endlich stimmt?
-
Arrr.... ArrayPointer war auch noch ein Relikt aus meinem ursprünglichen Code
struct _ElementTypA { float Element[3]; }*ElementTypA; struct _ElementTypB { float Element; }*ElementTypB; ElementTypA = (_ElementTypA*)getVoidPointer(); ElementTypB = (_ElementTypB*)getVoidPointer(); schreibeArray(ElementTypA); schreibeArray(ElementTypB); template <class _ElementTyp> void schreibeArray(_ElementTyp* ElementTyp) { _ElementTyp ArrayPuffer[100]; for(int i=0; i<100; i++) { ArrayPuffer[i] = *(ElementTyp+i); } ... }
Ob es jetzt endlich stimmt?
-
Michael E. schrieb:
template<class T, int i> void foo(T bar[i]) { ... }
Das wird aber nicht funktionieren, wenn dann schon so
template <class T, std::size_t N> void foo(const T (&bar)[N]) { // ... }
sqrt(-1) schrieb:
Wie kann ich am einfachsten einen Zeiger erstellen, der auf ein Objekt z.B. vom Typ float[3] zeigt?
ZB so
float a[3]; float* b = a; // oder float* c = &a[0];
sqrt(-1) schrieb:
Denn wenn ich folgendes mache...
float blah[3];
... ist blah ja ein Zeiger auf ein Objekt des Types float, nicht aber float[3] - so wie ich es brauche.
Nein, blah ist schon ein 'float[3]'. Dass der Compiler dies bei Bedarf implizit in ein 'float*' umwandeln darf, ist eine andere Sache.
sqrt(-1) schrieb:
Das bringt mir nichts weil ich ja einen Zeiger übergeben will und gleichzeitig den Typ (also z.B. float[3]) für das Template übermitteln muss.
Wieso willst du einen Zeiger übergeben, wenn du den Arraytyp brauchst? Nimm oben stehende Funktion, und du hast mit 'T[N]' den Typ. Das funktioniert natürlich nicht mit dynamisch erzeugten Arrays.
Und getVoidPointer()? Brauchst du das wirklich? Sowas deutet idR auf ein schlechtes Design.
-
groovemaster schrieb:
sqrt(-1) schrieb:
Wie kann ich am einfachsten einen Zeiger erstellen, der auf ein Objekt z.B. vom Typ float[3] zeigt?
ZB so
float a[3]; float* b = a; // oder float* c = &a[0];
Wird im gezeigten Template dann auch wirklich der ein Objekt vom Typ float[3] erkannt, oder wieder nur ein einfaches float wegen der impliziten Typumformung?
sqrt(-1) schrieb:
Denn wenn ich folgendes mache...
float blah[3];
... ist blah ja ein Zeiger auf ein Objekt des Types float, nicht aber float[3] - so wie ich es brauche.
Nein, blah ist schon ein 'float[3]'. Dass der Compiler dies bei Bedarf implizit in ein 'float*' umwandeln darf, ist eine andere Sache.[/quote]
Nun, eben dies wird ja zum Problem für das was ich tun will.sqrt(-1) schrieb:
Das bringt mir nichts weil ich ja einen Zeiger übergeben will und gleichzeitig den Typ (also z.B. float[3]) für das Template übermitteln muss.
Wieso willst du einen Zeiger übergeben, wenn du den Arraytyp brauchst? Nimm oben stehende Funktion, und du hast mit 'T[N]' den Typ. Das funktioniert natürlich nicht mit dynamisch erzeugten Arrays.
Und getVoidPointer()? Brauchst du das wirklich? Sowas deutet idR auf ein schlechtes Design.Nee, so eine Funktion gibt es in meinem Code nicht.
Habe sie nur geschrieben um die Zuweisung samt Typkonvertierung zeigen zu können.Und ich brauche ja nicht nur den Typ, sondern den Typ und den Pointer.
Der oben gezeigt Code scheint dies ja zu machen (zumindest nimmt der Compiler dies an).Die Frage von mir ist nun ob man keine schönere Alternative zu den blöden Strukturen hat, zumal ja nur ein einzigstes Array der Inhalt ist.