Include-Wächter-Namen
-
ipsec schrieb:
Man inkludiert ihn einfach und bei Bedarf springt der Include-Guard an (?)
Und wenn ich eine Funktion oder eine Klasse nur dann anbiete, wenn ein bestimmter Header geincludet wurde?
-
Da gibt es mehrere übliche Vorgehensweisen:
- Die entsprechenden Funktonen in einen eigenen Header packen, welcher den abhängigen Header inkludiert und welchen der Nutzer nur bei Bedarf mit inkludiert. Sollten die Funktionen keine freien Funktionen sein, werden sie zu solchen gemacht.
- oder - - Wenn der Nutzer die Funktionen möchte, muss er ein Makro wie
MEINE_LIB_USE_SPECIAL_FUNCTIONSdefinieren bevor er einen Bibliotheksheader inkludiert, nur bei Existens dieses Makros wird der abhängige Header inkludiert und die Funktionen zur Verfügung gestellt
Selbst wenn man die Namen der Inkludeguards wüsste, halte ich deinen Weg für schlecht. Ein zufällig inkludierter Header ändert dann plötzlich die Semantik des Programms bzw. es gibt keinen Bezug zwischen dem Header und der Bibliothek.
Als Nutzer muss ich dann womöglich bei dem Include einen Kommentar schreiben, dass ich das nur wegen LibX mache, ansonsten wird der eventuell mal später entfernt, weil ich daraus nichts nutze. Wenn die Library den braucht, muss sie ihn selbst inkludieren, wenn es optional ist, muss ich diese Entscheidung explizit treffen können (üblicherweise mit den oben genannten Möglichkeiten). Alles andere ist sehr wenig intuitiv (ich erinnere mich an SeppJs Kommentar zur Benutzbarkeit deiner Bibliothek).
- Die entsprechenden Funktonen in einen eigenen Header packen, welcher den abhängigen Header inkludiert und welchen der Nutzer nur bei Bedarf mit inkludiert. Sollten die Funktionen keine freien Funktionen sein, werden sie zu solchen gemacht.
-
Die zweite Methode spricht mich mehr an.
Vielen Dank
-
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)