E. Gladyshev wrote:--- Peter Dimov <[EMAIL PROTECTED]> wrote:
In this context, an allocator parameter is only an excuse for implementors to avoid doing the necessary work to make function<> useful out of the box. "You can always use a custom allocator", right?
Considering the variety of real life requirements and platforms, it is not practical to make a library that work out of the box.
The danger in that statement is that it looks obvious, but it's not. It is true in some sotuations (not as frequent as is generally believed) and false in others, and when it doesn't really hold but is axiomatically accepted as truth, it serves as exactly the excuse I was talking about. "It is not practical to make a library that works out of the box, so users should be happy that they are getting a library that can be made to work with a "small" additional investment. Of course we'll gladly sell you the additional bits and pieces."
That's an invalid argument, since the STL containers give you a default value for the allocator argument, which makes containers work out of the box, and the default is "for free."
It is interesting to compare the C++ approach with the Java approach to memory management in this context. C++ "pragmatically" accepts that the shipped malloc is often inadequate and provides several types of hooks that you can use to work around the problem. Java does not. If the JVM has a broken memory manager you lose and can do nothing about it. This gives C++ a short term advantage, but in the long term Java wins, since JVM implementors have no choice but to optimize their memory managers till they are blue in the face.
Bugs that have no workarounds are always fixed first. :-)
You're making a worse assumption here. Who says that the need for a different allocator class is because the default one has-bugs/is-slow/plain-old-sucks? There can be an orthogonal need for a different allocator class, which no improvement on the default one can fix.
In this case, the Java user is 100% screwed since they can't change the memory manager at all. Or at least, can't change the manager without changing it everywhere. (Allocator policies allow mix-and-match.)
That is why STL has allocators. In one project, if STL did not have allocators, I would have to implement my own containers. I was so happy that I didn't have to do it.
So far my experience indicates that people only bother with allocators when std::allocator is inadequate, i.e. slow. Your case may, of course, be different. It happens sometimes.
At least a library should be consistent about memory management.
This is an arbitrary requirement.
Taking a quick look at the Standard Library, all of the direct containers that use dynamic memory take an allocator argument, except for the maligned std::valarray<>.
The issue is how consistent boost is about it (STL is very consistent)? It seems that boost doesn't have any idea about how it manages its memory.
A fairly aggressive way to state it, but I see your point. It is true that Boost does not impose any requirements on how the particular libraries obtain and manage their memory. But you need to realize that "do nothing" can be a conscious design decision. Lack of strict requirements means more freedom for the implementations to do what they consider best.
This last sentence is probably why std::valarray<> keeps its memory policy private.
As an example, consider a hypothetical std::vector<T> that does not have an allocator argument and "has no idea how it manages its memory." Do you see the implications of that?
1. vector::resize and vector::reserve can now realloc in place since they can talk directly to the memory manager.
2. On many implementations, vector<T> can now be made as efficient as new T[], since new T[] often stores the equivalent of size() and capacity() anyway to allow delete[] to do the right thing.
For example if a boost class X uses std::list, does it have to expose the std::list<> allocator or should it use the standard
std::allocator<>. template<typename T> struct X { std::list<T> l; };
OR
template<typename T, typename A=stl::allocator<T> > struct X { std::list<T, A> l; };
Which definition is more friendly to boost?
The correct answer depends on X's interface. Your toy example is not a good illustration as this kind of "interface" is rarely seen.
Is it allowed for a boost libarary to use global new/delete? If so, should it be documented?
Boost libraries are allowed to use the C++ language without restrictions.
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost