Boost logo

Boost Users :

Subject: Re: [Boost-users] PolyCollection requiring copyable
From: Thorsten Ottosen (tottosen_at_[hidden])
Date: 2017-10-05 15:22:24

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:
> 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.

> 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


Boost-users list run by williamkempf at, kalb at, bjorn.karlsson at, gregod at, wekempf at