Boost logo

Boost :

From: Thorsten Ottosen (tottosen_at_[hidden])
Date: 2006-01-05 09:20:49


Sam Partington wrote:
> (Incidentally David you can disable the ADL warning in the project, or
> on the command line and they go away, quite why they don't with
> #pragma I don't know :-) )
>
> It seems to me that this discussion is actually three orthogonal discussions.
>
> 1. How should cloning be implemented.
> Current implementation :
> A clone function which defaults to copy constructor (if accessible)
> for the static type of the container. Overridable using ADL.
>
> Alternative implementation:
> Use the copy constructor for the static type of the pointer passed in
> (which may be a more derived type than the static type of the
> container).
>
> 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.

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.

> 2. Should ptr_ containers differ in interface from std containers.
>
> I've only just recently had a proper look at the ptr containers, and I
> do find the differences somewhat disconcerting. The map iterator
> dereferencing for example, is not what one is used to STL containers
> would expect. I think it will cause most people to stumble when they
> first start to use it. I can see the temptation to 'fix' interface
> problems in the std containers, but that comes at a cost of a learning
> 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.

> pop_back also is somewhat surprising, I haven't really thought this
> through, but could an innocent user in generic code write something
> like this and get unexpected results. (assume an exception free
> environment)
>
> 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.

> 3. Should ptr_vector support copy on write semantics. Or could boost
> use a cow smart pointer?
>
> All of the performance comparisons shown so far that aren't affected
> by cow show nearly identical results. This is understandable since
> they are all implemented with the same container underneath.
>
> To test the copy on write behaviour more accurately, I changed the
> copy test so it mutated all of the objects. And I added shared_ptr to
> the types tested.
>
> Adding shared_ptr tests how a multithreaded cow ptr would behave if no
> mutations were to occur - some marshalling has to be done, some ref
> count twiddling, but no copying. Which makes it a better comparison
> against the ptr_vector which obviously copies all its objects.
>
> container populate copy
> operator[] iterator*
> std::vector<copy_ptr<Shape> > 2.52 s 2.53 s 1.06 s 1.08 s
> boost::ptr_vector<Shape> 0.64 s 2.61 s 1.09 s 1.08 s
> std::vector<cow_ptr<Shape> > 1.20 s 4.75 s 1.13 s 1.14 s
> std::vector<boost::shared_ptr<Shape> > 1.38 s 0.17 s 1.09 s 1.09 s
>
> 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.

> Best case copy on write performs 90% quicker.
> Worst case copy on write performs 100% slower.

well, almost

I guess it would make sense to repeat the test with different sizes of
the containers. This is only for one size.

> Like all situations like this you have to pick and choose the tool
> based on your needs.
>
> Sam
>
>
> PS
> I don't find the docs terribly easy to follow. Finding what a member
> means navigating each concept and base class until you find what you
> want. And working out the class hierarchy is not always that straight
> forward.
>
> For example, I wanted to find out the exact type of
> ptr_map::value_type. So I went to the ptr_map page, which has no
> members. And not even an obvious link to tell me which of the 4 "See
> also" pages is the next in the chain.

> Since ptr_map_adaptor is the
> base class I selected that. ptr_map_adaptor has no base class, so I
> assume that of the 4 "see also" links I probably want
> associative_ptr_container, as it sounds like it ought to be the next
> in line. When I get there I still don't have a value_type, but now I
> can see I probably want to look on the reversible_ptr_container page,
> where sure enough I find it.
>
> That would have been a lot easier if each class page listed the
> hierarchy and its place in it, rather than just listing them in a "See
> also" section.

not a bad idea.

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

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

How?

-Thorsten


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