vlib
-
GPC schrieb:
allerdings müsste ich mir erstmal deine vhlib genau ansehen, wie sie aufgebaut ist, dein Design, entsprechende Konventionen usw.
template<typename Iterator> void sort(Iterator begin,Iterator end);
allerdings sofort probleme, denn die iteratoren können noch nicht zum beispiel op+(Iterartir,Size). das müßte dann nachgerüctet werden.
Dauert dir aber wohl zu lange, bis ich da fertig wär.
kann man nicht wissen. ich brauche noch keinen. wenn ich einen brauche, schreib ich halt einen. wenn du vorher einen hast, sag bescheid.
-
mkdir .outMakefile echo keep > .outMakefile/keep g++ -Wall -Werror -pipe -fno-rtti -O3 -s -DNDEBUG -fomit-frame-pointer -ffast-math -fno-enforce-eh-specs -fmerge-all-constants -c -o .outMakefile/assert.o -MD assert.cpp g++ -Wall -Werror -pipe -fno-rtti -O3 -s -DNDEBUG -fomit-frame-pointer -ffast-math -fno-enforce-eh-specs -fmerge-all-constants -c -o .outMakefile/credits.o -MD credits.cpp g++ -Wall -Werror -pipe -fno-rtti -O3 -s -DNDEBUG -fomit-frame-pointer -ffast-math -fno-enforce-eh-specs -fmerge-all-constants -c -o .outMakefile/FileReader.o -MD FileReader.cpp g++ -Wall -Werror -pipe -fno-rtti -O3 -s -DNDEBUG -fomit-frame-pointer -ffast-math -fno-enforce-eh-specs -fmerge-all-constants -c -o .outMakefile/FileWriter.o -MD FileWriter.cpp g++ -Wall -Werror -pipe -fno-rtti -O3 -s -DNDEBUG -fomit-frame-pointer -ffast-math -fno-enforce-eh-specs -fmerge-all-constants -c -o .outMakefile/iostream.o -MD iostream.cpp g++ -Wall -Werror -pipe -fno-rtti -O3 -s -DNDEBUG -fomit-frame-pointer -ffast-math -fno-enforce-eh-specs -fmerge-all-constants -c -o .outMakefile/main.o -MD main.cpp g++ -Wall -Werror -pipe -fno-rtti -O3 -s -DNDEBUG -fomit-frame-pointer -ffast-math -fno-enforce-eh-specs -fmerge-all-constants -c -o .outMakefile/os.o -MD os.cpp g++ -Wall -Werror -pipe -fno-rtti -O3 -s -DNDEBUG -fomit-frame-pointer -ffast-math -fno-enforce-eh-specs -fmerge-all-constants -c -o .outMakefile/prime.o -MD prime.cpp g++ -Wall -Werror -pipe -fno-rtti -O3 -s -DNDEBUG -fomit-frame-pointer -ffast-math -fno-enforce-eh-specs -fmerge-all-constants -c -o .outMakefile/PrimeGenerator.o -MD PrimeGenerator.cpp In file included from Array.hpp:5, from PrimeGenerator.hpp:4, from PrimeGenerator.cpp:1: RawArray.hpp: In member function `RawObject& RawArrayMemory<RawObject, size, onHeap>::operator[](Size)': RawArray.hpp:19: Fehler: es gibt keine Argumente für »ASSERT«, die von einem Templateparameter abhängen, weshalb eine Deklaration von »ASSERT« verfügbar sein muss RawArray.hpp:19: Fehler: (mit »-fpermissive« wird G++ den Code akzeptieren, aber die Verwendung eines nicht deklarierten Namens ist veraltet) RawArray.hpp: In member function `RawObject& RawArrayMemory<RawObject, size, true>::operator[](Size)': RawArray.hpp:39: Fehler: es gibt keine Argumente für »ASSERT«, die von einem Templateparameter abhängen, weshalb eine Deklaration von »ASSERT« verfügbar sein muss RawArray.hpp: In member function `RawObject& RawArrayMemory<RawObject, 0ul, true>::operator[](Size)': RawArray.hpp:62: Fehler: es gibt keine Argumente für »ASSERT«, die von einem Templateparameter abhängen, weshalb eine Deklaration von »ASSERT« verfügbar sein muss RawArray.hpp: In member function `Data& RawArrayImpl<Data, size, onHeap>::operator[](Size)': RawArray.hpp:143: Fehler: es gibt keine Argumente für »ASSERT«, die von einem Templateparameter abhängen, weshalb eine Deklaration von »ASSERT« verfügbar sein muss RawArray.hpp: In member function `Data& RawArrayImpl<Data, size, onHeap>::operator[](Size) [with Data = Stack<PrimeGenerator::Runner>, long unsigned int size = 16384u, bool onHeap = false]': Array.hpp:18: instantiated from `Data& ArrayImpl<Data, size, onHeap>::operator[](Size) [with Data = Stack<PrimeGenerator::Runner>, long unsigned int size = 16384u, bool onHeap = false]' PrimeGenerator.hpp:71: instantiated from here RawArray.hpp:143: Fehler: »ASSERT« nicht deklariert (erste Verwendung dieser Funktion) RawArray.hpp:143: Fehler: (Jeder nicht deklarierte Bezeichner wird nur einmal für jede Funktion, in der er vorkommt, gemeldet.) swap.hpp: In function `void swap(Data&, Data&) [with Data = Size]': Stack.hpp:52: instantiated from `void swap(Stack<PrimeGenerator::Runner>&, Stack<PrimeGenerator::Runner>&)' PrimeGenerator.hpp:95: instantiated from here swap.hpp:6: Fehler: Abfrage des Elementes »swap« in »a«, das vom Nicht-Klassentyp »long unsigned int« ist RawArray.hpp: In member function `Data& RawArrayImpl<Data, size, onHeap>::operator[](Size) [with Data = PrimeGenerator::Runner, long unsigned int size = 255ul, bool onHeap = false]': Stack.hpp:36: instantiated from `Data& Stack<Data>::peek() const [with Data = PrimeGenerator::Runner]' PrimeGenerator.hpp:97: instantiated from here RawArray.hpp:143: Fehler: »ASSERT« nicht deklariert (erste Verwendung dieser Funktion) RawArray.hpp: In member function `Data& RawArrayImpl<Data, size, onHeap>::operator[](Size) [with Data = Stack<BigPrimeGenerator::Runner>, long unsigned int size = 1048576u, bool onHeap = false]': Array.hpp:18: instantiated from `Data& ArrayImpl<Data, size, onHeap>::operator[](Size) [with Data = Stack<BigPrimeGenerator::Runner>, long unsigned int size = 1048576u, bool onHeap = false]' PrimeGenerator.hpp:132: instantiated from here RawArray.hpp:143: Fehler: »ASSERT« nicht deklariert (erste Verwendung dieser Funktion) RawArray.hpp: In member function `Data& RawArrayImpl<Data, size, onHeap>::operator[](Size) [with Data = BigPrimeGenerator::Runner, long unsigned int size = 255ul, bool onHeap = false]': Stack.hpp:36: instantiated from `Data& Stack<Data>::peek() const [with Data = BigPrimeGenerator::Runner]' PrimeGenerator.hpp:158: instantiated from here RawArray.hpp:143: Fehler: »ASSERT« nicht deklariert (erste Verwendung dieser Funktion) RawArray.hpp: In member function `RawObject& RawArrayMemory<RawObject, size, onHeap>::operator[](Size) [with RawObject = AlignedMemory<16ul, 8ul>, long unsigned int size = 16384u, bool onHeap = false]': RawArray.hpp:144: instantiated from `Data& RawArrayImpl<Data, size, onHeap>::operator[](Size) [with Data = Stack<PrimeGenerator::Runner>, long unsigned int size = 16384u, bool onHeap = false]' Array.hpp:18: instantiated from `Data& ArrayImpl<Data, size, onHeap>::operator[](Size) [with Data = Stack<PrimeGenerator::Runner>, long unsigned int size = 16384u, bool onHeap = false]' PrimeGenerator.hpp:71: instantiated from here RawArray.hpp:19: Fehler: »ASSERT« nicht deklariert (erste Verwendung dieser Funktion) RawArray.hpp: In member function `Data& RawArrayImpl<Data, size, onHeap>::operator[](Size) [with Data = u32, long unsigned int size = 514ul, bool onHeap = false]': Array.hpp:18: instantiated from `Data& ArrayImpl<Data, size, onHeap>::operator[](Size) [with Data = u32, long unsigned int size = 514ul, bool onHeap = false]' BitField.hpp:24: instantiated from `void BitField<size>::set(Size) [with long unsigned int size = 16384u]' PrimeGenerator.hpp:86: instantiated from here RawArray.hpp:143: Fehler: »ASSERT« nicht deklariert (erste Verwendung dieser Funktion) RawArray.hpp: In member function `RawObject& RawArrayMemory<RawObject, size, onHeap>::operator[](Size) [with RawObject = AlignedMemory<16ul, 8ul>, long unsigned int size = 255ul, bool onHeap = false]': RawArray.hpp:144: instantiated from `Data& RawArrayImpl<Data, size, onHeap>::operator[](Size) [with Data = PrimeGenerator::Runner, long unsigned int size = 255ul, bool onHeap = false]' Stack.hpp:36: instantiated from `Data& Stack<Data>::peek() const [with Data = PrimeGenerator::Runner]' PrimeGenerator.hpp:97: instantiated from here RawArray.hpp:19: Fehler: »ASSERT« nicht deklariert (erste Verwendung dieser Funktion) RawArray.hpp: In member function `RawObject& RawArrayMemory<RawObject, size, onHeap>::operator[](Size) [with RawObject = AlignedMemory<16ul, 8ul>, long unsigned int size = 1048576u, bool onHeap = false]': RawArray.hpp:144: instantiated from `Data& RawArrayImpl<Data, size, onHeap>::operator[](Size) [with Data = Stack<BigPrimeGenerator::Runner>, long unsigned int size = 1048576u, bool onHeap = false]' Array.hpp:18: instantiated from `Data& ArrayImpl<Data, size, onHeap>::operator[](Size) [with Data = Stack<BigPrimeGenerator::Runner>, long unsigned int size = 1048576u, bool onHeap = false]' PrimeGenerator.hpp:132: instantiated from here RawArray.hpp:19: Fehler: »ASSERT« nicht deklariert (erste Verwendung dieser Funktion) RawArray.hpp: In member function `RawObject& RawArrayMemory<RawObject, size, onHeap>::operator[](Size) [with RawObject = AlignedMemory<4ul, 4ul>, long unsigned int size = 514ul, bool onHeap = false]': RawArray.hpp:144: instantiated from `Data& RawArrayImpl<Data, size, onHeap>::operator[](Size) [with Data = u32, long unsigned int size = 514ul, bool onHeap = false]' Array.hpp:18: instantiated from `Data& ArrayImpl<Data, size, onHeap>::operator[](Size) [with Data = u32, long unsigned int size = 514ul, bool onHeap = false]' BitField.hpp:24: instantiated from `void BitField<size>::set(Size) [with long unsigned int size = 16384u]' PrimeGenerator.hpp:86: instantiated from here RawArray.hpp:19: Fehler: »ASSERT« nicht deklariert (erste Verwendung dieser Funktion) make: *** [.outMakefile/PrimeGenerator.o] Fehler 1
(Ach wie hassen wir doch alle kryptische template-fehler)
-
füg doch mal include "assert.hpp" hinzu...
-
> tar xjf vlib.tar.bz2 > cd vlib > make mkdir .outMakefile echo keep > .outMakefile/keep g++ -Wall -Werror -pipe -fno-rtti -O3 -s -DNDEBUG -fomit-frame-pointer -ffast-math -fno-enforce-eh-specs -fmerge-all-constants -c -o .outMakefile/assert.o -MD assert.cpp cc1plus: warnings being treated as errors Error.hpp:6: Warnung: ‘class Error’ has virtual functions but non-virtual destructor assert.cpp:4: Warnung: ‘class AssertError’ has virtual functions but non-virtual destructor make: *** [.outMakefile/assert.o] Fehler 1
template<typename RawObject,Size size,bool onHeap>
Warum benutzt du dieses bool-Flag? Finde ich
(a) nicht sonderderlich verständlich. Wenn jemand nun so etwas sieht und die vlib nicht kennt, dann weiß er nicht was es bedeutet
Array<int,10,true> a;
(b) was ist wenn man nun in Shared Memory oder in irgend einem spezial Speicher allokieren will, daher würde ich wie in der stdlib Allokatoren vorziehen.
-
DrGreenthumb schrieb:
füg doch mal include "assert.hpp" hinzu...
in RawArray.hpp?
ist drin. seit ner stunde afair.ach, wie ich das hasse, daß der eine compiler das durchläßt und der andere da nen fehler meldet.
-
volkard schrieb:
DrGreenthumb schrieb:
füg doch mal include "assert.hpp" hinzu...
in RawArray.hpp?
ist drin. seit ner stunde afair.ach, wie ich das hasse, daß der eine compiler das durchläßt und der andere da nen fehler meldet.
hehe, mach mal einen monotone oder svn server auf
btw. für welchen Compiler testest du? GCC 4?
-
kingruedi schrieb:
Error.hpp:6: Warnung: ‘class Error’ has virtual functions but non-virtual destructor
klarer programmierfehler. ist raus.
template<typename RawObject,Size size,bool onHeap>
Warum benutzt du dieses bool-Flag? Finde ich
(a) nicht sonderderlich verständlich. Wenn jemand nun so etwas sieht und die vlib nicht kennt, dann weiß er nicht was es bedeutetdie vlib soll nicht nur replacement der standardlib sein, sondern ein paar sachen schon anders machen. da flag wird schon ein wenig deutlicher bei
template<typename Data,Size size=0,bool onHeap=size==0> class Array...
ich will, daß ein Array mit echt vielen elementen ganz von allein auf dem heap liegt und ein kleies Array ganz von allein auf dem stack. das war bei std::vector immer ein großes argernis, daß der zwingend new benutzt und entsprechend langsam für kleine mengen ist.
Array<int,10,true> a;
normalerweise schreibt der benutzer ja
Array<int,10> a;
und benutzt das flag eher nie.
(b) was ist wenn man nun in Shared Memory oder in irgend einem spezial Speicher allokieren will, daher würde ich wie in der stdlib Allokatoren vorziehen.
ich habe noch nie std::vector zusammen mit einem eigenen allokator verwendet. hab die allokatoren erstmal vertagt. mus noch viel besser werden, um die gescheit hinzukriegen. aber bedarf ist schon da. der primzahlenzähler ist mit eigenem allokator 20% schneller.
-
kingruedi schrieb:
hehe, mach mal einen monotone oder svn server auf
theoretisch hab ich ja einen. muß mir mal erzählen lassen, wie man sowas verwendet.
btw. für welchen Compiler testest du? GCC 4?
windows: ms toolkit 2005
windows: mingw (gcc 3.4.2)
linux: gcc 3.3.5-20050130
-
Bei mir gehts immer noch nicht...
mkdir .outMakefile echo keep > .outMakefile/keep g++ -Wall -Werror -pipe -fno-rtti -O3 -s -DNDEBUG -fomit-frame-pointer -ffast-math -fno-enforce-eh-specs -fmerge-all-constants -c -o .outMakefile/assert.o -MD assert.cpp g++ -Wall -Werror -pipe -fno-rtti -O3 -s -DNDEBUG -fomit-frame-pointer -ffast-math -fno-enforce-eh-specs -fmerge-all-constants -c -o .outMakefile/credits.o -MD credits.cpp g++ -Wall -Werror -pipe -fno-rtti -O3 -s -DNDEBUG -fomit-frame-pointer -ffast-math -fno-enforce-eh-specs -fmerge-all-constants -c -o .outMakefile/FileReader.o -MD FileReader.cpp g++ -Wall -Werror -pipe -fno-rtti -O3 -s -DNDEBUG -fomit-frame-pointer -ffast-math -fno-enforce-eh-specs -fmerge-all-constants -c -o .outMakefile/FileWriter.o -MD FileWriter.cpp g++ -Wall -Werror -pipe -fno-rtti -O3 -s -DNDEBUG -fomit-frame-pointer -ffast-math -fno-enforce-eh-specs -fmerge-all-constants -c -o .outMakefile/iostream.o -MD iostream.cpp g++ -Wall -Werror -pipe -fno-rtti -O3 -s -DNDEBUG -fomit-frame-pointer -ffast-math -fno-enforce-eh-specs -fmerge-all-constants -c -o .outMakefile/main.o -MD main.cpp g++ -Wall -Werror -pipe -fno-rtti -O3 -s -DNDEBUG -fomit-frame-pointer -ffast-math -fno-enforce-eh-specs -fmerge-all-constants -c -o .outMakefile/os.o -MD os.cpp g++ -Wall -Werror -pipe -fno-rtti -O3 -s -DNDEBUG -fomit-frame-pointer -ffast-math -fno-enforce-eh-specs -fmerge-all-constants -c -o .outMakefile/prime.o -MD prime.cpp g++ -Wall -Werror -pipe -fno-rtti -O3 -s -DNDEBUG -fomit-frame-pointer -ffast-math -fno-enforce-eh-specs -fmerge-all-constants -c -o .outMakefile/PrimeGenerator.o -MD PrimeGenerator.cpp swap.hpp: In function `void swap(Data&, Data&) [with Data = Size]': Stack.hpp:52: instantiated from `void swap(Stack<PrimeGenerator::Runner>&, Stack<PrimeGenerator::Runner>&)' PrimeGenerator.hpp:95: instantiated from here swap.hpp:6: Fehler: Abfrage des Elementes »swap« in »a«, das vom Nicht-Klassentyp »long unsigned int« ist make: *** [.outMakefile/PrimeGenerator.o] Fehler 1
Mit meinem i386-pc-linux-gnu-g++ gehts übrigens. Wird wohl was mit der größe von datentypen z tun haben...
-
ness schrieb:
Bei mir gehts immer noch nicht...
jup. momentchen.
-
jetzt müßte es gehen.
lag an den datentypen.
weil ich swap nicht mehr für alle typen angeboten hab, sondern nur noch explizit angebe, was geswapped werden kann, und weil ich swap für unsigned long noch nicht hatte, konnte er bei dir Size nicht swappen.
-
kingruedi schrieb:
hehe, mach mal einen monotone oder svn server auf
eigentlich würde ein script um wget reichen, das bescheidsagt, wenn sich die vhlib.tar.bz geändert hat.
-
volkard schrieb:
die vlib soll nicht nur replacement der standardlib sein, sondern ein paar sachen schon anders machen. da flag wird schon ein wenig deutlicher bei
Aber das Allokatoren Konzept finde ich schon ziemlich gut, da es flexibel und ohne Overhead ist. Man braucht es zwar selten, aber wenn man mal Speicher woanders anlegen will, dann ist man aufgeschmissen und es kostet ja keinen Overhead.
Aber true und false Flags sind leider nicht so eindeutig. Mach doch ein
enum { OnHeap=true, OnStack=false };
-
Was mir persöhnlich nicht gefällt ist, dass ASSERT eine Ausnahme wirft. Das schafft meiner Meinung nach viel mehr Probleme als es löst.
Zum Beispiel kann es in keinem Destruktor eingesetzt werden.
Desweiteren kann man mittels catch(...) die Assertion auch abfangen also ist es nicht mehr sicher, dass eine Assertion immer knallt.
Wenn eine Assertion fehlschlägt dann ist der Wurm in der Programlogik also ist es nicht sicher, dass die Destruktoren ihren Job erledigen. Sollten einer deshalb während dem Stackunwinding abstürtzen dann merkt man nicht mal, dass die Assertion fehlschlug.
Man weiß nichtmal von wo die Ausnahme flog und man fragt wie zum Teufel der Programfaden dahin gelangt ist. Die Assertion schlug ja nicht fehl und danach gibt es kein throw mehr.
Desweiteren kann es selbst richtige Programlogik als falsch erscheinen lassen. Beispiel:
Obj::Obj(){ ptr = new int; *ptr = 1; } void Obj::foo() { // Mach irgendetwas, dass *ptr 0 ist was es aber nicht sein sollte } void Obj::swap(Obj&other) { int*temp = this->ptr; ptr = other.ptr; ASSERT(*ptr != 0); other.ptr = temp; ASSERT(*other.ptr != 0); } Obj::~Obj() { delete ptr; // Ein Genuß wie das hier knallt }
Das eigentliche Problem ist zwar, dass foo auf 0 testen sollte, aber du weißt ja hoffentlich wie schnell man ein ASSERT vergessen hat. in swap hat man sich gedacht, dass ein zusätzliches ASSERT nie überflüssig ist und teste sobald ein Objekt wieder in einem funktionierenden Zustand ist. this ist korrekt beim ersten ASSERT, other noch nicht wird es aber am Ende von swap sein.
So nun hat foo aber gewütet und das erste ASSERT wirft eine Ausnahme, other bleibt deshalb korrupt. Nun kommt es zum doppelten Löschen im Destruktor. Der Debugger wird sich hier melden. Der Programmierer wird denken, dass ihm irgendwo ein Flüchtigkeitsfehler bei der Speicherverwaltung unterlaufen ist und diese überprüfen und dabei ist diese fehlerfrei.
Ganz unabhängig davon ist
#define CHECK(cond) if(cond);else raiseAssertError(#cond,__FILE__,__LINE__)
fehlerhaft. Beispiel:
namespace foo { void raiseAssertError(char const* cond,char const* file,int line); void bar() { CHECK(false); // Hier wird foo::raiseAssertError aufgerufen } }
Das müsste
#define CHECK(cond) if(cond);else ::raiseAssertError(#cond,__FILE__,__LINE__)
heißen.
Dann währe ein FAIL(), FAIL_MSG(msg), CHECK_MSG(what, msg), ASSERT_MSG(what, msg) sicher nicht verkehrt.
In addModUnguarded würde ich die Argumente noch mit einer Assertion überprüfen.
Ganz dumme Frage aber was bezweks du mit
inline void operator delete(void*,void*) throw(){ }
-
Ben04 schrieb:
Ganz dumme Frage aber was bezweks du mit
inline void operator delete(void*,void*) throw(){ }
der wird aufgerufen, wenn der entsprechende placement new eine excpetion wirft. ok, das tut er zwar nicht, aber weiß das auch der linker?
-
volkard schrieb:
template<typename Iterator> void sort(Iterator begin,Iterator end);
allerdings sofort probleme, denn die iteratoren können noch nicht zum beispiel op+(Iterartir,Size). das müßte dann nachgerüctet werden.
Das wär weniger das Problem, denke/hoffe ich, hab eh grad mit meinen LinkedList Iteratoren zu kämpfen. :p
Aber range-checked sind sie ja, oder hab ich's falsch verstanden?volkard schrieb:
Dauert dir aber wohl zu lange, bis ich da fertig wär.
kann man nicht wissen. ich brauche noch keinen. wenn ich einen brauche, schreib ich halt einen. wenn du vorher einen hast, sag bescheid.
Ok, ansonsten kann ich nur (kennst du wahrscheinlich schon, aber wurst) www.sortieralgorithmen.de empfehlen.
-
Ben04 schrieb:
Was mir persöhnlich nicht gefällt ist, dass ASSERT eine Ausnahme wirft. Das schafft meiner Meinung nach viel mehr Probleme als es löst.
aber es löst auch probleme. und zwar darf ja durch ein einfache arraygrenzenüberschreitung irgendwo nicht auf einmal die datenbank wo anders in nem inkonsistenten zustand gelassen werden.
Zum Beispiel kann es in keinem Destruktor eingesetzt werden.
jup. zur zeit hoffe ich, daß assertions in destruktoren was extrem seltenes sind.
Desweiteren kann man mittels catch(...) die Assertion auch abfangen also ist es nicht mehr sicher, dass eine Assertion immer knallt.
man darf eben AssertError nicht fangen, ohne es weiterzuwerfen, außer man ist die main().
Wenn eine Assertion fehlschlägt dann ist der Wurm in der Programlogik also ist es nicht sicher, dass die Destruktoren ihren Job erledigen.
da wäre ich mir nicht so sicher.
Sollten einer deshalb während dem Stackunwinding abstürtzen dann merkt man nicht mal, dass die Assertion fehlschlug.
jo. bisher kenne ich einen kritischen fall. wenn ein FileWriter destruiert wird und deswegen flush() aufruft und die platte voll ist.
Desweiteren kann es selbst richtige Programlogik als falsch erscheinen lassen. Beispiel:
... void Obj::swap(Obj&other) { int*temp = this->ptr; ptr = other.ptr; ASSERT(*ptr != 0); other.ptr = temp; ASSERT(*other.ptr != 0); } Obj::~Obj() { delete ptr; // Ein Genuß wie das hier knallt }
[/quote]
aua. nun könnte ich sagen, daß man assert wie ne ausgabe auch halten sollte, also auf keinen fall im exception-unsicheren teil veranstalten. das würde ich auch sofort, wenn ich mir sicher wäre, daß es klappt. aber die range checked iteratoren werfen ja auch. und das kann ja oft passieren, wenn man am wenigsten damit rechnet. ein ausweg wäre ne datei assertlog.txt, die zuätzlich geschrieben wird. in den seltenen fällen, die du anführtst, hätte man dann wenigstens noch ne chance, zu sehen, was los war.Das müsste
#define CHECK(cond) if(cond);else ::raiseAssertError(#cond,__FILE__,__LINE__)
heißen.
ok. ist gefixt.
In addModUnguarded würde ich die Argumente noch mit einer Assertion überprüfen.
ok. in allen Unguarded-sachen.
hab vor jahren nach exceptionwerfendem assert umgestellt und es war bisher immer prima. meyers schlägt das auch vor. normalerweise soll dieses assert, wenn der debugger an ist, auch noch __asm int 3; ausführen, was einen auf der fehlerzeile in den debugger wirft. damit kann man dann auch die schwierigen fälle sehr gut verfolgen. normalerweise, hält man einfach das programm an, wenn man den fehler repariert hat. ist ne kritische sache unten am leben, die ber dtor gerettet werden muss, sagt man dem debugger halt, er soll bis programmende laufen.
ich will es drauf ankommen lassen, ob die von die genannten probleme sich wirklich zeigen werden und lass ASSERT vorläufig werfen.
-
GPC schrieb:
Aber range-checked sind sie ja, oder hab ich's falsch verstanden?
ja, sind sie. das könnte recht praktisch werden, wenn man nen sortieralgo baut. bin mal gespannt.
-
volkard schrieb:
jetzt müßte es gehen.
lag an den datentypen.
weil ich swap nicht mehr für alle typen angeboten hab, sondern nur noch explizit angebe, was geswapped werden kann, und weil ich swap für unsigned long noch nicht hatte, konnte er bei dir Size nicht swappen.Ja, sowas hab ich mich auch gedacht...
Aber, was bezweckst du damit? Ich meine, zumindest primitivtypen könntest du doch normal swappen?namespace help { template<class T,bool simple_swap> struct sh { static inline void swap(T& a,T& b) { a.swap(b); }; }; template<class T> struct sh<T,true> { static inline void swap(T& a,T& b) { T tmp(a); a=b; b=tmp; }; }; }; template<class T> inline void swap(T& a,T& b) { help::sh<T,type_traits<T>::is_primitive||type_traits<T>::is_pointer>::swap(a,b); };
-
ness schrieb:
Aber, was bezweckst du damit?
daß jeder, der ne klasse baut, die swappen können soll, das auch anbieten muss. dabei garantiert er dann auch, daß swap exceptionsicher ist.
[/quote]Ich meine, zumindest primitivtypen könntest du doch normal swappen?[/quote]
jo. nix dagegen.namespace help { template<class T,bool simple_swap> struct sh { static inline void swap(T& a,T& b) { a.swap(b); }; }; template<class T> struct sh<T,true> { static inline void swap(T& a,T& b) { T tmp(a); a=b; b=tmp; }; }; }; template<class T> inline void swap(T& a,T& b) { help::sh<T,type_traits<T>::is_primitive||type_traits<T>::is_pointer>::swap(a,b); };
hab keine type_traits.
für pointer hab ich schontemplate<typename Data> inline void swap(Data*& a,Data*& b){ Data* tmp(a); a=b; b=tmp; }
was auch zu funktionieren scheint.
nu bin ich am überlegen, ob ich die primitiven typen lieber aufzählen sollte, oder ob ich meta-programming-monster baue.
vol umfang des codes sollte es ähnlich sein.