Beim Refactoring von Code und dem Entfernen all dieser # Definitionen, die uns jetzt beigebracht werden zu hassen, stieß ich auf diese Schönheit, die zur Berechnung der Anzahl von Elementen in einer Struktur verwendet wurde:
%Vor%Sehr nützlich wie es ist, aber kann es in eine Inline-Funktion oder eine Vorlage umgewandelt werden?
OK, ARRAYSIZE wäre ein besserer Name, aber das ist Legacy-Code (keine Ahnung, wo es herkommt, es ist mindestens 15 Jahre alt), also habe ich es eingefügt wie es ist.
Beim Refactoring von Code und dem Entfernen all dieser # Definitionen, die uns jetzt beigebracht werden zu hassen, stieß ich auf diese Schönheit, die zur Berechnung der Anzahl von Elementen in einer Struktur verwendet wurde:
%Vor%Sehr nützlich wie es ist, aber kann es in eine Inline-Funktion oder eine Vorlage umgewandelt werden?
OK, ARRAYSIZE wäre ein besserer Name, aber das ist Legacy-Code (keine Ahnung, wo es herkommt, es ist mindestens 15 Jahre alt), also habe ich es eingefügt wie es ist.
Das Makro hat einen sehr irreführenden Namen - der Ausdruck im Makro gibt die Anzahl der Elemente in einem Array zurück, wenn der Name eines Arrays als Makroparameter übergeben wird.
Bei anderen Typen erhalten Sie etwas mehr oder weniger bedeutungsloses, wenn der Typ ein Zeiger ist oder Sie einen Syntaxfehler bekommen.
Normalerweise wird das Makro so benannt wie NUM_ELEMENTS () oder etwas, um seine wahre Nützlichkeit anzuzeigen. Es ist nicht möglich, das Makro durch eine Funktion in C zu ersetzen, aber in C ++ kann eine Vorlage verwendet werden.
Die Version, die ich verwende, basiert auf dem Code in winnt.h von Microsoft (bitte teilen Sie mir mit, ob das Veröffentlichen dieses Snippets über den fairen Gebrauch hinausgeht):
%Vor%Auch Matthew Wilsons Buch "Imperfect C ++" hat eine schöne Behandlung dessen, was hier vor sich geht (Abschnitt 14.3 - Seite 211-213 - Arrays und Zeiger - dimensionof ()).
Ihr Makro ist falsch benannt, es sollte ARRAYSIZE genannt werden. Es wird verwendet, um die Anzahl der Elemente in einem Array zu ermitteln, deren Größe zur Kompilierungszeit festgelegt ist. Hier ist ein Weg, wie es funktionieren kann:
char foo [128]; // In Wirklichkeit würdest du habe etwas konstant oder konstant Ausdruck als Array-Größe.
für (vorzeichenlos i = 0; i & lt; STRUKTUR ( foo); ++ i) {}
Es ist etwas spröde zu benutzen, weil Sie diesen Fehler machen können:
char * foo = neues Zeichen [128];
für (vorzeichenlos i = 0; i & lt; STRUKTUR ( foo); ++ i) {}
Sie werden jetzt für i = 0 zu & lt; 1 und reiß dein Haar aus.
Der Typ einer Template-Funktion wird automatisch abgeleitet, im Gegensatz zu dem einer Template-Klasse. Sie können es noch einfacher verwenden:
%Vor%Aber ich stimme zu, es funktioniert nicht für Strukturen: Es funktioniert für Arrays. Also würde ich es eher als Arraygröße bezeichnen:)
Die Lösung von KTC ist zwar sauber, kann aber nicht zur Kompilierzeit verwendet werden und ist vom Compiler abhängig Optimierung, um Code-Bloat- und Funktionsaufruf-Overhead zu verhindern.
Man kann die Array-Größe mit einer Compile-Time-Only-Metafunktion ohne Laufzeitkosten berechnen. BCS war auf dem richtigen Weg, aber diese Lösung ist falsch.
Hier ist meine Lösung:
%Vor%mit Testcode (mit Boost.StaticAssert , um die Kompilierzeit zu demonstrieren -nur Verwendung):
%Vor%Diese Lösung weist bei der Kompilierung keine Array-Typen zurück, so dass sie nicht durch Zeiger verwechselt werden, wie dies bei der Makroversion der Fall ist.
Simplfying @ KTC's, da wir die Größe des Arrays im Template-Argument haben:
%Vor%Nachteil ist, dass Sie eine Kopie davon in Ihrer Binärdatei für jede Typname, Größenkombination haben werden.
Bearbeiten: Aus Dougs Code
%Vor%Mir wurde gesagt, dass der zweite nicht funktioniert. OTOH etwas wie es sollte machbar sein, ich benutze nur C ++ nicht genug, um es zu beheben.
Eine Seite mit C ++ - (und D-) Vorlagen für die Kompilierzeit
Ich bevorzuge die von [BCS] vorgeschlagene Enum-Methode (in Kann dieses Makro in eine Funktion umgewandelt werden? )
Dies liegt daran, dass Sie es dort verwenden können, wo der Compiler eine Kompilierzeitkonstante erwartet. Die aktuelle Version der Sprache lässt Sie keine Funktionsergebnisse für Kompilierzeitkonstraste verwenden, aber ich glaube, das kommt in der nächsten Version des Compilers:
Das Problem mit dieser Methode ist, dass es keinen Kompilierzeitfehler erzeugt, wenn es mit einer Klasse verwendet wird, die den '*' Operator überladen hat (Details siehe unten).
Leider kompiliert die von 'BCS' bereitgestellte Version nicht so wie erwartet, also hier ist meine Version:
%Vor%Ich glaube nicht, dass das wirklich die Anzahl der Elemente in einer Struktur berechnet. Wenn die Struktur gepackt ist und Sie Objekte verwenden, die kleiner sind als die Zeigergröße (z. B. char auf einem 32-Bit-System), sind die Ergebnisse falsch. Wenn die Struktur eine Struktur enthält, irren Sie sich auch!
Ja, es kann eine Vorlage in C ++ gemacht werden
%Vor%zu verwenden:
%Vor%Siehe BCS Beitrag oben oder unten über eine coole Möglichkeit, dies mit einer Klasse zur Kompilierzeit zu tun, indem Sie eine leichte Template-Metaprogrammierung verwenden.
Wie John McG's Antwort, aber
Nachteil ist, dass Sie eine Kopie davon in Ihrer Binärdatei für jede Kombination von Typname und Größe haben werden.
Aus diesem Grund sollten Sie eine Inline Vorlagenfunktion erstellen.
xtofl hat die richtige Antwort, um eine Array-Größe zu finden. Zum Ermitteln der Größe einer Struktur sollte kein Makro oder Template benötigt werden, da sizeof () gut funktionieren sollte.
Ich stimme dem Präprozessor zu, ist böse , aber es gibt Gelegenheiten, wo es ist ist das kleinste Übel der Alternativen .
Windows-spezifisch:
Das Makro %code% wird vom CRT genau für diesen Zweck geliefert.
Beantwortete im Detail hier: Array-Größenbestimmung Teil 1 und hier: Array-Größenbestimmung Teil 2 .
Für C99-artige Arrays variabler Länge scheint es, dass der reine Makro-Ansatz (sizeof (arr) / sizeof (arr [0])) der einzige ist, der funktioniert.
Keiner hat bisher einen portablen Weg vorgeschlagen, um die Größe eines Arrays zu erhalten, wenn Sie nur eine Instanz eines Arrays und nicht seinen Typ haben. (typeof und _countof sind nicht tragbar, können also nicht verwendet werden.)
Ich würde es folgendermaßen machen:
%Vor%Ich habe das Konstrukt in ein Makro eingepackt, um eine anständige Syntax zu erhalten. Wenn Sie es loswerden wollen, ist Ihre einzige Option, die Ersetzung manuell zu tun.
Keiner hat bisher einen portablen Weg vorgeschlagen, um die Größe eines Arrays zu erhalten, wenn Sie nur eine Instanz eines Arrays und nicht seinen Typ haben. (typeof und _countof sind nicht tragbar, können also nicht verwendet werden.)
Ich würde es folgendermaßen machen:
%Vor%Ich habe das Konstrukt in ein Makro eingepackt, um eine anständige Syntax zu erhalten. Wenn Sie es loswerden wollen, ist Ihre einzige Option, die Ersetzung manuell zu tun.
Die Lösung von KTC ist zwar sauber, kann aber nicht zur Kompilierzeit verwendet werden und ist vom Compiler abhängig Optimierung, um Code-Bloat- und Funktionsaufruf-Overhead zu verhindern.
Man kann die Array-Größe mit einer Compile-Time-Only-Metafunktion ohne Laufzeitkosten berechnen. BCS war auf dem richtigen Weg, aber diese Lösung ist falsch.
Hier ist meine Lösung:
%Vor%mit Testcode (mit Boost.StaticAssert , um die Kompilierzeit zu demonstrieren -nur Verwendung):
%Vor%Diese Lösung weist bei der Kompilierung keine Array-Typen zurück, so dass sie nicht durch Zeiger verwechselt werden, wie dies bei der Makroversion der Fall ist.
Das Makro hat einen sehr irreführenden Namen - der Ausdruck im Makro gibt die Anzahl der Elemente in einem Array zurück, wenn der Name eines Arrays als Makroparameter übergeben wird.
Bei anderen Typen erhalten Sie etwas mehr oder weniger bedeutungsloses, wenn der Typ ein Zeiger ist oder Sie einen Syntaxfehler bekommen.
Normalerweise wird das Makro so benannt wie NUM_ELEMENTS () oder etwas, um seine wahre Nützlichkeit anzuzeigen. Es ist nicht möglich, das Makro durch eine Funktion in C zu ersetzen, aber in C ++ kann eine Vorlage verwendet werden.
Die Version, die ich verwende, basiert auf dem Code in winnt.h von Microsoft (bitte teilen Sie mir mit, ob das Veröffentlichen dieses Snippets über den fairen Gebrauch hinausgeht):
%Vor%Auch Matthew Wilsons Buch "Imperfect C ++" hat eine schöne Behandlung dessen, was hier vor sich geht (Abschnitt 14.3 - Seite 211-213 - Arrays und Zeiger - dimensionof ()).
Ihr Makro ist falsch benannt, es sollte ARRAYSIZE genannt werden. Es wird verwendet, um die Anzahl der Elemente in einem Array zu ermitteln, deren Größe zur Kompilierungszeit festgelegt ist. Hier ist ein Weg, wie es funktionieren kann:
char foo [128]; // In Wirklichkeit würdest du habe etwas konstant oder konstant Ausdruck als Array-Größe.
für (vorzeichenlos i = 0; i & lt; STRUKTUR ( foo); ++ i) {}
Es ist etwas spröde zu benutzen, weil Sie diesen Fehler machen können:
char * foo = neues Zeichen [128];
für (vorzeichenlos i = 0; i & lt; STRUKTUR ( foo); ++ i) {}
Sie werden jetzt für i = 0 zu & lt; 1 und reiß dein Haar aus.
Der Typ einer Template-Funktion wird automatisch abgeleitet, im Gegensatz zu dem einer Template-Klasse. Sie können es noch einfacher verwenden:
%Vor%Aber ich stimme zu, es funktioniert nicht für Strukturen: Es funktioniert für Arrays. Also würde ich es eher als Arraygröße bezeichnen:)
Bearbeiten: Aus Dougs Code
%Vor%Mir wurde gesagt, dass der zweite nicht funktioniert. OTOH etwas wie es sollte machbar sein, ich benutze nur C ++ nicht genug, um es zu beheben.
Eine Seite mit C ++ - (und D-) Vorlagen für die Kompilierzeit
Ich bevorzuge die von [BCS] vorgeschlagene Enum-Methode (in Kann dieses Makro in eine Funktion umgewandelt werden? )
Dies liegt daran, dass Sie es dort verwenden können, wo der Compiler eine Kompilierzeitkonstante erwartet. Die aktuelle Version der Sprache lässt Sie keine Funktionsergebnisse für Kompilierzeitkonstraste verwenden, aber ich glaube, das kommt in der nächsten Version des Compilers:
Das Problem mit dieser Methode ist, dass es keinen Kompilierzeitfehler erzeugt, wenn es mit einer Klasse verwendet wird, die den '*' Operator überladen hat (Details siehe unten).
Leider kompiliert die von 'BCS' bereitgestellte Version nicht so wie erwartet, also hier ist meine Version:
%Vor%Ich glaube nicht, dass das wirklich die Anzahl der Elemente in einer Struktur berechnet. Wenn die Struktur gepackt ist und Sie Objekte verwenden, die kleiner sind als die Zeigergröße (z. B. char auf einem 32-Bit-System), sind die Ergebnisse falsch. Wenn die Struktur eine Struktur enthält, irren Sie sich auch!
xtofl hat die richtige Antwort, um eine Array-Größe zu finden. Zum Ermitteln der Größe einer Struktur sollte kein Makro oder Template benötigt werden, da sizeof () gut funktionieren sollte.
Ich stimme dem Präprozessor zu, ist böse , aber es gibt Gelegenheiten, wo es ist ist das kleinste Übel der Alternativen .
Beantwortete im Detail hier: Array-Größenbestimmung Teil 1 und hier: Array-Größenbestimmung Teil 2 .
Für C99-artige Arrays variabler Länge scheint es, dass der reine Makro-Ansatz (sizeof (arr) / sizeof (arr [0])) der einzige ist, der funktioniert.
Tags und Links macros c++ c-preprocessor