Boost logo

Boost :

From: Paul Mensonides (pmenso57_at_[hidden])
Date: 2006-08-31 16:07:16


> -----Original Message-----
> From: boost-bounces_at_[hidden]
> [mailto:boost-bounces_at_[hidden]] On Behalf Of Larry Evans

> > Regarding what the generated code is doing (as opposed to what the
> > generator code is doing), the major problem with forwarding without
> > language support is that it is a combinatorial problem--rather than
> > linear. I.e. you really need various combinations of const and-or
> [snip]
>
> Ouch! Do you know of anyone working on a compiler to solve
> this forwarding problem?

I know this is one of the things being tossed around in the committee, but I
don't know the likelihood that of acceptance or if it has already been accepted.
Dave would know more.

> > In any case, it is still reasonable up to 5 parameters if you're
> > ignoring volatile. I know that Dave implemented this kind of
> > forwarding for an operator new workalike that returned a smart
> > pointer. (With perfect forwarding, you can design a
> reference-counted
> > 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. If so, then this is what I was trying to do with:

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.

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

Regards,
Paul Mensonides


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