Include-Wächter-Namen
-
Kein Bibliotheksentwickler der Welt ist auf solche Scherze vorbereitet. Die Standardheader dürfen sich beliebig gegenseitig einbinden, und auch Drittbibliotheken ändern ihre Headerabhängigkeiten ohne Vorwarnung. Code, dessen Struktur davon abhängt, ob optionale Header eingebunden worden sind, wird von Compiler zu Compiler und Bibliotheksversion zu Bibliotheksversion unterschiedliche Ergebnisse liefern.
Dazu kommt, dass es ausgesprochen schlechter Stil ist, wenn
#include "dein_header.hh" #include <vector>sich anders verhält als
#include <vector> #include "dein_header.hh"Jetzt stell dir mal vor, dein Header wird von anderen Headern eingebunden. Der erste bindet ihn ohne die spezielle Funktion ein, der zweite verlässt sich darauf, dass sie vorhanden ist. Werden beide hintereinander eingebunden, geht der zweite (wenn er nach dem ersten eingebunden wurde) kaputt.
Wer soll denn da durchfinden?
Sofern es keinen IOC++CC gibt, von dem ich noch nichts gehört habe oder du für ein neues Buch von Jürgen Wolf ("Programmierpraktik in C++"?) recherchierst, halte ich das für ein XY-Problem. Was ist es, das du wirklich vorhast?
-
EOutOfResources schrieb:
Die zweite Methode spricht mich mehr an.
Vielen Dank
Die zweite Methode ist aber ganz schlimmer Unfug
ipsec schrieb:
PS: wenn du schon das deutsche Partizip bildest, dann bitte geincludet und nicht so ein Mischmasch.
Inkludifiziert

-
seldon schrieb:
Jürgen Wolf
*würg*
seldon schrieb:
Was ist es, das du wirklich vorhast?
Einen (auf meinen Container spezifischen) Allokator anbieten, der die Speicherverwaltung von C unterstützt. Und den braucht man eben nur, wenn man zuvor mit
malloc,callocoderreallocgearbeitet hat.
-
Na dann hast du dir hoffentlich schon eine portable Methode herausgesucht, um zu unterscheiden, ob ein Pointer vom globalen ::operator new(), einer klassenspezifischen Überladung oder von malloc() reserviert wurde

Btw, "die Speicherverwaltung von C unterstützt" ist eine etwas vage Beschreibung.
-
CStoll schrieb:
Na dann hast du dir hoffentlich schon eine portable Methode herausgesucht, um zu unterscheiden, ob ein Pointer vom globalen ::operator new(), einer klassenspezifischen Überladung oder von malloc() reserviert wurde

Der Allokator befreit nur was er auch selbst (oder eine andere Instanz mit der selben Methode) reserviert hat.
-
Und warum soll ich nich einfach
"dein_allocator.h"inkludieren dürfen, wenn ich deinen Allokator will? Auch wenn ichmallocund Konsorten sonst vielleicht gar nicht brauche? Und wenn ich den Allokator nicht will, inkludiere ich die Datei eben nicht.
-
EOutOfResources schrieb:
CStoll schrieb:
Na dann hast du dir hoffentlich schon eine portable Methode herausgesucht, um zu unterscheiden, ob ein Pointer vom globalen ::operator new(), einer klassenspezifischen Überladung oder von malloc() reserviert wurde

Der Allokator befreit nur was er auch selbst reserviert hat.
Dann brauchst du dich doch auch nicht darum kümmern, wie andere Leute ihren Speicher angefordert haben.
(btw, nur wenn jemand die <cstdlib> eingebunden hat, heißt das noch lange nicht, daß er die malloc()-Familie verwendet)
-
ipsec schrieb:
Und warum soll ich nich einfach
"dein_allocator.h"inkludieren dürfen, wenn ich deinen Allokator will?Das darfst du ja. Wenn der Allokator aus
"dein_allocator.h"eben nicht nurnewundnew[]unterstützen soll, dann schreibst du eben:#include <cstdlib> #include "dein_allocator.h"
-
CStoll schrieb:
Dann brauchst du dich doch auch nicht darum kümmern, wie andere Leute ihren Speicher angefordert haben.
Aha! Du denkst, dass ich den Allokator als Template implentiert habe und dass der Nutzer die Methode als Klassenobjekt übergibt, oder?
CStoll schrieb:
nur wenn jemand die <cstdlib> eingebunden hat, heißt das noch lange nicht, daß er die malloc()-Familie verwendet
Klar.
-
Du willst das Verhalten einer Klasse von übersetzungseinheitsspezifischen Details abhängig machen? Ich sehe Linkeralbträume voraus.
Was spricht dagegen, am Anfang des Allokatorheaders <cstdlib> einzubinden und die malloc-Variante unabhängig davon zu deklarieren, ob sie nachher benutzt wird?
-
seldon schrieb:
Du willst das Verhalten einer Klasse von übersetzungseinheitsspezifischen Details abhängig machen?
Was daran ist übersetzungseinheitsspezifisch?
seldon schrieb:
Was spricht dagegen, am Anfang des Allokatorheaders <cstdlib> einzubinden und die malloc-Variante unabhängig davon zu deklarieren, ob sie nachher benutzt wird?
Ja, direkt eigentlich nichts, aber ist das nicht ein schlechter Stil?
-
EOutOfResources schrieb:
CStoll schrieb:
Dann brauchst du dich doch auch nicht darum kümmern, wie andere Leute ihren Speicher angefordert haben.
Aha! Du denkst, dass ich den Allokator als Template implentiert habe und dass der Nutzer die Methode als Klassenobjekt übergibt, oder?
Nicht unbedingt.
Aber wenn du den Container schreibst, kannst du auch selber festlegen, wie er seinen Speicher anfordert - und die dazu passende Freigabefunktion verwenden. Da ist es egal, ob jemand anderes an anderer Stelle nun mit malloc(), new oder irgendwelchen systemspezifischen Funktionen seinen Speicher anfordert.
-
CStoll schrieb:
Aber wenn du den Container schreibst, kannst du auch selber festlegen, wie er seinen Speicher anfordert
Machen das nicht die Allokatoren?
-
EOutOfResources schrieb:
CStoll schrieb:
Aber wenn du den Container schreibst, kannst du auch selber festlegen, wie er seinen Speicher anfordert
Machen das nicht die Allokatoren?
Oder so - wichtig ist jedenfalls nur, daß die Speicherreservierung deines Allokators zu seiner eigenen Speicherfreigabe passt.
EOutOfResources schrieb:
seldon schrieb:
Du willst das Verhalten einer Klasse von übersetzungseinheitsspezifischen Details abhängig machen?
Was daran ist übersetzungseinheitsspezifisch?
Klasse 1 verwendet nur deinen Header -> der Allokator nutzt new/delete.
Klasse 2 bindet <cstdlib> und Klasse 2 ein -> der Allokator verwendet malloc()/free()
Wenn jetzt beide zusammen in einem Programm genutzt werden, hast du inkonsistentes Verhalten - und spätestens wenn Klasse 1 versucht einen Container zu zerstören, den Klasse 2 erzeugt hat, kracht es. (wenn das überhaupt durch den Linker kommt)
-
CStoll schrieb:
und spätestens wenn Klasse 1 versucht einen Container zu zerstören, den Klasse 2 erzeugt hat, kracht es. (wenn das überhaupt durch den Linker kommt)
Der Allokator ist ein Template-Argument der Containers (wie bei der STD).
-
Du wirfst immer nur sinnlose fetzen hin die zusammen keinen Sinn ergeben.
Generell klingt die Idee absolut grottig, aber es ist schwer zu sagen weil du ja keinen Ton verraetst.
-
Ich glaube, so langsam habe ich den Überblick verloren, was du überhaupt vorhast. Kannst du nochmal den Teil ab "der die Speicherverwaltung von C unterstützt" erläutern?
(PS: Wenn ich mir deine letzten Threads so ansehe - du scheinst etwas zu kompliziert zu denken :D)
-
Mein eigener Container erwartet als zweites Template-Argument einen Allokator. Und ich implentiere zwei Standard-Allokatoren,
new/deleteundmalloc/free. Es kann ein beliebiger Typ als Allokator an den Container übergeben werden (der die Bestimmungen erfüllt). Der Allokator, welchermallocundfreebenutzt, ist natürlich nur benutzbar, wenn der Header<cstdlib>inkludiert wurde (logisch, oder?). Nun könnte ich folgende Schritte unternehmen:- Der Allokator ist nur definiert, wenn
<cstdlib>bereits inkludiert wurde (meine eigentliche Idee). - Der Allokator ist immer definiert, denn
<cstdlib>wird im Allokator-Header inkludiert. - Der Allokator ist nur definiert, wenn ein bestimmtes Makro definiert ist (z.B. LIB_USE_MALLOC) und dann wird dann ggf
<cstdlib>inkludieret.
- Der Allokator ist nur definiert, wenn
-
Ich wäre für Variante 2. Alternativ könntest du die Definition des malloc-Allokators auch in einen eigenen Header auslagern (inklusive des #include <cstdlib>), den der Nutzer bei Bedarf einbinden kann.
-
Hör mal das ist eigentlich kein Problem. Die zweite Variante ist üblich!
Und niemand der deine Lib verwenden wird, hätte wahrscheinlich ein Problem das
cstdlib eingebunden ist!