Boost logo

Boost :

From: Andy Glew (glew_at_[hidden])
Date: 1999-11-10 10:13:25

> I very much do like being able to say
> a = b.
> Oh, yeah, you already get that with shared_ptr<T> assignment
> (one of my smart_ptrs is a degenerate pointer that always allocates
> on assignment - I call it coa_ptr<T>, copy on access.)

Excuse me, I misspoke.

With Boost's shared_ptr<T>,
a = b
has pointer semantics:
a->some_field = x
=> b->some_field = x.

To get value semantics, you need to do copy-on-write
on any potentially writeable dereference.

With manual proxies, the user may know of all writing methods.

With oblivious proxies in a library, your only choice is to
do the copy on write on any non-const lvalue producing
method. I.e.
    smart_ptr<T>::operator smart_ptr<T>& () {
        ...break sharing, copying object pointed to
Unfortunately, this seems to have several problems:
(1) it doesn't work (at least with GCC 2.95)
(2) even if it did, there are a heck of a lot of places
    where a non-const ref is needed
    (often due to insufficient use of const)
(3) since even a const ref may be cast and written to,
    it is not 100% safe.

These last two considerations motivated me to define
a non-shared coa_ptr<T>, where "coa" means "copy on
access". Such a coa_ptr always has value semantics;
whenever assigned to, it does something like
    coa_ptr<T>& coa_ptr<T>::operator= ( const T& that ) {
        if( this->ptr == that.ptr ) return *this;
        if( this->ptr != 0 ) delete this->ptr;
        this->ptr = that.ptr->clone();
        return *this;
I.e. I gave up on copy-on-write, since there seem to be
too many potentially writeable places.
I.e. a coa_ptr<T> is the antithesis of a shared_ptr<T>.

All that a coa_ptr<T> does is provide a convenient
place for holding run-time polymorphic values, with
proper scopiing and ownership - and it dos this without
any of the funny ownership semantics of auto_ptr<T>.
STL containers of coa_ptr<T> are safe.

coa_ptr<T> don't have any of the sharing advantages
of shared_ptr<T> or auto_ptr<T>. But, for polymorphic
objects where each of the polymorphs is fairly simple,
copying on each access yields a very convenient holder
for polymorphic values.
Thus, as described earlier, I start down the slippery slope.
Vanilla coa_ptr<T> has pointer semantics and syntax, even though
what it points to is unshared. You must say 
    *a == *b
rather than 
    a = b
But, if you want to put coa_ptr's in STL containers and use STL
algorithms on it, it is very convenient to make
     a == b
have value semantics.
And so, for a < b, ...

Boost list run by bdawes at, gregod at, cpdaniel at, john at