Boost logo

Boost :

From: Sam Partington (sam.partington_at_[hidden])
Date: 2006-01-06 04:09:42


> > It seems to me that the first has the disadvantage of making it
> > relatively easy to provide an incorrect cloner that allows slicing.
> > However this is relatively easy to avoid by making your hierarchy
> > noncopyable, (Perhaps a way around this is to remove the default
> > implementation of new_clone?)
>
> It's not very sensible to make the hierarchy copyable, because you
> can run into slicing in other places then.

Agreed, so why do we encourage copyable types by providing a default
new_clone that uses the copy constructor. It almost gives the
impression that that its a recommended way to do it. The only time
the default would be useful is when you are using the ptr_ containers
to store non-polymorphic types, probably for efficiency problems. Its
not so much of a burden to require the user to write new_clone in
those situations.

> As for the default, then I've been thinking about this too. It still
> won't catch that one missed a clone() function longer down the hiararchy.

No, but we can only help you so far. And like you say in a later post
a typeid based assert could help to avoid that when RTTI is enabled.

> > curve and strange inconsitencies for the user. i->first and i->second
> > isn't pretty, but we're used to it now, and I can't see the std
> > containers changing.
>
> This is not to fix the interface, but to hide direct write-access to the
> pointer.

How so? Could you not emulate it with a proxy? Or would the overhead
be too high? Perhaps this could go in the docs FAQ / rationale.

> > typename Container::value_type v = container.back();
> > container.pop_back();
> > return v;
> >
> > ?
>
> I don't think so. The first statement won't compile. Secondly, your
> types should not be copyable.

I see, but is value_type not T*, so I'm guessing then that back
returns a reference? Oh, it has to doesn't it, to match the
indirection semantics of the ptr_ containers. Fair enough. This does
compile :

template<class Container>
        typename Container::value_type f(const Container& container)
{
        typename Container::value_type v = &container.back();
        container.pop_back();
        return v;
}

But that wouldn't compile for a std container, and its quite apparent
that the code is taking the address of something and then popping it -
so I agree pop_back should stay as it is. It would be nice to have
something in the FAQ / rationale about why pop_back returns the popped
element.

> > The results are pretty much what you'd expect. shared_ptr performs
> > well on the copy test, cow_ptr performs very poorly. I think you can
> > read this as best/worst case scenario for COW.
>
> right. I'm a bit surprised that the worst case is so bad.
(snip)
> I guess it would make sense to repeat the test with different sizes of
> the containers. This is only for one size.

I was surprised too - I was expecting the cost of copying the object
to overshadow the overhead of the copy on write logic. Size of
container, and the object being stored, and the amount of mutating
done changes all this greatly.

(BTW I meant 100%-ish :-) I didn't see much point in working it out
exactly since the numbers depend entirely on the problem domain)

> I couldn't figure out what the type is either. I can figure out what you
> want with that type either; AFAICT, it has no use (so maybe it is not
> that serious it is not there).

I wanted to know the type to figure out whether the code fragment I
gave before would compile. If value_type had been a reference, or
back had returned a pointer then it would have compiled and would
return either a reference or a pointer to a deleted object.

> > Even better than that would be if ptr_map and etc.
> > listed ALL its members. This could presumably be automated?
>
> How?

Not easily, and I don't think the boost build process has the ability
to do things like this, but I was thinking along the lines of some
kind of embedded directives, parsed by a python/perl script. For
example the ptr_map might contain a directive like this, below its own
members :

<?inherit from="ptr_map_adapter"?>

Which would pull out all of the members documented in
ptr_map_adapter.html headed with "Inherited from ptr_map_adaptor".

This in turn would pull in any inherited things from
associative_ptr_container.html with a similar declaration.

I'd be happy to write a suitable script. The alternative would be to
copy+paste it all, but making changes to base class documentation
would be a maintainance nightmare.

Of course you may feel that its all too much effort and the user
should follow the hierarchy to find the member they want. Which would
be fair enough :-).

Sam


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk