|
Boost : |
From: Phil Nash (phil.nash.lists_at_[hidden])
Date: 2002-05-02 06:48:18
> "Phil Nash" <phil.nash.lists_at_[hidden]> wrote in message
> news:000001c1f1ab$32e848f0$700a0c0a_at_TimeMachine...
> > In which case, FWIW, I would add my voice of agreement that
> something like
> > shared_ptr could be the "standard" way to pass a shared pointer
> across a
> > published interface,
>
> I will try to convince you - and everybody - otherwise.
I'm open to debate :-) (rolls up sleeves...)
> > Andrei, put in that light does what am saying make more sense and
> sound reasonable now (I think it means I was agreeing with you more than I
> thought right from the start)?
>
> I don't have much time right now, and I plan to write a lenghty post
> on the subject "Binary compatibility of smart pointers: a red
> herring?" later - if ever. I am behind my sleep, and I have tons of
> homeworks and projects to worry about.
I know the feeling. I'd love to have been more in depth and thoroughly
researched in most of my postings too.
> I'll give some quick facts now.
>
> 1. Shared pointers allow you to change at runtime the function with
> which the pointer is destroyed.
>
> The main reason, it's been said, is to allow library writers to change
> that function without having to change the binary layout of the code.
I notice you bring "library writers" into this a lot, but, unless I missed
something earlier on (very possible) I thought we were talking about general
interfaces - including application level interfaces. That covers static and
dynamic libraries, in-process and out of process, whatever... and nobody is
proposing a single smart_ptr to cover *every* situation. Personally I am
just agreeing with the view that a sensible default that works the same way
in most situations - but allows you to fine tune *if there is a proven need*
is a good idea. IIRC you have said much the same yourself elsewhere.
Having said that, there does seem to be a camp that takes a slightlu
stronger approach, and maybe your comments are more directed at them.
> So the situation that's helped by keeping the function pointer in the
> body of shared_ptr is dynamic linking or changing the function that
> destroys a pointer at runtime. For helping this situation, all code
> must pay. I argue that the case is not common enough to warrant
> imposing such an overhead to all libraries that want to share
> pointers.
And I argue that the deleter function is only one case. What about
intrustive vs non-intrustive for example? Ok, I see you bring that up in the
context of your next point, but that's for a specific case...
> 2. shared_ptr has significant size and speed overhead for COM and
> CORBA-style smart pointers
I would say these are probably good candidates for deviating from the
complete default. It would also be nice to be able to specify a default to
be used in these situations (perhaps through your "ptr template" you suggest
elsewhere). Obviously we don't want to clutter the design space too much
with fixed definitions for specific points, but the more common the case the
more valuable the fixed (default) definition. COM and CORBA are surely
common enough.
> Refcounting COM and CORBA pointers is optimized already for proxy
> situation, so there's no reason to "reoptimize" it via another
> indirect call. That's a pessimization.
Or, looking at it another way, perhaps it's a premature optimisation to
avoid the default until you know that the benefit of consistency is
outweighed by the benefit of performance/ size.
Having said that, I do think that COM and CORBA deserve their own "default"
policy definition.
> I know that these are reasons enough for people I used to work with -
> and I believe for most COM (and CORBA) programmers - to stay away from
> shared_ptr for any COM work and use Microsoft's CComPtr<T> class which
> is designed for the exact task of managing COM pointers.
so boost::ptr::com<T> would be a nice replacement for that wouldn't it :-)
I think we concur on that point.
> 3. I believe that having a "default smart pointer type" is not such a
> good idea.
I disagree, but I think it is a matter of degrees. After all you yourself
have said that you decided on some sensible defaults for the Loki::SmartPtr
policies. If a "default smart pointer type" is not a good idea then what is
the point of Loki::SmartPtr<T> ?
This issue is surely not all-or-nothing.
Perhaps what you are really arguing against is whether those defaults should
be to defer to runtime policies (in mimicry of boost::shared_ptr). In which
case I lean towards the default-to-runtime view (for pointers that are
passed across interfaces at least) as it discouragues premature
optimisation, but certainly does not preclude such optimisation. Heretically
I would say that such optimisation is allowable in interfaces, but should be
kept to a minimum.
> (To generalize a bit, when I hear of this notion of "default type" I
> become wary. The Standard, for example, recommends vector as the
> "default container type". What do you mean, "default"? "I don't know
> what type to choose for this variable, so let it be float". What
> gives? Oh well.)
You would use vector unless you know you have reason to need the extra
features or complexity guarantees of one of the other containers instead.
You can, after all, do most (if not all) of what you can do with the other
containers with a humble vector. However, the case is weaker with the
containers because we have another abstraction - iterators. You rarely pass
containers across interfaces, but iterators into them.
Nonetheless, I'm sure the situation would be the same (maybe even clearer)
if we have std::container<T, complexity_policy, etc>. Then there would be
defaults for the policies given and std::container<T> would probably look
much like a std::vector<T> does now.
Because of the iterators abstraction I don't think this makes a very good
point of illustration, though. But I have no problem understanding what they
mean by "default" in this case (unless, I did misunderstand it, of course
:-s)
> If a library has to pass around COM pointers and pointers to non-COM
> objects, in my humble opinion, it's not a good idea to use the same
> smart pointer type for both. It's just a obstination to preserve a
> situation that brings no advantage to anyone. Give to the Caesar...
> you know. Use COM-tuned pointers for COM objects; use smart pointers
> tuned for your objects, for your objects. Make them syntactically
> uniform, and make them perform well for the objects they manage.
Agreed, in this case. I think the COM/ CORBA case is strong enough, not just
from the optimisation point of view, but also from the perspective that it's
probably quite useful to distinquish COM/ CORBA objects from other objects
by type. I would say that is not always the case and such cases should be
marked by their exclusivity, rather than lost in a proliferation of
differing policy choices for weaker reasons, or maybe no real reason at all.
> 4. shared_ptr is a point in smart_ptr's design space.
Yes, although maybe a blurred point... in a sense.
> I might start sounding like a broker record here, but shared_ptr's
> behavior is /one/ fixed design in a rich design space offered by a
> smart pointer based on policies. I can't understand how a design with
> a hardcoded set of decisions embedded inside of it can do better and
> more than a framework that grants you that specific design all right,
> in addition to many other useful designs.
I agree with that. But we are not talking about hardcoded decisions (at
least I am not) - just sensibly defaulted ones, along with a recommended
practice that you only "tweak" when you have identified a definite and
specific need to.
> 5. Syntactic convenience
>
> This is, in my humble opinion, the last bastion of hardcoded smart
> pointer designs. As I showed in my post "Proposal for easying
> smart_ptr usage within C++98", syntactic convenience can be brought
> within acceptable bounds (in my opinion) with inner typedefs: replace
> 'shared_ptr<T>' with 'ptr<T>::shared'.
Yes that looked interesting.
Despite my several objections above, I don't think we are too far out of
sync on this one. I don't claim to be representative of the cause that
Dietmar was championing, though. If Dietmar is around, perhaps he could make
an observation at this point?
> I'd love to write more on the subject, but look at the time...
Tell me about it! (although I am writing this one during the day, for a
change).
> Andrei the sleep-deprived one
[)o
IhIL... likewise.
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk