Is the motivation for the design of XMemory documented anywhere?
There appear to be some basic flaws in its design.
In Item 22 of his new book: Exceptional C++ Style, Herb Sutter (the chair of the C++ standards commitee) gives some useful guidelines for overloading new:
1) If you provide any class-specific new, always also provide specific plain (no-extra-parameters) new.
2) If you provide any class-specific new, then always also provide class-specific in-place new.
3) If you provide any class-specific new, then consider also providing class-specific nothrow new in case some users of your class do want to invoke it; otherwise, it will be hidden by other class-specific overloads of new.
1) is satisfied by XMemory. XMemory provides a non-standard new:
void* operator new(size_t size, MemoryManager* memMgr);
but also provides an overrided version of plain new:
void* operator new(size_t size);
2) is not satisfied by XMemory. Although a comment in the code claims that the non-standard new overrides placement new (in-place new in Sutter's words), this is not the case. Global placement new has the signature:
void* operator new(std::size_t size, void* ptr) throw();
The second argument is a void pointer not a MemoryManager pointer.
3) is not satisfied, but this is unlikely to be a problem in practice as nothrow new is not very widely used and probably not even supported by some compilers.
The reason why the failure to satisfy 2) is a problem is alluded to in 3). Defining a class-specific new hides all of the global versions of new. In particular this means placement new cannot be used with XMemory objects. Furthermore, placement new is often used to implement standard library containers - the library shipped with MSVC++ being a notable example. In practice, this means that containers such as vector are unusable with objects derived from XMemory. This was a problem for me when trying to create a vector of XMLUri objects (I don't see any sensible reason why such objects shouldn't be stored in a standard vector).
The fix is to add a definition of placement new to the class definition and simply forward it to the global placement new:
void* operator new(std::size_t size, void* q) throw() {return ::operator new(size, q);}
The corresponding delete operator should also be defined in case an exception is thrown during construction:
void operator delete(void* p, void* q) throw() {::operator delete(p, q);}
This can be hidden for the broken Borland compiler as already done for:
void operator delete(void* p, MemoryManager* memMgr);
Technically (according to the C++ standard) the <new> header should be included at the top of the file <XMemory.hpp>. In practice this can be omitted, as can the std:: qualification on size_t and the throw specifications.
It might be argued that by default XMemory derived objects should never be constructed by calling placement new. If this is the intention (something I would disagree with) then a dummy private placement new could be given, as with the hidden constructors and assignment operator.
Another question is how XMemory objects are supposed to behave in the presence of operator new[]. Currently, no operator new[] is defined, and hence the global version will be called. Is this the intention?
IMO forwarding functions for the global placement new and delete should definitely be added to XMemory.hpp. At any rate, I would suggest that the design goals of XMemory should be documented somewhere.
Sam
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]