Den 05-10-2017 kl. 13:30 skrev Joaquin M López Muñoz via Boost-users:
El 05/10/2017 a las 10:08, Thorsten Ottosen via Boost-users escribió:
Thorsten, regarding Boost.PolyCollection I've given a thought or two to the request that copy/assignment of elements be externalized to a configurable traits class:
http://www.boost.org/doc/html/poly_collection/future_work.html#poly_collecti...
and I'm not sure how/whether this can be done. The typical copy interface of a virtual hierarchy is through some clone() member function like this:
virtual base* clone()const;
which is BTW what you adopt in Boost.PointerContainer. The problem with this is that clone() not only constructs the derived object but also allocates memory for it, which is against Boost.PolyCollection approach, where memory is allocated through the collection's allocator and passed to construction code.
Right. I have thought about using the allocator to allocate all memory, but did not find it worth the trouble for ptr_container.
This implies the cloning interface should look like:
// OOP member function virtual void construct(void *p)const; // p alocated/aligned OK for derived
// As embodied in the copy traits void construct(void* p,cont derived& x){x.construct(p);}
which doesn't seem like OOP usual practice. In particular, I don't see how clone() can be used (without changing the OOP code) to implement copy_traits::construct. Thoughts on this?
Well, this is not trivial. First of, can we assume that the class hierarchy supports clone() in some form? If not, then you can use e.g. ptr_vector even without knowing the number of objects in advance, though you can't deep copy the container. And one can use PolyCollection as you outlined above with throwing move/copy operations (though here we need to know the size). So let's assume the hierarchy has some notion of clone(). Then it must have /protected/ copy-constructors (at least that would be the easiest and safest way to do it, possibly just using = default). If it has that, then there should be nothing wrong with having /protected/ move operations. Now if it has those copy/move operations internally, can't we just grant PolyCollection access to it? friend class boost::poly_collection::access; it needs to be defined in every class in hierarchy (except perhaps the root of the hierarchy), but so does the virtual function that clones (or constructs). I would rather do that compared to seeing stuff like void* in the class. There is a difference though: in PolyCollection reference stability can be broken when the segments resize or erases elements and not just when the /actual/ element is erased (deleted) ... this holds even for moves. So one has to be a little more careful of handing out base* objects to other pieces of code. So, returning to your actual question: can we do anything without changing/adding something to the hierarchy? I don't see how that could work either. Nor how an existing clone() would help (because it mixes memory and copy-construction as you said). There is no free lunch ... kind regards Thorsten