Arrayinformation über Funktion beibehalten
-
Okay, folgendes:
template<typename T> inline size_t sizeof_a(T arr[]) { return sizeof(arr) / sizeof(arr[0]); } #define SIZEOF_A(x) (sizeof(x) / sizeof((x)[0])) int abc[100]; cout << sizeof_a(abc) << endl; // 1 cout << SIZEOF_A(abc) << endl; // 1001. funktioniert nicht wie erwartet.
2. schon.Also, ich möchte die Array Größe ermitteln lassen. Dass das zweite funktioniert ist klar, liefert auch 100 als Ergebnis. Aber das erste liefert nur 1. Warum?
sizeof(arr) liefert 4, da arr in diesem Fall als Pointer interpretiert wird. sizeof(arr[0]) ist ebenfalls 4 (zumindest, wenn sizeof(int) == 4) und daraus resultiert 1.Frage: Gibt es eine Möglichkeit, die Arrayeigentschaft beizubehalten, sodass sizeof(arr) in der Funktion 400 ergibt und damit 100 als Ergebnis liefert?
Dankö!
-
Nein, gibt es nicht. Darum nimmt man stattdessen normalerweise std::vector und std::vector::size().
-
array schrieb:
Frage: Gibt es eine Möglichkeit, die Arrayeigentschaft beizubehalten, sodass sizeof(arr) in der Funktion 400 ergibt und damit 100 als Ergebnis liefert?
Dankö!
Wenn du dein Array zum einziges Mitglied einer struct machst gehts (sizeof struct/sizeof T).

-
Hallo
Das Template sollte so aussehen
template<class T, std::size_t N> std::size_t countem(T (&)[N]) { return N; }Aber wie schon gesagt, ist das nicht wirklich gut. Spätestens wenn es um Pointer/Referenzen auf Arrays geht, versagt das.
bis bald
akari
-
akari schrieb:
template<class T, std::size_t N> std::size_t countem(T (&)[N]) { return N; }Genau das habe ich irgendwo schonmal gesehen (irgenwie in Zusammenhang mit boost). Aber ich habe das nicht wirklich verstanden.
Kann man das irgendwie genauer erklären, weil das ja doch ein wenig kryptisch ausschaut.
-
Das ist eine Template-Funktion deren Template-Parameter der Typ und die Größe des Arrays sind.
T (&)[N]ist eine Referenz auf ein Array der Größe N von Elementen des Typs T. Ohne die Klammern wäre es ein Array von Referenzen (was bekanntlich nicht geht). Diese Funktion gibt die Größe N zurück. Durch die Deduktion der Template-Parameter (will heissen bei Angabe der Funktionsargumente ist der Compiler selbst in der Lage die Vorlagenargumente zu ermitteln) expandiert das ganze z.B. so:
Typ array[100]; size_t length = countem(array); // expandiert zu size_t length = countem<Typ, 100>(array);Im besten Fall (inline) expandiert das ganze dann zu "100". Ein großer Vorteil dieser Methode ist (bitte korrigieren falls das durch den Standard nicht gedeckt sein sollte, meine Compiler handeln das alle so), dass das (im Gegensatz zum Makro) nicht compiliert, wenn der Arraytyp unvollständig ist oder ein Zeigertyp übergeben wird.
Und was schöner aussieht darf jeder selbst entscheiden

std::copy( array, array + countem( array ), ziel ); std::copy( array, array + sizeof( array ) / sizeof( array[ 0 ] ), ziel );
-
Ich würde für Arrays zwar auch eher einen passenden Container empfehlen. Wenn man es aber unbedingt braucht, würde ich eher zu einem Makro greifen.
#define lengthof(x) (sizeof(x) / sizeof(*x))Das kommt sizeof am nächsten, da das Ergebnis ein konstanter Ausdruck ist. Dies ist bei der Funktionsversion nicht der Fall, und für mich damit für eine generelle Verwendung unbrauchbar. Zwar fehlt dem Makro die Sicherheit bei Zeigerargumenten und UDTs, vielleicht kann man aber auch das noch irgendwie hinbekommen. Wäre alles kein Problem, wenn es ein Schlüsselwort typeof geben würde, was ja leider (noch) nicht der Fall ist.

-
groovemaster schrieb:
Ich würde für Arrays zwar auch eher einen passenden Container empfehlen. Wenn man es aber unbedingt braucht, würde ich eher zu einem Makro greifen.
#define lengthof(x) (sizeof(x) / sizeof(*x))Das kommt sizeof am nächsten, da das Ergebnis ein konstanter Ausdruck ist.
Das kommt der sizeof()-Lösung nicht nur nahe, das ist die sizeof-Lösung (mit all ihren Problemen und Einschränkungen). Und hier geht es gerade darum, diese Probleme zu umgehen.
PS: Es gibt übrigens ein typeof - das nennt sich "typeid" (und ist an der Stelle leider nicht besonders hilfreich)
-
array schrieb:
...
template<typename T> inline size_t sizeof_a(T arr[]) { return sizeof(arr) / sizeof(arr[0]); }...
Hi,
ich meine, mich daran zu erinnern, dass ein Arrayparameter beim Funktionsaufruf immer zu einem Zeiger degeneriert, so dass "sizeof(arr)" nur "die Länge einer Zeigervariable" gibt.
Bei einem #define (was ja eine reine Textersetzung ist) passiert das nicht; deswegen funktioniert der obige Mechanismus nur mit #define und nicht mit Funktionen (selbst wenn sie aus einem template intantiiert wurden).Bei akaris Version "zieht" auch nicht direkt die "Parameterbehandlung bei Funktionen", sondern die "automatische Spezialisierungsregel bei Templates", weswegen das klappt.
-- So jedenfalls meine Vermutung --Gruß,
Simon2.
-
CStoll schrieb:
Es gibt übrigens ein typeof - das nennt sich "typeid"
Naja, das sind aber schon noch zwei ziemlich unterschiedliche Sachen. Zumindest nach dem, was ich unter typeof verstehe. Und wie du schon sagtest, typeid nützt einem hier nichts.
-
in der aktuellen version vom gcc gibt's typeof und das funtkioniert auch. Ziemlich praktisch.