
intrusive_ptr(T * p, bool add_ref = true); Effects: if(p != 0 && add_ref) intrusive_ptr_add_ref(p);.
Postconditions: get() == p.
[...]
Right, so you can't call it a bug if the implementation does exactly as stated. ;-)
Consider: X * x = new X ; { intrusive_ptr<X> px(x) ; } Here, x is destroyed, and rightly so. Now (same example as yesterday): X * x = new X ; { intrusive_ptr<X, false> px(x) ; } Here, x is destroyed *too*, even though the additional "false" was supposed to mean: "please, don't mess-up with refCounts at all, *I* have everything under control. Nope. If preserving the current intrusive_ptr semantics is paramount (as I kind of sense it is now), some confusion could be avoided by renaming "addRef" to something less ambiguous or suggestive. The question is not _how_ it does what it does (it does it by adding 1 to the refCount, or not, hence that dubious name) but _what_ it does when that argument is set to false. If it is difficult to find a name to describe _what_ it does in such a case (which might point to a poorly understood use-case) then the next best thing is probably a catch-all word such as "standard", which, by negation (=false) means a clear warning: "What you're about to do when setting ``standard'' to false is, by definition non standard, and you *must* understand so and so to avoid being caught with your pants down"
I'm pretty sure that a shared_ptr-based port can closely approximate the original,
"approximate"! That's the key. I don't want to "approximate". Either I find a way to *completely* hide the smart pointer modulo: - the initial "new X" - "on the fly" packaging of ``this'' when required __from within__ (ie when passing ``this'' to some other unrelated method of some other class that requires an _envelope_ as argument and not a _body_, since my whole API, once translated from Java, will only expose _envelopes_) or I will go the painful Boehm's road and use conservative GC.
but a custom smart pointer would probably be a better choice for idiomatic Java code.
I wish you are right! I'll give myself all the evenings and week-ends until the end of May. If I fail to come up with something that is acceptable, I'll go conservative, because "Real artists ship!" :-)
As for intrusive_ptr, its main strength is that it has the size of a pointer.
HoHum ...scoped_ptr shares this "exclusive" strength ...
Adding a boolean would likely meet serious opposition.
Never mind the opposition. Is that the right thing to do or not? Since I don't understand your use cases, I just can't comment.
Your requirements are very interesting, however, and point to a shared/intrusive hybrid along the lines of:
template<class T> class intrusive_ptr_2 { T * px_; intrusive_ptr<Object> pn_;
// insert smart pointer boilerplate here ;-) };
I'm not sure I understand. pn_ is supposed to perform the refCounting part, and px_ is supposed to be the actual _body_ ?
It's an intrusive pointer that's close to shared_ptr in expressive power; you can use it to point to a subobject, for example.
Extending intrusive_ptr to accommodate the above along the lines of
template<class T, class U = void> class intrusive_ptr { T * px_; U * pn_; // not present when U == void };
could be feasible.
I'm lost. I don't see how this relates to the problem of providing an indirection ("pointer") construct such that, once you've have written xxxx_ptr<X> p(new X) ; you're done, once and for all, never asking _user_ code to deal with the intricacies of your xxxx_ptr *implementation*. When you come to think of it, a garbage collector is meant to provide _automatic_ garbage collection, not semi-automatic, or half-manual. Compounding the problem of memory management with additional idiosyncratic problems is not going to free that one remaining brain cell out of a total of 7, that holds the whole universe under your current consciousness level. A bad guarantee is worse than no guarantee at all. IMHO :) Many thanks -- JFB