
Hi Thorsten, On Sat, Jun 27, 2009 at 11:48 AM, Thorsten Ottosen < thorsten.ottosen@dezide.com> wrote:
Christian Schladetsch skrev:
PS. Perhaps just porting ptr_container to use boost::container rather than
std::container would solve Roberts problem?
No. He needs to "install" his own new/delete with the container.
Isn't this called a stateful allocator? Which boost::container supports?
Hm. Is it? So construct() and destroy() would act as custom allocator/deleter?
No, the custom allocator would act as a custom allocator. Obviously I don't follow this. If you want to "install" custom new and delete into a container, isn't this best achieved by using a stateful allocator? If so, it seems the best want to support stateful allocators is to base ptr_container on boost::interprocess::containers (hopefully soon to be boost::containers) rather than std::containers. It seemed to me that Robert needed stateful allocators for ptr_containers. You said he didn't. But now you made clone_allocator stateful, but left the normal allocator stateless. I'm confused.
Anyway, let's say that all allocation is done with the supplied allocator via rebind<>. This is what you require to use ptr_container with monotonic allocators, right?
No. Monotonic works well with either stateless or stateful allocators. The problem was that I could not implement a sane clone_allocator for ptr_container, and I didn't know how anyone else would either. Now that you made clone_allocator stateful, I still can't pass it the containers allocator at constructon time. Why not make the parent allocator stateful, and pass it to a static clone method in a stateless clone_allocator? Doesn't that make more sense and solve more problems?
But how do you get objects into the ptr_container in the first place?
In a perfect world, I would pass a pointer to be added to a container of pointers: ptr_container<T> c; c.push_back(new T(..args..)); Then use value semantics of type T and not T * on the contained elements. But I realise that isn't how it works.
Do you intend users to write
container c; c.push_back( c.get_allocator().construct( c.get_allocator().allocate(sizeof(T)) );
No - why would they? That is what the container does internally. I am sure you are making a good point here, I just can't see it. All I need to make ptr_container work for me is to give the clone_allocator access to the parent container's allocator - preferably just by passing it to clone_allocator::clone rather than making it stateful. It makes sense to me that clones should be made using the parent container's own allocator, which it used to make the originals with in the first place. But then when you think that through, it seems that clone_allocator itself is a practically useless appendage. Unless you want clones to be made using a stateful sort-of allocator that does not model std::allocator, is different to the parent containers allocator, and you want to ensure that clones must be made using a different allocator to the parent container allocator. The obvious question then is: why you would want to do that, and how it is useful in any way? What would be useful is if ptr_container supported stateful v2 allocators based on boost::interprocess::containers, rather than stateless v1 allocators based on std::containers. Is this how you expect it to work for Robert and others?: struct my_stateful_custom_clone_allocator { ...state here, including some way to store a general allocator ... template <class U> U *clone(U const &X) { ...use the general allocator in this->state to make the clone of X... } }; ptr_container<T, my_stateful_custom_clone_allocator, my_custom_normal_allocator<T> > cont; my_custom_clone_allocator &alloc = cont.get_clone_allocator(); alloc.parent_allocator = cont.get_allocator(); alloc.... = ...; rather than: struct my_stateless_custom_clone_allocator { template <class U, class Alloc> U *clone(U const &X, Alloc &alloc) { // use alloc to make a clone of X } }; ptr_container<T, my_stateless_custom_clone_allocator, my_custom_normal_allocator<T> > cont; Having the users needing to dig into an otherwise private piece of machinery within the container itself - especially after it is created - seems really ugly. Isn't it better to do all the setup in the type and ctor for a ptr_container? I'm obivously missing something. Do you have any use-cases or examples that use a custom clone allocator with a ptr_container? Either stateless or stateful? I still think that the entire issue of cloning from base types is best put into a seperate, orthogonal system outside of ptr_container. However, I understand that you wanted to support it as a specific case for ptr_containers in the context of OO hierarchies. I also understand that you don't want to use copy-constructors to make a copy; there is no need to repeat either sentiment. And how do you pass constructor arguments to construct? Forwarding construction arguments is a general problem that is not limited to the std::allocator concept.
-Thorsten
Best, Christian