Boost logo

Boost :

From: Larry Evans (cppljevans_at_[hidden])
Date: 2006-08-31 17:28:06


On 08/31/2006 03:07 PM, Paul Mensonides wrote:
>>-----Original Message-----
[snip]
>>>smart pointer so that it doesn't require a double
>>>allocation.)
>>
>>I assume you mean one which doesn't use an intrusive
>>refcount, IOW, uses a "detached" refcount like the existing
>>shared_ptr? IOW, with the current shared_ptr, an one
>>allocation is for the pointed-to object, the other is for the
>>refcount.

> Yes, basically you have the smart pointer allocate the
> pointed-to-object itself as a data member of a struct that also
> contains the reference count. E.g.
 
> template<class T> class smart_ptr {
> // ...
> private:
> struct data {
> unsigned long rc;
> T value;
> } * p_;
> smart_ptr(data* p);
> };

> You need a forwarding contructor on the 'data' structure to directly
> initialize the 'value' member. You also need a forwarding function
> on whatever takes the arguments from clients--so the resulting
> syntax looks something like:
 
> smart_ptr<X> p = make_ptr<X>(a, b, 123);

> The make_ptr<X> function has to construct a 'smart_ptr<X>::data'
> object and initialize a smart_ptr with it and return that smart_ptr.

The above make_ptr<X> is close to the managed_ptr::
auto_overhead<X,ulong_rc> where:

  template<class>
  struct ulong_rc
  {
      unsigned long rc;
  };

and instead of:

  smart_ptr(data* p)
  
there would only be:

  smart_ptr(auto_overhead<T,ulong_rc>& a_auto)
  
IOW, auto_overhead is simply derived from auto_ptr with the pointee
being an instance of the managed_ptr::
overhead_referent_vals<ulong_rc,T>. IOW,
overhead_referent_vals<ulong_rc,T> corresponds to your
smart_ptr<T>::data. The reason for the elaborate overhead_referent_*
classes is to allow different smart_ptr policies, e.g. to allow strong
and weak pointers. The reason for disallowing:

   smart_ptr(overhead_referent_vals<ulong_rc,T>*)
   
is to never expose a raw pointer to the client.

> One problem of forwarding is arity (which can be more-or-less solved
> with code generation). The more stubborn problem with forwarding is
> temporaries. They cannot be bound to a non-const reference, and the
> template mechanism cannot deduce T as const U in a parameter of type
> T&. OTOH, non-temporaries don't have any problem deducing T as U or
> const U in a parameter of type T&.

Yeah, I had that problem which is why the a_auto above is not 'const &'.
I remember some attempt at a workaround, but can't remember the
details or even if it worked.

> Unfortunately, the only way to handle it transparently is to
> overload via cv-qualifier--which leads the the combinatorial
> explosion when multiple parameters are involved.

:(

>
>>the workaround implemented with the help of
>>managed_ptr_ctor_forwarder.hpp:
>>
>> http://tinyurl.com/o7zlg
>>
>>generates CTOR's of the form:
>>
>> template
>> < class VecOfTypes
>> >
>> ctor_this_type
>> ( VecOfTypes const&
>> , mpl::at_c<VecOfTypes,0>::type a0
>> , mpl::at_c<VecOfTypes,1>::type a1
>> , ...
>> , mpl::at_c<VecOfTypes,n>::type an
>> )
>> : ctor_base_type
>> ( a0
>> , a1
>> , ...
>> , an
>> )
>> {}
>>
>>IOW, the client has to specify the "signature" of the
>>ctor_base_type CTOR via a single VecOfTypes template arg to
>>the ctor_this_type CTOR. The justification for this was that
>>the client would have to know which ctor_base_type CTOR he
>>wanted anyway, so it would not be that much of a burden for
>>him to name it, indirectly, by supplying the "signature".
>

> I'm not sure why you need to add this into each class (rather than
> just to the smart-pointer-related interfaces).

Sorry I was unclear. This above is only needed for the auto_overhead
class. IOW, replace ctor_this_type with auto_overhead and
ctor_base_type with Referent from auto_overhead<Referent,Overhead>.
Of course it's a little more complicated, but that's essentially
what's happening with the MANAGED_PTR_CTOR_FORWARDER_OVERLOAD macro
invokation in the middle of the auto_overhead class definition.

> It may be that we're not talking about the same thing, but the
> smart_ptr facilities above could be designed without *any* intrusive
> requirements on the type pointed-to

Likewise, auto_overhead does not have *any* intrusive requirements
since the only allocation is for
overhead_referent_vals<ulong_rc,pointee_type>.

> and without *any* manual listing of argument types by the client.
> Granted, you can only support a fairly low number of parameters
> (larger if you ignore volatile).
 
And this, AFAICT, is the advantage of make_ptr vs. auto_overhead.
IOW, auto_overhead does have to supply, as mentioned in my previous
post, the signature (VecOfTypes in the above code) of the desired
"target" CTOR.


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