|
Boost : |
From: Kevin Spinar (spinarkm_at_[hidden])
Date: 2006-07-10 13:28:15
On 7/09/06, Matt Calabrese <rivorus_at_[hidden]> wrote:
> As we established, the types being created
> aren't really smart pointers but are actually smart objects.
If that is true, then is the following form really correct?:
clone_ptr<Base> p(new Derived);
Wouldn't it be more-correct to write:
Derived d;
clone_ptr<Base> p(d);
On 7/10/06, Matt Calabrese <rivorus_at_[hidden]> wrote:
> On 7/9/06, Kevin Spinar <spinarkm_at_[hidden]> wrote:
> >
> > First, let me make an assumption. Most people who would use
> > clone_ptr<T> would have T be an abstract base class with no member
> > variables. Now, how would someone write a sorting predicate with
> > that? Double dispatch is a solution, but probably not a desirable
> > solution. Or is my assumption incorrect?
>
>
> Right, for most uses it would be difficult to implement. Still, as tough as
> it is, comparing the pointer value simply isn't correct, so I wouldn't even
> consider that an option at all. If you agree, then the only options I can
> think of are either some form of forwarded operation, or no definition at
> all. It's true that neither one seems great, so maybe there is a better
> solution out there, but I personally don't see it. The only reason I am
> leaning towards some form of forwarded solution is that in the case that
> comparison operators actually are implemented, it allows the user to work
> with sorted containers and algorithms without having the explicitly specify
> a comparison predicate. To be honest, I don't mind either way as I
> personally don't have much of a need for the comparison functionality.
Ok, perhaps comparison forwarding would be the best solution.
> > Another alternative would be to throw an exception upon using * or ->
> > on a default-constructed clone_ptr, though that would add yet more
> > overhead to those operators.
>
>
> True, and I personally do not enjoy working with operations that can
> potentially throw or dereference null pointers,
> especially with such seemingly simple and common
> operations. Writing code is much easier when errors and exceptions are
> avoided entirely by design
> if possible.
I suppose the best solution would be what you suggested earlier:
"perhaps a default child type were specified via a template argument
to the smart object type template itself (which would default to the
first type if left unspecified)."
On 7/10/06, Peter Dimov <pdimov_at_[hidden]> wrote:
> clone_ptr (or copy_ptr, or copy_on_write_ptr) is a better name from a
> "marketing standpoint" than poly_obj, because it's more recognizable.
Opinions? Accurate name or recognizable name?
> Regarding:
>
> template<class Y, class Alloc> clone_ptr(Y * p, Alloc); // Y must be
> complete
>
> The template parameter name 'Alloc' implies a standard allocator. This is
> pretty confusing; you should rename it to CloneAlloc if you really want to
> use the 'CloneAllocator concept'.
Indeed and I'll admit there is other naming and documentation issues I
should address before releasing this.
> The alternative is to just take a standard allocator.
The reasoning to have a a clone allocator concept (
http://www.boost.org/libs/ptr_container/doc/reference.html#the-clone-allocator-concept
) is to allow for cloning of objects which don't have public copy
constructors or to allow people to do something other than copy
construct.
> You might also want to not ignore the actual argument and make an
> effort to support stateful allocators (although this is somewhat more
> complicated, it is also considerably more useful.)
I agree. ptr_container's clone allocators don't seem to be meant for
keeping stateful allocators (their functions are static). Perhaps it's
time to break away from ptr_container's clone allocator and have my
own clone allocator concept.
>
> The copy on write semantics are problematic from an usability standpoint.
> Consider this code:
>
> // thread 1
>
> int x1 = p->x;
>
> // thread 2
>
> int x2 = p->x;
>
> Is this legal (assuming that both threads use the same pointer p)? You can't
> tell without looking at p. If it's const, or points at const, the code is
> legal. The problem is that there are no visible mutating operations in the
> code; it looks innocent enough as all we do is read p->x, right?
I intended to add mutexes and thread safety to the code. Is there
more to this issue than that? Though I suppose adding locks to a
getter function isn't that desireable efficiency-wise.
> One option is to always return a const from -> and * and provide a separate
> mutable accessor.
Not exactly the most desirable solution, but it seems many things in
this aren't turning out as I originally expected. Of course, if we go
back to clone-on-copy semantics, this won't be an issue.
Kevin Spinar
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk