In C ++ 2003, the dispenser model is broken, and there really is no right solution. For C ++ 2011, the distributor model has been fixed, and you can have instances for each distributor that propagate to contained objects (unless, of course, you want to replace them). Generally, for this to be useful, you probably want to use the dynamically polymorphic type of distributor, for which std::allocator<T>
not required by default (and normally I would expect it to not be dynamically polymorphic, although this may be the best implementation choice). However, [almost] all the classes in the C ++ standard library that take up memory allocation are templates that use the allocator type as the template argument (for example, IOStreams are an exception, but usually they do not allocate any interesting amount of memory to guarantee adding dispenser support).
In a few of your comments, you insist that distributors really have to be global: this is definitely not true. Each type that supports the allocator saves a copy of the provided allocator (at least if it has instance level data, and if not, there is nothing that could be saved, for example, in the case of the default allocator using operator new()
and operator delete()
). This actually means that the distribution mechanism provided to the object must adhere as long as it uses the active dispenser. This can be done using a global object, but it can also be done using, for example, reference counting or linking a distributor to an object containing all the objects to which it is defined. For example, if each "document" (I think XML, Excel, Pages, any structure file) transfers the distributor to its members, the distributor can live as a member of the document and be destroyed when the document is destroyed after its contents are destroyed. This part of the distributor model should work with classes pre-C ++ 2011 if they also accept a dispenser argument. However, in pre-C ++ 2011 classes, the allocator will not be passed to contained objects. For example, if you provide a allocator for std::vector<std::string>
, C ++ 2011 will create std::string
using the allocator assigned by std::vector<std::string>
, appropriately converted to work with std::string
s. This will not happen with pre-C ++ 2011 allocators.
To actually use distributors in a subsystem, you really need to pass them, either explicitly as an argument to your functions and / or classes, or implicitly using objects that support the distributor, which serve as context. For example, if you use any of the standard containers as [part of] the transferred context, you can get the used allocator using its get_allocator()
method.